当键或值很大时,为什么redis hash会从ziplist转换为hashtable?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当键或值很大时,为什么redis hash会从ziplist转换为hashtable?相关的知识,希望对你有一定的参考价值。

关于redis中哈希的数据结构有两个配置:hash-max-ziplist-entrieshash-max-ziplist-value

很容易理解它应该在条目太多时转换为哈希表,因为它会花费太多的时间来获取命令。

但是为什么当值很大时它会转换为哈希表?据我所知,由于ziplist条目中有一个“length”字段,如果一个条目是1位或100位,则无关紧要,只需移动整个条目即可获得下一个条目。

答案

为了向前和向后遍历,doubly linked list必须为每个条目保存两个指针(即64位机器上的16个字节)。如果条目数据很小,比如8个字节,则内存效率非常低:数据只有8个字节,而额外的指针则需要16个字节。

为了解决这个问题,ziplist使用两个variable length encoded数来代替两个指针,并将所有条目保存在连续的内存中。在这种情况下,如果所有条目值都小于64字节,这两个variable length encoded数字只需要2个字节(请纠正我,如果我错了)。这非常有效。但是,如果条目数据非常大,比如1024字节,这个技巧将不会节省太多内存,因为条目数据的成本更高。

另一方面,由于ziplist以紧凑的方式将所有条目保存在连续的内存中,因此几乎每次写入操作都必须进行内存重新分配。那是非常低效的CPU。编码和解码那些variable length encoded数量也需要CPU。

因此,如果条目数据/值很小,您可以使用ziplist来实现内存效率。但是,如果数据很大,则不会获得太多的增益,同时会花费大量的CPU时间。

以上是关于当键或值很大时,为什么redis hash会从ziplist转换为hashtable?的主要内容,如果未能解决你的问题,请参考以下文章

在 Java 中向 HashMap 添加空键或值有啥用?

如何检查Map中是不是存在键或值?

查找数组的嵌套对象中是不是存在键或值

不能将 Nil 用于 PFObject 的键或值

将枚举映射到键或值的类型

如何从 json 列中获取键或值数据