对象编码
哈希对象的编码可以是ziplist
或者hashtable
ziplist
ziplist编码的哈希对象使用压缩列表作为实现, 每当有新的键值对要加入到哈希对象时, 程序会先将保存了键的压缩列表节点推入到压缩列表表尾, 然后再将保存了值的压缩列表节点推入到压缩列表表尾.
优点
-
保存了同一键值对的两个节点总是紧挨在一起, 保存键的节点在前, 保存值的节点在后.
-
先添加到哈希对象中的键值对会被放在压缩列表的表头方向, 后来添加到哈希对象中的键值对会被放在压缩列表的表尾方向.
hashtable
hashtable编码的哈希对象使用字典作为底层实现, 哈希对象中的每个键值对都使用以这个字典键值对保存:
-
字典中每个键都是一个
字符串
对象, 并保存键的值 -
字典中么个值都是一个
字符串
对象, 并保存键值对的值
编码转换
当哈希对象同时满足以下两个条件时, 哈希对象使用ziplist编码
-
哈希对象保存的所有键值对的键和值的字符串长度都小于
64
字节 -
哈希对象保存的键值对数量小于512个; 不能满足这两个条件的哈希对象需要使用
hashtable
调整
-
hash-max-ziplist-value
: 用于控制字符串能够设置的最大长度 -
hash-max-ziplist-entries
: 用于控制压缩列表最大存储的节点数量
以上两个参数用于控制ziplist
向hashtable
转换的条件.
# Hashes are encoded using a memory efficient data structure when they have a # small number of entries, and the biggest entry does not exceed a given # threshold. These thresholds can be configured using the following directives. hash-max-ziplist-entries 512 hash-max-ziplist-value 64
哈希命令的实现
命令 | ziplist编码实现方法 | hashtable编码的实现方法 |
---|---|---|
HSET | 首先调用ziplistPush 函数, 将键推入到压缩列表的表尾, 然后再次调用ziplistPush 函数, 将值推入到压缩列表的表尾 |
调用dictAdd 函数, 将新节点添加到字典里面 |
HGET | 首先调用ziplistFind 函数, 在压缩列表中查找指定键所对应的节点, 然后调用ziplistNext 函数, 将指针移动到键节点叛变的值节点, 然后返回节点 |
调用dictFine 行数, 在字典中查找给定键, 然后调用dictGetVal 函数, 返回该键所对应的值. |
HEXISTS | 调用ziplistFind 函数, 在压缩列表中查找指定键所对应的节点, 如果找到的话, 说明键值对存在, 没找到的话说明键值对不存在 |
调用dictFind 函数, 在字典中查找给定键, 如果找到的话说明键值对存在, 没找到的话说明键值不存在 |
HDEL | 调用ziplistFind 函数, 在压缩列表中查找指定键所对应的节点, 然后将对应的键节点, 以及键节点旁边的值节点都删除掉 |
调用dectDelete 函数, 将指定键所对应的键值对从字典中删除掉 |
HLEN | 调用ziplistLen 函数, 取的压缩列表包含节点的总数量, 将这个数量除以2 , 得出的结果就是压缩列表保存的键值对的数量 |
调用dictSize 函数, 返回字典包含的键值对的数量, 这个数量就是哈希对象包含的键值对的数量 |
HGETALL | 遍历整个压缩列表, 用ziplistGet 函数返回所有键和值 |
遍历真个字典, 用dictGetKey 函数返回字典的键, 用dictGetVal |