Redis 哈希(上)

哈希是一个键值对集合,适合存储对象。本课学习哈希的基本操作。

什么是哈希?

哈希类似于编程语言中的:

一个Redis哈希键可以存储多个字段-值对:

user:1
├─ name  → "Alice"
├─ age   → "25"
├─ city  → "Beijing"
└─ email → "alice@example.com"
💡 优势: 哈希可以单独修改某个字段,不需要读取整个对象。内存效率也比存储JSON字符串更高。

HSET和HGET:设置和获取字段

HSET:设置单个字段

REDIS
# 设置单个字段
HSET user:1 name "Alice"
(integer) 1  # 返回新增的字段数量

# 设置多个字段
HSET user:1 age 25 city "Beijing"
(integer) 2  # 新增了2个字段

# 更新已存在的字段
HSET user:1 name "Bob"
(integer) 0  # 字段已存在,返回0

HGET:获取单个字段

REDIS
HGET user:1 name
"Alice"

HGET user:1 age
"25"

# 字段不存在
HGET user:1 notexist
(nil)

HSETNX:仅当字段不存在时设置

REDIS
# 仅当字段不存在时设置
HSETNX user:1 name "Charlie"
(integer) 0  # 字段已存在,设置失败

HSETNX user:1 phone "13800138000"
(integer) 1  # 字段不存在,设置成功

HMSET和HMGET:批量操作

HMSET:批量设置字段

REDIS
HMSET user:2 name "Bob" age 30 city "Shanghai" email "bob@example.com"
OK
⚠️ 注意: Redis 4.0.0后,HMSET已被废弃,建议使用HSET设置多个字段。

HMGET:批量获取字段

REDIS
HMGET user:2 name age city
1) "Bob"
2) "30"
3) "Shanghai"

# 包含不存在的字段
HMGET user:2 name email phone
1) "Bob"
2) "bob@example.com"
3) (nil)  # phone不存在

HGETALL:获取所有字段和值

REDIS
HGETALL user:2
1) "name"
2) "Bob"
3) "age"
4) "30"
5) "city"
6) "Shanghai"
7) "email"
8) "bob@example.com"
⚠️ 注意: HGETALL返回字段和值交替的数组。如果哈希很大,会占用大量内存和网络带宽,慎用!

HKEYS和HVALS:获取所有字段名或值

HKEYS:获取所有字段名

REDIS
HKEYS user:2
1) "name"
2) "age"
3) "city"
4) "email"

HVALS:获取所有值

REDIS
HVALS user:2
1) "Bob"
2) "30"
3) "Shanghai"
4) "bob@example.com"

HEXISTS:检查字段是否存在

REDIS
HEXISTS user:2 name
(integer) 1  # 存在

HEXISTS user:2 phone
(integer) 0  # 不存在

HDEL:删除字段

REDIS
# 删除单个字段
HDEL user:2 email
(integer) 1  # 删除了1个字段

# 删除多个字段
HDEL user:2 age city
(integer) 2  # 删除了2个字段

# 删除不存在的字段
HDEL user:2 notexist
(integer) 0

HLEN:获取字段数量

REDIS
HSET user:3 name "Charlie" age 28
HLEN user:3
(integer) 2  # 有2个字段

# 键不存在
HLEN notexist
(integer) 0

HSTRLEN:获取字段值的长度

REDIS
HSET user:1 name "Alice" bio "Software Engineer"
HSTRLEN user:1 name
(integer) 5  # "Alice"长度为5

HSTRLEN user:1 bio
(integer) 17  # "Software Engineer"长度为17

哈希应用场景

场景1:存储用户信息

REDIS
# 存储用户基本信息
HSET user:1001 name "Alice" age 25 email "alice@example.com" role "admin"

# 获取用户姓名
HGET user:1001 name

# 更新用户年龄
HSET user:1001 age 26

# 获取所有用户信息
HGETALL user:1001

场景2:购物车

REDIS
# 用户1的购物车
HSET cart:user:1 product:101 2    # 商品101,数量2
HSET cart:user:1 product:102 1    # 商品102,数量1
HSET cart:user:1 product:103 5    # 商品103,数量5

# 查看购物车所有商品
HGETALL cart:user:1

# 修改商品数量
HSET cart:user:1 product:101 3

# 删除商品
HDEL cart:user:1 product:102

# 查看购物车商品数量
HLEN cart:user:1

场景3:文章元数据

REDIS
# 存储文章信息
HSET article:123 title "Redis Tutorial" author "Alice" views 1000 likes 50

# 增加阅读数(需要HINCRBY)
HINCRBY article:123 views 1

# 增加点赞数
HINCRBY article:123 likes 1

# 获取文章标题和作者
HMGET article:123 title author

场景4:商品信息缓存

REDIS
# 缓存商品详情
HSET product:2001 name "iPhone 15" price 5999 stock 100 category "phone"

# 获取商品价格
HGET product:2001 price

# 更新库存
HSET product:2001 stock 95

# 检查商品是否存在
HEXISTS product:2001 name

哈希 vs 字符串存储对象

方式1:字符串存储JSON

REDIS
SET user:1 '{"name":"Alice","age":25,"email":"alice@example.com"}'

# 获取整个对象
GET user:1

# 修改年龄:需要读取、解析、修改、序列化、写回
# 步骤多,效率低

方式2:哈希存储

REDIS
HSET user:1 name "Alice" age 25 email "alice@example.com"

# 获取单个字段
HGET user:1 name

# 修改年龄:一步完成
HSET user:1 age 26

# 获取多个字段
HMGET user:1 name age

对比总结

对比项 字符串(JSON) 哈希
修改单个字段 需要读取整个对象 直接修改
内存占用 较大(JSON格式) 较小(紧凑存储)
查询单个字段 需要解析JSON 直接获取
复杂嵌套对象 ✅ 支持 ❌ 不支持
部分更新 ❌ 困难 ✅ 简单
💡 选择建议:

  • 简单对象(扁平结构):使用哈希
  • 复杂对象(嵌套结构):使用字符串存储JSON
  • 需要频繁修改单个字段:使用哈希

哈希编码优化

Redis会根据哈希大小自动选择编码:

编码类型 使用条件 说明
ziplist 字段数量 ≤ 512,值长度 ≤ 64字节 压缩列表,节省内存
hashtable 字段数量 > 512 或值长度 > 64字节 哈希表,性能更好

查看编码类型

REDIS
HSET small:hash field1 "value1" field2 "value2"
OBJECT ENCODING small:hash
"ziplist"

# 添加大量字段后
HSET large:hash field1 "value1" field2 "value2" ... field600 "value600"
OBJECT ENCODING large:hash
"hashtable"
ℹ️ 了解: 编码类型由Redis自动选择,可通过配置参数调整阈值。

❓ 常见问题

Q 哈希可以存储多少个字段?
A 理论上无限制(2^32 - 1),但实际受内存限制。建议单个哈希不要超过几千个字段。
Q HGETALL会影响性能吗?
A 会。如果哈希很大,HGETALL会返回大量数据,占用内存和网络带宽。建议使用HSCAN迭代获取。
Q 哈希的字段值可以是数字吗?
A 可以。Redis中所有值都是字符串,但数字字符串可以进行数值操作(HINCRBY)。
Q 如何删除整个哈希键?
A 使用DEL命令删除键,而不是HDEL删除字段:DEL user:1
Q 哈希支持嵌套吗?
A 不支持。哈希的值只能是字符串。如需嵌套,使用字符串存储JSON。

📖 小节

📝 作业

  1. 用户信息: 使用哈希存储一个用户的信息(姓名、年龄、邮箱、城市),然后获取所有信息
  2. 购物车: 使用哈希实现一个购物车,添加3个商品,修改1个商品数量,删除1个商品
  3. 字段操作: 使用HEXISTS检查某个字段是否存在,使用HLEN统计字段数量
  4. 对比练习: 分别用字符串JSON和哈希存储同一个对象,对比修改单个字段的步骤

下一课

下一课我们将学习 Redis 哈希(下),学习哈希的高级操作和数值计算。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏