vlambda博客
学习文章列表

接上文:深度剖析不一样的Redis架构设计


04 Redis高性能设计


Redis是单线程的吗?

Redis的单线程主要是值Redis的网络IO和键值对读写是由一个线程完成的,这也是Reids对外提供键值存储服务的主要流程。但是Redis的其他功能,比如持久化,异步删除,集群数据同步都是由额外的线程执行的。


Redis单线程为什么还能这么快?

每秒的话,差不多可以支持小10万的并发,这已经是一个很恐怖的数据了。

因为他的所有数据都是在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能消耗。正因为Redis是单线的,所有要小心使用Redis的命令。对于那些耗时的命令(比如keys),一定要谨慎。


Redis单线程是如何处理那么多并发客户端的连接?

Redis的IO多路复用:Redis利用Epoll来实现IO多路复用,将连接信息和事件放在队列中,一次放到文件事件分派器,事件分派器将事件分发到事件处理器。


  


05 Redis核心设计原理

Redi作为key-value存储系统,数据结构如下:(盗图了)


一个Redis实例对应多个DB,一个DB对应多个key,key一般是string的,后面的value是RedisObject,不是说value就是string,list,map这些,而是说这些类型,都被Redis封装成一个叫RedisObject,具体是哪个类型?是用指针的方式来向具体的哪个类型。(盗图了)

  1. RedisBD结构

    Redis没有表的概念,Redis实例所对应的DB以编号区分,DB本身就是key的命名空间。比如:user:wengyifei作为key的值,表示在user这个命名空间下id为wengyifei的元素,类似于user表中id=wengyifei的行。

  2. SDS字符串

    Redis是用C语言来实现的,在C语言中,String这个类型,其实就是一个char数组,比如char data[] = "xxx\0",但是,客户端往Redis发送set命令,是可以发送任意的字符串的,是没有校验的,所以假如我们发了一个字符串XX\0xx,那么\0后面的xx是不会读的,只会读前面的xx。所以Redis自己实现了一个string叫sds,sds中记录了一个len和一个char buf[],len用来记录buf的长度,比如char buf[] = "xxx\0xx",那么len的长度就是5,sds中还有一个比较重要的属性就是free,表示还剩余多少。free是通过改变len来计算,比如"xxx1234"改成"xxx123456",那么会按照(len+addlen) * 2 =18来扩容,这个时候len就变成了9,free就是18-9也就变成了9。

    例如:

    char buf[] = 'xxx1234'改成'xxx123456'//这里的buf是柔性数组

    free:12 变成 free:10

    len:8     变成 len:10


    Redis设计SDS字符串有什么好处?

    1.二进制安全的数据结构

    2.提供了内存预分配机制,避免了频繁的内存分配

    3.兼容C语言

    4.有单独的统计变量len和free,可以方便的得到字符串长度,这样就避免了读取不完整的风险。