小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
摘要
本次分享面试题专题均为自己21届校招时通过牛客以及自己面试遇到的问题,答案均为自己理解整理,如果有错误,请麻烦评论指出,万分感谢,如对您有所帮助,请交出您的三连或者点赞也是爱♥
Redis 的 hash 底层说一下
底层主要有四个部分组成,分别是dictType(类型,不咋重要),dictht(哈希表),dictEntry(哈希条目),dict(字典)
字典dict里存了两个哈希表dictht , 用于处理rehash过程 , 哈希表的扩展和收缩
dict(字典)是对hash进行简单的封装,其中type和private是为了实现字典多态而设置,当字典中存放着不同类型的值,dict底层中还有rehash索引,当字典中没有rehash时,默认为-1
table(表)是一个dictEntry类型的数组,用于真正存储数
size表示数组大小,sizemark用于计算索引位置,且总是等于size-1,used表示dictht中已有的节点数量
扩展问:rehash是什么?
与java中的hashmap类似,当redis中的dict进行扩容或者缩容,会发生rehash,具体为:
新建一个哈希表,一次性将所有节点进行rehash,然后复制到新的哈希表相应的位置之后,释放掉原有的hash表,持有新的表,这个过程时间复杂度是O(n),而redis用的单线程,难以承受这个时间复杂度,因此rehash使用的是渐进式rehash,一点点搬迁
redis的扩容和缩容?
扩容:当 hash 表中元素的个数等于第一维数组的长度时,就会开始扩容,扩容的新数组是原数组大小的 2 倍。不过如果 Redis 正在做 bgsave,为了减少内存页的过多分离 (Copy On Write),Redis 尽量不去扩容 (dict_can_resize),但是如果 hash 表已经非常满了,元素的个数已经达到了第一维数组长度的 5 倍 (dict_force_resize_ratio),说明 hash 表已经过于拥挤了,这个时候就会强制扩容。
缩容:当 hash 表因为元素的逐渐删除变得越来越稀疏时,,Redis 会对 hash 表进行缩容来减少 hash 表的第一维数组空间占用。缩容的条件是元素个数低于数组长度的 10%。缩容不会考虑 Redis 是否正在做 bgsave