REDIS字典(dict)

来源:互联网 发布:微信支付php源码 编辑:程序博客网 时间:2024/05/21 09:53
REDIS用字典来实现键值的空间, 底层是由动态哈希来实现; 字典的结构如下面的图
  1.  在字典中有两个哈希桶来实现哈希的扩展; 在没有对哈希进行扩张和rehash的情况下, 只有ht[0]来保存数据库的键值; 在对哈希表进行扩展和rehash时,首先会将哈希桶扩大2倍,挂到ht[1]的哈希桶下面,并将rehashidx置为0(表示开始从哈希桶的第一个桶开始进行rehash),然后逐渐将ht[0]哈希表上的数据转移到ht[1]上。
  2.  REDIS对哈希表进行rehash不是一次完成的,而是逐渐的对哈希表进行rehash的操作, REDIS的实现是在添加记录时,对哈希表进行步值是1的rehash(即每添加一条记录,对一个哈希桶(slot)做一次rehash的操作);
  3.  REDIS启动的一个定时任务来判断是否需要对hash表进行resize操作, 如果需要resize(哈希表的使用率小于10% : used/size < 10%), 就需要减少哈希桶的数量; 并进行rehash的操作; 即使没有对表进行resize的操作, 如果主动rehash打开(activerehashing); 也会进行rehash的操作, 这种方式的rehash一般是已每步100slots的速度进行rehash的;不过一般是每次定时任务执行中在1毫秒内以100步为单位进行, 每执行100步, 就判断是否超过1毫秒,如果超过就不再进行rehash了。
  4. 在哈希表进行rehash的过程中, 对表的操作要同时处理ht[0]和ht[1]两张表, 一般插入是只需对ht[1]操作就可以; 查找,删除就需要对两张表进行操作。
  5. 当节点rehash完毕后, 就需要将ht[1]指向的哈希桶赋给ht[0],ht[1]作为下一次哈希桶扩展时用。
typedef struct dict
{
    // 特定于类型的处理函数
    dictType *type;
    // 类型处理函数的私有数据
    void *privdata;
    // 哈希表(2个)
    dictht ht[2];
    // 记录 rehash 进度的标志,即正在对哪个桶节点做rehash,值为-1 表示 rehash未进行
    int rehashidx;
    // 当前正在运作的安全迭代器数量
    int iterators;
} dict;