Redis 的设计与实现——数据结构实现之(二)链表与字典

链表      

首先Redis中存在的抽象结构为List,而链表是其一种实现方式,当list元素较多或者元素都为比较长的字符串时,采用链表作为底层实现。此外,链表还用在Redis服务器保存客户端状态、发布与订阅功能等等。

       在Redis中,链表是双向链表,其Node结构定义如左图,List的定义如右图:

观察得知,Redis中链表的特点如下

  1. 无环(头节点的pre指向null,尾节点的next也指向null)
  2. 具有头指针和尾指针,找表头和表尾的时间复杂度都是O(1)
  3. 双端
  4. 多态(由于多态的存在,使得链表可以保存不同类型的值并正常处理)
  5. 带有链表长度len

字典

       Key-value键值对,key独一无二,Redis的数据库就是用这种数据结构实现的,使用哈希表来实现,其中哈希表节点定义如左图所示,哈希表整个的定义如右图所示:

 

Hash节点的next指针用来链接同一个hash值的元素(链地址法解决冲突,添加到表头O(1)

下图是整个字典的实现,其中type用于指示键值对的类型,是为了创建多态字典,Redis为用途不同的字典配置不同的类型函数,具体如右图所示:

 

Redis采用MurmurHash2算法来计算hash值

Rehash操作

  1. 为hash[1]表分配空间:
    1. 如果执行扩展操作,则分配为超过hash[0].used*2的最小2^n;
    2. 如果执行收缩操作,则分配为超过hash[0].used的最小2^n;
  2. 将hash[0]上所有元素rehash到hash[1]上
  3. 释放hash[0],将hash[1]置为hash[0],在hash[1]上新建一个空白表

那么到底啥时候进行Rehash扩容呢?

  1. 服务器目前没在BGSAVE 或则BVGEWRITEAOF,且hash表的负载因子>=1;
  2. 服务器目前在BGSAVE 或则BVGEWRITEAOF,且hash表的负载因子>=5;
  3. 缩容是负载因子<0.1时

渐进式Hash

       在字典中维护一个rehashIdx属性,在rehash期间,每次进行更新、删除、查找、添加时,除了进行原有操作外,额外还将hash[0]中的rehashIdx对应的项rehash到hash[1]中去,然后将rehashIdx+1;直到所有都移动完毕,rehashIdx恢复-1。

注意,在rehash期间,所有的添加操作都在hash[1]上进行,查找、更新、删除则要从两个表都进行。

      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值