Redis 学习笔记 03:字典
一、介绍
字典又称为符号表、关联数组或映射,是一种保持键值对的抽象数据结构。它综合了数组和链表的优点,是这两种数据结构的折中,内置于各种高级语言。在 redis 中广泛使用,作为底层结构对数据库做增删改查等操作。
二、数据结构
字典相关数据结构:
eg:包含三个键值对的哈希表
三、哈希算法
Redis 计算哈希值和索引值的方法如下:
四、哈希冲突
1、产生原因:
当有两个或以上数量的键被分配到了哈希表数组的同一个索引上面时,我们称这些键发生了冲突(Collosion)。
2、哈希冲突的解决方法:
redis 采用链地址法解决哈希冲突。采用单链表连接哈希冲突的键值对,这样做的好处:
(1)不必要求分配连续的大片空间
(2)可以将分散的空间利用起来
使用链表解决 k1 和 k2 的冲突问题,如图所示:
3、节点的添加方法
redis 里面采用头插法进行节点的添加,主要是从效率考虑。头插法的时间复杂度为 O(1)。
五、Rehash
1、哈希因子
哈希因子又称为负载因子,即为哈希表的使用率。load_factor = ht[0].used/ht[0].size;
2、哈希表的收缩和扩展
为了让哈希表的负载因子维持在一个合理的范围之内(主要是为了保证哈希表的利用率,减少空间浪费)。当哈希表保存的键值对数量太多或者太少时,程序需要对哈希表的大小进行扩展或者收缩。
3、哈希表收缩和扩展的步骤:
1)为字典 ht[1]哈希表分配空间
①扩展:ht[1]>=ht[0].used*2*2^n
②收缩:ht[1]<=ht[0].used*2^n
2) 将保存在 ht[0]中的所有键值对重哈希到 ht[1]上,并将键值对放到 ht[1]指定位置。
3)当 ht[0]所有的键值对都迁移到 ht[1]后,释放 ht[0],并将 ht[1]设置为 ht[0],然后为 ht[1]创建一个空白哈希表,为下一次 rehash 做准备。
4、扩展和收缩的时机
扩展:
1)当前没有执行 BGSAVE 或者 BGREWRITEAOF 命令,且哈希表的负载因子大于等于 1
2)当前正在执行 BGSAVE 或者 BGREWRITEAOF 命令,且哈希表的负载因子大于等于 5
收缩:
当哈希表的负载因子小于 0.1 时
5、哈希表收缩和扩展的方案
哈希表的扩展和收缩的并不是一次性、集中式完成的,而是分多次、渐进式的完成。(主要避免对服务器性能造成影响)
rehash 的步骤:
1)为 ht[1]分配空间,让字典同时持有 ht[0]和 ht[1]两个哈希表
2)字典维持索引计数器变量 rehashidx,设置为 0 表示 rehash 工作正式开始
3)rehash 期间,每次对字典添加、删除、查找、更新等操作时,除了指定操作外,还会顺带将 ht[0]哈希表在 rehashidx 索引上的所有键值对 rehash 到 ht[1]上,rehash 完成后,rehashidx 属性的值加一
4)当 ht[0]所有键值对都被 rehash 到 ht[1]上时,将 rehashidx 设置为-1 表示 rehash 完成。
相关图例演示:
1、渐进式 rehash-开始
2、渐进式 rehash-进行中
3、渐进式 rehash-结束
版权声明: 本文为 InfoQ 作者【架构精进之路】的原创文章。
原文链接:【http://xie.infoq.cn/article/dc7aba52326d0ffbfa201094a】。文章转载请联系作者。
评论