概述
redis中字典是最为频繁的一种复合型数据结构,除了hash结构本身用到字典外,redis本身就是一个由key,value的全局字典。
组成结构
//代码来自redis深度历险
struct dictht{
//二维 第一维是数组,第二维是链表(当hash取模时如果索引是相同的时候,则放到链表中--键冲突)
dictEntry** table;
//第一维数组的长度
long size;
//hash表中的元素个数
long used;
}
struct dictEntry{
void* key;
void* value;
//下一个entry
dictEntry* next;
}
操作
查找
redis运行hget时候,会对键进行hash取哈希值,然后与一维数组长度进行求余找到对应的索引位置,然后进行遍历链表找出数据
扩容
redis一维数组的长度不会一直不变,他会在满足hash表中元素的个数等于第一维数组的长度的时候就进行扩容,扩容为原来的两倍。但是如果redis正在bgsave,redis就尽量不去扩容,除非达到了第一维数组的5倍,这个时候就强制性扩容
rehash
扩容后由于第一维长度改变了,原来的数据需要进行rehash(简单一句话就是数据重新放),redis采用的是渐进式rehash,就是两个hash结构(一个新的一个旧的),旧的hash向新的进行迁移,在查询的时候会两个都进行查询,知道最后一个元素过去,旧hash数据进行回收处理。(redis自己也会定时进行rehash)
ps:为什么扩容或者缩容(简单来说就是第一维数组长度变了)就需要数据重新rehash?因为原来的数据放哪个索引位置是根据键的哈希值与第一维长度数组长度求余找到对应索引位置的,如果求得索引值相同,则放到链表中。
缩容
当元素的个数小于数组长度的10%,则进行缩容(不会考虑是否正在bgsave)
ps: bgsave指的是将当前内存数据,fork一个子进程持久化到磁盘(这一个操作就是RDB),后续写一个持久化补充下。
本文来自于redis深度历险,redis设计与实现,redis官方文档等待总结出来的,有什么不足请谅解,最后还是大家有空去去读下钱文品的redis深度历险这本书很给力的。