Redis的哈希对象是一个string类型的field和value的映射表,特别适合用于存储对象,每个 hash 可以存储 2^32 - 1 键值对。
1. 编码
Redis中哈希对象的编码有ZIPLIST和HT。
ziplist编码的哈希对象使用压缩列表作为底层实现,有新的键值对插入时,现将键插入的压缩列表尾部,再将值插入的压缩列表尾部,这样键值对总是紧密挨在一起的。
hashtable编码的哈希对象使用字典作为底层实现,每个键值对都用字典的键值对保存。
2. 编码转换
当哈希对象满足以下条件时,使用ZIPLIST编码:
- 哈希对象保存的所有键值对的字符串长度小于64字节。
- 哈希对象保存的键值对个数小于512
这两个参数可以通过hash-max-ziplist-value和hash-max-ziplist-entries修改。
当对ziplist编码的哈希对象进行一些操作致使无法使用ziplist编码是,则将哈希对象转换成HT编码,ziplist中保存的键值对会移动到新的字典中。
目前仅实现了ZIPLIST ==> HT的编码转换
3. 命令
命令 | 作用 |
---|---|
HDEL | 删除一个或多个哈希表字段 |
HEXISTS | 查看哈希表 key 中,指定的字段是否存在 |
HGET | 获取存储在哈希表中指定字段的值 |
HGETALL | 获取在哈希表中指定 key 的所有字段和值 |
HINCRBY | 为哈希表 key 中的指定字段的整数值加上增量 increment |
HINCRBYFLOAT | 为哈希表 key 中的指定字段的浮点数值加上增量 increment |
HKEYS | 获取所有哈希表中的字段 |
HLEN | 获取哈希表中字段的数量 |
HMGET | 获取所有给定字段的值 |
HMSET | 同时将多个 field-value (域-值)对设置到哈希表 key 中 |
HSET | 将哈希表 key 中的字段 field 的值设为 value |
HSETNX | 只有在字段 field 不存在时,设置哈希表字段的值 |
HSTRLEN | 获取哈希表字段值的长度 |
HVALS | 获取哈希表中所有值 |
HSCAN | 迭代哈希表中的键值对 |
4. 源码剖析
- 哈希表中添加键值对
1 | int hashTypeSet(robj *o, sds field, sds value, int flags) { |
- 哈希表中删除键值对
1 | int hashTypeDelete(robj *o, sds field) { |
- 迭代哈希表
1 | int hashTypeNext(hashTypeIterator *hi) { |
- 哈希对象编码转换
1 | void hashTypeConvertZiplist(robj *o, int enc) { |
- HGETALL底层实现
1 | void genericHgetallCommand(client *c, int flags) { |
- HSET命令
1 | void hsetCommand(client *c) { |