哈希表¶
REDIS_HASH
(哈希表)是 HSET 、 HLEN 等命令的操作对象,
它使用 REDIS_ENCODING_ZIPLIST
和 REDIS_ENCODING_HT
两种编码方式:
![digraph redis_hash {
node [shape=plaintext, style = filled];
edge [style = bold];
// type
REDIS_HASH [label="哈希表\nREDIS_HASH", fillcolor = "#95BBE3"];
// encoding
REDIS_ENCODING_ZIPLIST [label="压缩列表\nREDIS_ENCODING_ZIPLIST", fillcolor = "#FADCAD"];
REDIS_ENCODING_HT [label="字典\nREDIS_ENCODING_HT", fillcolor = "#FADCAD"];
// edge
REDIS_HASH -> REDIS_ENCODING_ZIPLIST;
REDIS_HASH -> REDIS_ENCODING_HT;
// datastruct 1
ziplist [label="ziplist"];
REDIS_ENCODING_ZIPLIST -> ziplist;
// datastruct 2
dict [label="dict.h/dict"];
REDIS_ENCODING_HT -> dict;
}](../_images/graphviz-79b313a74063fd9f3eab8e324689b24c3be725a0.png)
字典编码的哈希表¶
当哈希表使用字典编码时, 程序将哈希表的键(key)保存为字典的键, 将哈希表的值(value)保存为字典的值。
哈希表所使用的字典的键和值都是字符串对象。
下图展示了一个包含三个键值对的哈希表:
![digraph db {
rankdir = LR;
node [shape = record, style = filled];
edge [style = bold];
dict [label = "<head>dict\n |<number>StringObject\n \"number\" | NULL |<book>StringObject\n \"book\" |<message>StringObject\n \"message\"", fillcolor = "#A8E270"];
number [label = "<head>StringObject | 10086"];
book [label = "<head>StringObject | \"Mastering C++ in 21 days\""];
message [label = "<head>StringObject | \"hello moto\""];
dict:number -> number:head;
dict:book -> book:head;
dict:message -> message:head;
}](../_images/graphviz-79d5e1fa69655be0f0399a6f684997c98424b09e.png)
压缩列表编码的哈希表¶
当使用 REDIS_ENCODING_ZIPLIST
编码哈希表时,
程序通过将键和值一同推入压缩列表,
从而形成保存哈希表所需的键-值对结构:
+---------+------+------+------+------+------+------+------+------+---------+
| ZIPLIST | | | | | | | | | ZIPLIST |
| ENTRY | key1 | val1 | key2 | val2 | ... | ... | keyN | valN | ENTRY |
| HEAD | | | | | | | | | END |
+---------+------+------+------+------+------+------+------+------+---------+
新添加的 key-value 对会被添加到压缩列表的表尾。
当进行查找/删除或更新操作时,程序先定位到键的位置,然后再通过对键的位置来定位值的位置。
编码的选择¶
创建空白哈希表时,
程序默认使用 REDIS_ENCODING_ZIPLIST
编码,
当以下任何一个条件被满足时,
程序将编码从 REDIS_ENCODING_ZIPLIST
切换为 REDIS_ENCODING_HT
:
哈希表中某个键或某个值的长度大于
server.hash_max_ziplist_value
(默认值为64
)。压缩列表中的节点数量大于
server.hash_max_ziplist_entries
(默认值为512
)。
哈希命令的实现¶
哈希类型命令的实现全都是对字典和压缩列表操作函数的包装, 以及几个在两种编码之间进行转换的函数, 没有特别要讲解的地方。