Redis字典结构数据的rehash过程
Redis字典的数据实现方式是使用哈希表。
先解释一下Redis字典中负载因子的概念,负载因子描述字典容量的负载程度,它的计算公式为:
负载因子
=哈希表已保存节点数量
/哈希表大小
Redis中哈希表与java中的HashMap
长得一样样的,HashMap
里动态扩容的机制在Redis的字典里也存在。Redis的字典不但能扩容,还能减容,而且在实现方式上与HashMap
有很大的不同。
哈希表扩展收缩条件
- 扩展
- 一般情况下哈希表负载因子大于1
- 服务器在执行
BGSAVE
或BGREWRITEAOF
命令,且哈希表负载因子大于5
- 收缩
一般情况下哈希表负载因子小于0.1
执行rehash的步骤
假设需要调整的哈希表ht[0]
- 新创建一个哈希表
ht[1]
,为新表分配空间,此时字典同时持有ht[0],ht[1]
两个哈希表 - 在字典中维持一个计数器变量
rehashidx
,初始值为0,表示开始rehash工作 - 在rehash期间,对字典的所有增删改查操作都会同时操作两个哈希表,目的是将
ht[0]
中的健值对重新hash到ht[1]
对应位置上,操作完成后rehashidx
加1 - 随着操作的进行,当
ht[0]
所有健值对迁移完毕后,rehashidx
设置成-1,表示rehash完成。释放ht[0]
,将ht[1]
设置成ht[0]
,并创建一个空哈希表,为下次rehash做准备。
可以看出,Redis字典的rehash过程不是一次性的,而是渐进的。这种设计当然是基于性能上的考虑,防止哈希表过大,Redis单线程rehash会导致所有客户端长时间无法使用。
扩展示例
- 准备开始rehash
- rehash第1个健值对
- rehash第2个健值对
- rehash第3个健值对
- rehash第4个健值对
- rehash完成
以上内容来自黄健宏《Redis的设计与实现》