哈希对象的编码可以是 ziplist
或者 hashtable
。
ziplist
编码的哈希对象使用压缩列表作为底层实现, 每当有新的键值对要加入到哈希对象时, 程序会先将保存了键的压缩列表节点推入到压缩列表表尾, 然后再将保存了值的压缩列表节点推入到压缩列表表尾, 因此:
举个例子, 如果我们执行以下 HSET 命令, 那么服务器将创建一个列表对象作为 profile
键的值:
redis> HSET profile name "Tom" (integer) 1 redis> HSET profile age 25 redis> HSET profile career Programmer1
如果 profile
键的值对象使用的是 ziplist
编码, 那么这个值对象将会是图 8-9 所示的样子, 其中对象所使用的压缩列表如图 8-10 所示。
另一方面, hashtable
编码的哈希对象使用字典作为底层实现, 哈希对象中的每个键值对都使用一个字典键值对来保存:
举个例子, 如果前面 profile
键创建的不是 ziplist
编码的哈希对象, 而是 hashtable
编码的哈希对象, 那么这个哈希对象应该会是图 8-11 所示的样子。
编码转换
当哈希对象可以同时满足以下两个条件时, 哈希对象使用 ziplist
编码:
- 哈希对象保存的所有键值对的键和值的字符串长度都小于
64
字节; - 哈希对象保存的键值对数量小于
512
个;
不能满足这两个条件的哈希对象需要使用 hashtable
编码。
注意
这两个条件的上限值是可以修改的, 具体请看配置文件中关于 hash-max-ziplist-value
选项和 hash-max-ziplist-entries
选项的说明。
对于使用 ziplist
编码的列表对象来说, 当使用 ziplist
编码所需的两个条件的任意一个不能被满足时, 对象的编码转换操作就会被执行: 原本保存在压缩列表里的所有键值对都会被转移并保存到字典里面, 对象的编码也会从 ziplist
变为 hashtable
。
以下代码展示了哈希对象因为键值对的键长度太大而引起编码转换的情况:
# 哈希对象只包含一个键和值都不超过 64 个字节的键值对 redis> HSET book name Mastering C++ in 21 days redis> OBJECT ENCODING book ziplist # 向哈希对象添加一个新的键值对,键的长度为 66 字节 redis> HSET book long_long_long_long_long_long_long_long_long_long_long_description content # 编码已改变 redis>hashtable"
除了键的长度太大会引起编码转换之外, 值的长度太大也会引起编码转换, 以下代码展示了这种情况的一个示例:
# 哈希对象只包含一个键和值都不超过 个字节的键值对 redis> HSET blah greeting hello world" OBJECT ENCODING blah # 向哈希对象添加一个新的键值对,值的长度为 68 字节 redis> HSET blah story many string ... many string ... many string ... many string ... many"
最后, 以下代码展示了哈希对象因为包含的键值对数量过多而引起编码转换的情况:
# 创建一个包含 512 个键值对的哈希对象 redis> EVAL for i=1,512 do redis.call('HSET',KEYS[1],i,i) end" 1 numbers (nil) redis> HLEN numbers (integer) OBJECT ENCODING numbers # 再向哈希对象添加一个新的键值对,使得键值对的数量变成 513 个 redis> HMSET numbers keyvalue OK redis> # 编码改变 redis>"
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。