哈希对象
哈希对象的编码可以是ziplist或者hashtable。
概述。
ziplist编码的哈希对象使用压缩列表作为底层实现,每当有新的键值对要加入到哈希对象时,程序会先将保存了键的压缩列表推入到压缩列表表尾,然后再将保存了值的压缩列表节点推入到压缩列表表尾,因此:
- 1.保存了同一键值对的两个节点总是紧挨在一起,保存键的节点在前,保存值的节点在后。
- 2.先添加到哈希对象中的键值对会被放在压缩列表的表头方向(相对于值对象来说),而后来添加到哈希对象中的键值对会被放在压缩列表的表尾方向
另一方面,hashtable编码的哈希对象使用字典作为底层实现,哈希对象中的每个键值对都使用一个字典键值对来保存:
- 1.字典的每个键都是一个字符串对象,对象中保存了键值对的键
- 2.字典的每个值都是一个字符串对象,对象中保存了键值对的值
例子
- 举个例子,如果执行以下HSET命令,那么服务器将创建一个列表对象作为profile键的值,如果profile键的值对象使用的是ziplist编码,那么这个值对象将会是图中的结构,其中对象所使用的压缩列表
- 举个例子,前面profile键创建的不是ziplist编码的哈希对象,而是hashtable编码的哈希对象,那么这个哈希对象应该会是图中的结构
编码转换。
当哈希对象可以同时满足以下两个条件时,哈希对象使用ziplist编码:
- 1.哈希对象保存的所有键值对的键和值的字符串长度都小于64字节
- 2.哈希对象保存的键值对数量小于512个
不能满足这两个条件的哈希对象需要使用hashtable编码
对于使用ziplist编码的列表对象,当使用ziplist编码所需的两个条件任意
一个不能被满足时,对象的编码转换操作就会被执行,原本保存在压缩
列表里的所有键值对都会被转移并保存到字典里面,对象的编码也会从ziplist变为hashtable.
代码展示了哈希对象因为键值对的键长度太大而引起编码转换的情况
// 哈希对象只包含一个键和值都不超过64字节的键值对
127.0.0.1:6379> HSET book name "Mastering C++ in 21 days"
(integer) 1
127.0.0.1:6379> OBJECT ENCODING book
"ziplist"
// 向哈希对象添加一个新的键值对,键的长度为66字节
127.0.0.1:6379> HSET book long_long_long_long_long_long_long_long_long_long_long_description "content"
(integer) 1
// 编码已改变
127.0.0.1:6379> OBJECT ENCODING book
"hashtable"
除了键的长度太大会引起编码转换之外,值得长度太大也会引起编码转换
// 哈希对象只包含一个键和值不超过64个字节的键值对
127.0.0.1:6379> HSET blah greeting "hello word"
(integer) 1
127.0.0.1:6379> OBJECT ENCODING blah
"ziplist"
// 向哈希对象添加一个键值对,值得长度为79个字节
127.0.0.1:6379> HSET blah stroy "many string ... many string ... many string ... many string ... many string ..."
(integer) 1
// 编码已改变
127.0.0.1:6379> OBJECT ENCODING blah
"hashtable"
最后,代码展示了哈希对象因为包含的键值对数量过多而引起编码转换的情况
// 创建一个包含512个键值对的哈希对象
127.0.0.1:6379> EVAL "for i=1, 512 do redis.call('HSET', KEYS[1], i, i)end" 1 "numbers"
(nil
127.0.0.1:6379> HLEN numbers
(integer) 512
127.0.0.1:6379> OBJECT ENCODING numbers
"ziplist"
// 再向还对象添加一个新的键值对,使得键值对数量变成513个
127.0.0.1:6379> HMSET numbers "key" "value"
OK
127.0.0.1:6379> HLEN numbers
(integer) 513
127.0.0.1:6379> OBJECT ENCODING numbers
"hashtable"
注意。
这两个条件的上限值时可以修改的,具体要看配置文件中关于
hash-max-ziplist-value选项和hash-max-ziplist选项说明