1.介绍
- Redis hash(哈希散列)是由字符类型的 field(字段)和 value 组成的哈希映射表结构(也称散列表),它非常类似于表格结构。在 hash 类型中,field 与 value 一一对应,且不允许重复。
- Redis hash 特别适合于存储对象。一个 filed/value 可以看做是表格中一条数据记录;而一个 key 可以对应多条数据。
2.常用命令
#设置单个字段
127.0.0.1:6379> HSET user:10 user:1 20201001
(integer) 1
#同时设置多个字段
127.0.0.1:6379> HMSET user:10 user:2 20201002 user:3 20201004 user:4 20201018
OK
#查询单个字段
127.0.0.1:6379> HGET user:10 user:2
"20201002"
#查询所有字段
127.0.0.1:6379> HGETALL user:10
1) "user:1"
2) "20201001"
3) "user:2"
4) "20201002"
5) "user:3"
6) "20201004"
7) "user:4"
8) "20201018"
127.0.0.1:6379> HKEYS user:10
1) "user:1"
2) "user:2"
3) "user:3"
4) "user:4"
#返回字段个数
127.0.0.1:6379> HLEN user:10
(integer) 4
#返回所有字段值
127.0.0.1:6379> HVALS user:10
1) "20201001"
2) "20201002"
3) "20201004"
4) "20201018"
#迭代hash的key键 HSCAN key cursor
# 迭代哈希表中的所有键值对,cursor 表示游标,默认为 0。
127.0.0.1:6379> HSCAN user:10 0
1) "0"
2) 1) "user:1"
2) "20201001"
3) "user:2"
4) "20201002"
5) "user:3"
6) "20201004"
7) "user:4"
8) "20201018"
#判断字段是否存在,存在返回1,不存在返回0
127.0.0.1:6379> HEXISTS user:10 user:4
(integer) 1
127.0.0.1:6379> HEXISTS user:10 user:5
(integer) 0
3.存储结构
3.1 ziplist
两种情况都满足时,Hash会使用 ziplist 进行存储:
- 哈希对象保存的所有键值对的键和值的字符串长度都小于 64 字节。对应配置:server.hash_max_ziplist_value。
- 哈希对象保存的键值对数量小于 512 个。对应配置:server.hash_max_ziplist_entries。
这种情况下查找元素的时间复杂度为O(n),并不适合存储大量键值对。如果不满足上述两个条件,则自动转换为hashtable类型。
> hset aaa k1 v1
(integer) 1
> debug object aaa
Value at:0x7f9e25e279d0 refcount:1 encoding:ziplist serializedlength:20 lru:85125 lru_seconds_idle:8
3.2 hashtable
dictht类型:
- table:指向哈希表的指针
- size:哈希表数组的大小
- sizemask:用于计算哈希值的掩码
- used:已经存储的(K,V)个数
字典类型的中其实包含两个哈希表,一个是用于存储(K,V)的哈希表ht[0],而另外一个ht[1]用于后续的扩容。
渐进式rehash扩容,移动一部分到新哈希表中,查找时先查旧再查新。
3.3 顺序问题
默认情况下,Redis的Hash是使用ziplist进行存储的,当超出一定限制后,再改为hashtable进行存储。
- ziplist是双向链表,存储顺序和数据插入顺序一致。查询结果顺序和存储顺序一致。
- hashtable是字典结构,查询结果顺序和插入顺序不一致。
HGETALL 没有顺序性。如果需要顺序,业务上层排序。Hash会根据数据量进行数据结构调整。目的:提高性能。