Redis字典总结
Redis字典采用哈希表作为底层实现。
typedef struct dictht{ //哈希表数组 dictEntry **table; //哈希表大小 unsigned long size; //哈希表大小掩码,用于计算索引值 //总是等于size-1 unsigned long sizemask; //哈希表已有节点数量 unsgined long used; }dictht;
table指向dicEntry数组。
typedef struct dictEntry{ //键 void *key; //值 union{ void *val; uint64_tu 64; int64_ts 64; }v; //指向下一个哈希表节点,形成链表 struct dictEntry *next; } dictEntry;
其中next是用于在链地址法中使用,用于解决冲突。
typedef struct dict { //类的特定函数,其中第一个函数为哈希函数,将key转换成unsigned int dicType *type; //私有数据,作为特定函数的参数 void *private; //哈希表 dictht ht[2]; //rehash索引 //当rehash不在进行时,为-1 int rehashidx; }dict;
ht属性用于rehash。当哈希表的元素过多或者很少,会触发哈希表的扩容或者收缩,具体的时机与哈希表的负载有关(当前哈希表中的元素个数除以哈希表大小)。
当哈希表新插入元素而触发扩容时,首先会先为ht[1]申请两倍的ht[0]的空间,将新元素先插入ht[1],再从ht[0]中拿出rehashidx++对于的所有键值元素,重新计算键的哈希值后插入ht[1]。之后每次插入,查询,更新,删除都会导致ht[0]的一个rehashidx++对应的所有键值被转移到ht[1]。直到所有元素都转移到ht[1]中,再将ht[1]的内容拷贝到ht[0]并释放ht[1]。(这种方法称为渐进式rehash,java中的哈希表需要扩容时是直接将哈希表转换成红黑树)。