Redis 哈希是一种用于存储键值对的数据结构。在 Redis 哈希中,每个键(key)都关联着一个哈希表(hash)。这个哈希表包含了多个字段(field)和值(value)。哈希非常适合存储对象,因为你可以通过字段名快速访问或修改对象的属性。
在我的博客中还介绍了关于String类型的详解,感兴趣的可以点击学习:
String类型的详解https://blog.csdn.net/qq_45875349/article/details/139692572?spm=1001.2014.3001.5501
字符串和哈希在redis中存储的对比:
1. 常用命令
命令 | 执行效果 | 时间复杂度 |
hset key field value | 设置值 | O(1) |
hget key field | 获取值 | O(1) |
hdel key field [field …] | 删除field | O(k),k是field个数 |
hlen key | 计算field个数 | O(1) |
hgetall key | 获取所有的field-value | O(k),k是field个数 |
hmget field [field …] | 批量获取field-value | O(k), k 是 field个数 |
hmset field value [field value …] | 批量设置field-value | O(k),k是field个数 |
hexists key field | 判断field是否存在 | O(1) |
hkeys key | 获取所有的field | O(k),k是field个数 |
hvals key | 获取所有的value | O(k),k是field个数 |
hsetnx key field value | 设置值,但必须在field不存在时才能设置成功 | O(1) |
hincrby key field n | 对应field-value+n | O(1) |
hincrbyfloat key field n | 对应field-value+n | O(1) |
hstrlen key field | 计算value的字符串长度 | O(1) |
相关命令演示
HSET key field value 设置值
设置用户的名字和年龄和余额:
HSET user:1000 name "John Doe"
HSET user:1000 age 30
HSET user:1000 balance 100.0
HGET key field 获取值
获取用户的名字
HGET user:1000 name
HDEL key field [field ...] 删除字段
HLEN key 计算field个数
hgetall key 获取所有的field和value
HMGET key field [field ...] 批量获取field-value
HMSET key field value [field value ...]批量设置field-value
hkeys key 获取所有的 field
2. 内部编码
Redis 中的哈希数据结构使用两种不同的内部编码方式:ziplist
(压缩列表)和 hashtable
(哈希表)。Redis 会根据哈希表中数据的大小和元素个数自动选择使用哪种编码方式。
2.1 压缩列表(ziplist)
压缩列表是一种特殊编码的双向链表,能够高效地存储和访问小规模数据。它的特点是:
- 存储在连续的内存块中,减少内存碎片。
- 使用特殊编码压缩小整数和短字符串。
- 插入、删除操作需要移动大量内存数据,适用于元素较少的情况。
使用条件:
- 当哈希表的元素个数小于
hash-max-ziplist-entries
(默认 512个)。 - 当所有字段和值的长度都小于
hash-max-ziplist-value
(默认 64 字节)。
配置示例(在 redis.conf
配置文件中):
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
2.2 哈希表(hashtable)
哈希表是一种典型的哈希数据结构,使用哈希函数将键值对映射到一个数组中。它的特点是:
- 支持快速的插入、删除和查找操作。
- 随着数据量的增加,内存消耗较大。
- 适用于大规模数据的存储和操作。
使用条件(不满足ziplist):
- 当哈希表的元素个数大于等于
hash-max-ziplist-entries
。 - 当任一字段或值的长度大于等于
hash-max-ziplist-value
。
ziplist
:
# 设置哈希表字段
127.0.0.1:6379> HMSET hashkey f1 v1 f2 v2
OK
# 查看哈希表的内部编码
127.0.0.1:6379> OBJECT ENCODING hashkey
"ziplist"
hashkey
哈希表的字段较少且值较小,因此使用
ziplist
编码。
2. 当有值大于 64 字节时,内部编码会转换为 hashtable
:
# 设置一个大于 64 字节的值
127.0.0.1:6379> HSET hashkey f3 "one string is bigger than 64 bytes ... 比特就业课 ..."
OK
# 查看哈希表的内部编码
127.0.0.1:6379> OBJECT ENCODING hashkey
"hashtable"
3. 当字段个数超过 512 时,内部编码也会转换为 hashtable
:
# 设置超过 512 个字段
127.0.0.1:6379> HMSET hashkey f1 v1 f2 v2 f3 v3 ... f513 v513
OK
# 查看哈希表的内部编码
127.0.0.1:6379> OBJECT ENCODING hashkey
"hashtable"
3. 使用场景
1. 存储映射关系的信息(用户信息、商品信息、购物车)
在许多应用中,需要存储用户的信息,例如用户名、电子邮件、年龄等。使用 Redis Hash 可以非常方便地将这些信息存储在一起:
HMSET user:1000 name "John Doe" email "john.doe@example.com" age "30"
通过使用哈希类型,我们可以快速访问和更新用户的某个具体字段,而不需要读取整个对象。
HGET user:1000 email
"john.doe@example.com"
HSET user:1000 age "31"
(integer) 1
电商平台需要存储大量的商品信息,包括商品名称、价格、库存等。Redis Hash 非常适合存储这种类型的数据:
HMSET product:2000 name "Laptop" price "999.99" stock "50"
可以快速查询和更新某个商品的字段:
HGET product:2000 price
"999.99" # 返回 "999.99"
HINCRBY product:2000 stock -1
(integer) 49 # 减少库存数量
2. 计数器
哈希类型可以用来实现复杂的计数器。例如,记录文章的各类统计信息,如点赞数、评论数、分享数等:
HMSET article:3000 views "1000" likes "150" comments "20" shares "5"
OK
可以方便地增加或减少某个字段的值:
HINCRBY article:3000 views 1
(integer) 1001
HINCRBY article:3000 comments 1
(integer) 21
3. 会话管理
在 Web 应用中,可以使用 Redis Hash 来管理用户会话信息。例如,存储每个用户的会话数据:
HMSET session:4000 user_id "1000" login_time "2023-06-21 10:00:00" last_access "2023-06-21 10:05:00"
OK
可以快速更新用户的最后访问时间:
HSET session:4000 last_access "2023-06-21 10:10:00"
(integer) 1