当哈希对象可以同时满足以下两个条件时, 哈希对象使用 ziplist 编码:
哈希对象保存的所有键值对的键和值的字符串长度都小于 64 字节; 哈希对象保存的键值对数量小于 512 个;不能满足这两个条件的哈希对象需要使用 hashtable 编码。
注意:这两个条件的上限值是可以修改的, 具体请看配置文件中关于 hash-max-ziplist-value 选项和 hash-max-ziplist-entries 选项的说明。
对于使用 ziplist 编码的列表对象来说, 当使用 ziplist 编码所需的两个条件的任意一个不能被满足时, 对象的编码转换操作就会被执行: 原本保存在压缩列表里的所有键值对都会被转移并保存到字典里面, 对象的编码也会从 ziplist 变为 hashtable 。
以下代码展示了哈希对象编码转换的情况:
1.键的长度太大引起编码转换 # 哈希对象只包含一个键和值都不超过 64 个字节的键值对 redis> HSET book name "Mastering C++ in 21 days" (integer) 1 redis> OBJECT ENCODING book "ziplist" # 向哈希对象添加一个新的键值对,键的长度为 66 字节 redis> HSET book long_long_long_long_long_long_long_long_long_long_long_description "content" (integer) 1 # 编码已改变 redis> OBJECT ENCODING book "hashtable" 2.值的长度太大引起编码转换 # 哈希对象只包含一个键和值都不超过 64 个字节的键值对 redis> HSET blah greeting "hello world" (integer) 1 redis> OBJECT ENCODING blah "ziplist" # 向哈希对象添加一个新的键值对,值的长度为 68 字节 redis> HSET blah story "many string ... many string ... many string ... many string ... many" (integer) 1 # 编码已改变 redis> OBJECT ENCODING blah "hashtable" 3.键值对数量过多引起编码转换 # 创建一个包含 512 个键值对的哈希对象 redis> EVAL "for i=1, 512 do redis.call('HSET', KEYS[1], i, i) end" 1 "numbers" (nil) redis> HLEN numbers (integer) 512 redis> OBJECT ENCODING numbers "ziplist" # 再向哈希对象添加一个新的键值对,使得键值对的数量变成 513 个 redis> HMSET numbers "key" "value" OK redis> HLEN numbers (integer) 513 # 编码改变 redis> OBJECT ENCODING numbers "hashtable" 五、要点总结1.Hash类型两种编码方式,ziplist 与 hashtable
2.hashtable 编码的哈希对象使用字典作为底层实现
3.ziplist 与 hashtable 编码方式之间存在转换