第4章 字典
Posted ashoftime
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第4章 字典相关的知识,希望对你有一定的参考价值。
4.1基本结构
Redis中的字典和Java中的HashMap结构类似,但Redis中字典不等于哈希表。
每一个哈希表dictht结构中存储着一个指向数组的指针,该数组用于存储键值对,除此之外存储着数组的长度、已经存储的键值对的数量、用于计算索引的哈希掩码。
数组中每个节点的结构也和Java中HashMap类似,存储着key-value对以及用于解决哈希冲突的next指针
之所以说字典不等于哈希表,除了因为字典结构中还封装了一些操作哈希表的函数外,还因为每个字典中保存了两个哈希表,即dict结构中的ht[2]成员。一般情况下使用ht[0]作为字典中使用的哈希表,只有当渐进式rehash的时候才会使用he[1]。
4.2 哈希算法
首先根据key值采用MurmurHash算法计算出hash值,该算法的优点是即使输入是存在一定规律性也可以保证计算出的哈希值尽可能平均,这很符合redis的应用场景。其次用hash值结合hash掩码计算出index。
4.3 解决冲突
拉链法解决哈希冲突,和HashMap一样采用头插法。
4.4 rehash与渐进式rehash
4.4.1 什么时候需要rehash以及新数组的大小分配
当没有执行BGSAVE或者BGREWRITEAOF命令且负载因子大于等1或者正在执行且负载因子大于等于5时,执行rehash。可见是在保证安全的情况下如果数组里放了太多的元素,会降低查询的效率。扩容是大小也和HashMap类似,如果是扩容操作那么就是第一个大于等于ht[0].used*2的2的n次幂,HashMap是每次扩大两倍,这里是根据已经使用的节点来决定扩容后的大小。
4.4.2 渐进式
redis作为一个对读写速度要求高的内存数据库,如果在扩容的时候暂停对外服务是不符合业务场景的。Redis中的扩容策略是每次当查询、插入、删除操作定位到某个节点的时候,顺便把他搬到新的数组即ht[1]上,并且当转义成功后trehashindex加一。这种策略的好处第一是提高了效率,避免额外开启线程用于扩容,第二是没有中断Redis的服务,新的hash操作仍然可以在ht[0]上进行。
在渐进式扩容期间删除 查找 更新会在两个数组同时进行,这三种操作都需要先定位到具体的节点即都有一个查找过程,查找的时候首先在ht[0]上找,如果没有找到再去ht[1]上寻找。插入操作只会在ht[1]上执行。这种策略保证ht[0]的节点只会越来越少。
如果客户端没有对Redis进行操作,Redis也会使用定时任务对dict进行扩容。
以上是关于第4章 字典的主要内容,如果未能解决你的问题,请参考以下文章