Redis设计与实现3 哈希对象( ziplist hashtable)

Redis设计与实现3 哈希对象( ziplist hashtable),第1张

ziplist 编码的哈希对象使用压缩列表作为底层实现, 每当有新的键值对要加入到哈希对象时, 程序会先将保存了键的压缩列表节点推入到压缩列表表尾, 然后再将保存了值的压缩列表节点推入到压缩列表表尾, 因此:

保存了同一键值对的两个节点总是紧挨在一起, 保存键的节点在前, 保存值的节点在后;

先添加到哈希对象中的键值对会被放在压缩列表的表头方向, 而后来添加到哈希对象中的键值对会被放在压缩列表的表尾方向。

举个例子, 如果我们执行以下 HSET 命令, 那么服务器将创建一个列表对象作为 profile 键的值:

另一方面, hashtable 编码的哈希对象使用字典作为底层实现, 哈希对象中的每个键值对都使用一个字典键值对来保存:

Redis 的字典使用哈希表作为底层实现, 一个哈希表里面可以有多个哈希表节点, 而每个哈希表节点就保存了字典中的一个键值对。

Redis 字典所使用的哈希表由 dicth/dictht 结构定义:

table 属性是一个数组, 数组中的每个元素都是一个指向 dicth/dictEntry 结构的指针, 每个 dictEntry 结构保存着一个键值对。

size 属性记录了哈希表的大小, 也即是 table 数组的大小, 而 used 属性则记录了哈希表目前已有节点(键值对)的数量。

sizemask 属性的值总是等于 size - 1 , 这个属性和哈希值一起决定一个键应该被放到 table 数组的哪个索引上面。

图 4-1 展示了一个大小为 4 的空哈希表 (没有包含任何键值对)。

哈希表节点使用 dictEntry 结构表示, 每个 dictEntry 结构都保存着一个键值对:

key 属性保存着键值对中的键, 而 v 属性则保存着键值对中的值, 其中键值对的值可以是一个指针, 或者是一个 uint64_t 整数, 又或者是一个 int64_t 整数。

next 属性是指向另一个哈希表节点的指针, 这个指针可以将多个哈希值相同的键值对连接在一次, 以此来解决键冲突(collision)的问题。

举个例子, 图 4-2 就展示了如何通过 next 指针, 将两个索引值相同的键 k1 和 k0 连接在一起。

Redis 中的字典由 dicth/dict 结构表示:

type 属性和 privdata 属性是针对不同类型的键值对, 为创建多态字典而设置的:

ht 属性是一个包含两个项的数组, 数组中的每个项都是一个 dictht 哈希表, 一般情况下, 字典只使用 ht[0] 哈希表, ht[1] 哈希表只会在对 ht[0] 哈希表进行 rehash 时使用。

除了 ht[1] 之外, 另一个和 rehash 有关的属性就是 rehashidx : 它记录了 rehash 目前的进度, 如果目前没有在进行 rehash , 那么它的值为 -1 。

图 4-3 展示了一个普通状态下(没有进行 rehash)的字典:

在Redis中,由于它对实时性要求更高,因此使用了渐进式rehash

当有新键值对添加到Redis字典时,有可能会触发rehash。Redis中处理哈希碰撞的方法与Java一样,都是采用链表法,整个哈希表的性能则依赖于它的大小size和它已经保存节点数量used的比率。

比率在1:1时,哈希表的性能最好,如果节点数量比哈希表大小大很多的话,则整个哈希表就退化成多个链表,其性能优势全无。

上图的哈希表,平均每次失败查找需要访问5个节点。为了保持高效性能,在不修改键值对情况下,

需要进行rehash,目标是将ratio比率维持在1:1左右。

Ratio = Used / Size

rehash触发条件:

rehash执行过程:

Redis哈希为了避免整个rehash过程中服务被阻塞,采用了渐进式的rehash,即rehash程序激活后,并不是

马上执行直到完成,而是分多次,渐进式(incremental)的完成。同时,为了保证并发安全,在执行rehash

中间执行添加时,新的节点会直接添加到ht[1]而不是ht[0], 这样保证了数据的完整性与安全性。

另一方面,哈希的Rehash在还提供了创新的(相对于Java HashMap)收缩(shrink)字典,当可用节点远远

大于已用节点的时候,rehash会自动进行收缩,具体过程与上面类似以保证比率始终高效使用。

当哈希对象可以同时满足以下两个条件时, 哈希对象使用 ziplist 编码:

1、大的方向,redis是内存数据库,独立进程;map是java的数据类型

2、redis支持五种数据类型:string,list,hash(字典),set(集合),zset(有序集合)。java map和redis的hash对应,当然各自包含的方法不同

3、redis可以做主存,也可做缓存。

以上就是关于Redis设计与实现3 哈希对象( ziplist /hashtable)全部的内容,包括:Redis设计与实现3 哈希对象( ziplist /hashtable)、redis 和 java map的区别、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9722069.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-01
下一篇2023-05-01

发表评论

登录后才能评论

评论列表(0条)

    保存