Redis之字典

Redis的字典的底层实现是用哈希表。

/* This is our hash table structure. Every dictionary has two of this as we
 * implement incremental rehashing, for the old to the new table. */
typedef struct dictht {
    dictEntry **table;
    unsigned long size;
    unsigned long sizemask;
    unsigned long used;
} dictht;

table是一个数组指针,每一个数组成员是一个dictEntry*,每一个dictEntry都是一个键值对,size是table的大小,sizemask=size-1,大小掩码,而used是哈希表总共有的键值对。因为哈希表对于简直哈希值的冲突解决是链地址法,每一个dictEntry都有一个next指针,用来实现链表。

typedef struct dict {

    dictType *type;
    void *privdata;
    dictht ht[2];
    int rehashidx; /* rehashing not in progress if rehashidx == -1 */
    int iterators; /* number of iterators currently running */
} dict;
一般的字典会有两个哈希表,目的是为了进行rehash,type用于制定一些特殊的操作,比如哈希函数,比较函数等。

不同用途的对象,type不尽相同,dictCreate时传入了指定的dictType,比如集合setDictType。

随着操作的不断执行,为了让哈希表的负载因子维持在合理的范围内,Redis会自动对哈希表进行扩展和收缩,之前为啥有两个哈希表,就是用来rehash用的。

主要步骤如下:

1.  为ht[1]分配足够的空间,一般都是2的n次方>=ht[0].used

2. 把ht[0]上的键值对映射到ht[1]的哈希表;

3. 交换两个哈希表,释放原来的ht[0]。

值得注意的是,哈希表的负载因子会和BGSAVE和BGREWRITEAOF有关。不在这些操作是,负载因子负载因子大于等于1,否则负载因子大于等于5,负载因子used/size.另一方面,负载因子小于0.1也会执行rehash。

一般情况下,字典的rehash不是一次性做完的,而是在每次主循环tick的时候,rehash部分key到ht[1],所以又一个rehashidx用于记录当前rehash的进度;而rehash期间,对字典做的操作会在两个哈希表中操作。

删改查会同时在两个哈希表中执行,增操作会在ht[1]中进行。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值