Redis命令-Hash命令

一、前言:为什么用 Hash 存储对象?

在 Redis 中,Hash(哈希) 是一种非常高效的键值对集合类型,特别适合存储对象

例如:

  • 用户信息:user:1001 → {name: "Alice", age: 25, email: "a@example.com"}
  • 商品详情:product:2001 → {title: "手机", price: 2999, stock: 100}

相比将每个字段拆成独立 key(如 user:1001:nameuser:1001:age),Hash 具有:

内存更省 (Redis 对小 Hash 有特殊编码优化)

操作原子性 (单个 Hash 内部操作是原子的)

网络开销更低(一次命令获取多个字段)

本文将系统讲解 Redis Hash 的所有核心命令 ,并附带实战示例与最佳实践


二、Hash 核心命令速查表

命令 作用 时间复杂度
HSET key field value [field value ...] 设置一个或多个字段 O(1) 每个字段
HGET key field 获取指定字段的值 O(1)
HMSET key field value [field value ...] 已废弃 ,用 HSET 替代 ---
HMGET key field [field ...] 获取多个字段的值 O(N),N=字段数
HGETALL key 获取所有字段和值 O(N),N=字段数
HDEL key field [field ...] 删除一个或多个字段 O(N),N=字段数
HEXISTS key field 判断字段是否存在 O(1)
HLEN key 获取 Hash 字段数量 O(1)
HKEYS key 获取所有字段名 O(N)
HVALS key 获取所有字段值 O(N)
HINCRBY key field increment 对整数值字段加减 O(1)
HINCRBYFLOAT key field increment 对浮点值字段加减 O(1)
HSTRLEN key field 获取字段值的字符串长度 O(1)

💡 注意 :从 Redis 4.0 起,HMSET 被标记为 deprecated,统一使用 HSET


三、常用命令详解与示例

3.1 写入数据:HSET

bash 复制代码
# 设置单个字段
127.0.0.1:6379> HSET user:1001 name "Alice"
(integer) 1  # 1=新增,0=更新

# 设置多个字段(推荐!)
127.0.0.1:6379> HSET user:1001 age 25 email "alice@example.com" city "Beijing"
(integer) 3  # 新增了 3 个字段

优势:一次命令完成多字段写入,减少网络往返。


3.2 读取数据:HGET / HMGET / HGETALL

bash 复制代码
# 获取单个字段
127.0.0.1:6379> HGET user:1001 name
"Alice"

# 获取多个字段(按需加载,避免全量)
127.0.0.1:6379> HMGET user:1001 name age city
1) "Alice"
2) "25"
3) "Beijing"

# 获取所有字段(慎用!大数据量会阻塞)
127.0.0.1:6379> HGETALL user:1001
1) "name"
2) "Alice"
3) "age"
4) "25"
5) "email"
6) "alice@example.com"
7) "city"
8) "Beijing"

⚠️ 生产建议

  • 避免在大 Hash 上使用 HGETALL
  • 优先使用 HMGET 按需获取字段

3.3 删除与判断:HDEL / HEXISTS

bash 复制代码
# 删除字段
127.0.0.1:6379> HDEL user:1001 email city
(integer) 2

# 判断字段是否存在
127.0.0.1:6379> HEXISTS user:1001 email
(integer) 0  # 不存在
127.0.0.1:6379> HEXISTS user:1001 name
(integer) 1  # 存在

3.4 计数与遍历:HLEN / HKEYS / HVALS

bash 复制代码
# 字段数量
127.0.0.1:6379> HLEN user:1001
(integer) 2

# 获取所有字段名(调试用)
127.0.0.1:6379> HKEYS user:1001
1) "name"
2) "age"

# 获取所有值
127.0.0.1:6379> HVALS user:1001
1) "Alice"
2) "25"

🔍 注意HKEYS/HVALS/HGETALL 在字段数 > 1000 时可能阻塞主线程!


3.5 数值自增:HINCRBY / HINCRBYFLOAT

bash 复制代码
# 整数自增(常用于计数器)
127.0.0.1:6379> HSET product:2001 view_count 100
127.0.0.1:6379> HINCRBY product:2001 view_count 1
(integer) 101

# 浮点自增(慎用,精度问题)
127.0.0.1:6379> HINCRBYFLOAT product:2001 avg_score 0.5
"0.5"

典型场景:商品浏览量、用户积分、评分统计。


四、Hash 的内部编码优化

Redis 对小 Hash 使用 ziplist(压缩列表) 编码,节省内存:

复制代码
# redis.conf 默认配置
hash-max-ziplist-entries 512   # 字段数 ≤ 512
hash-max-ziplist-value 64      # 每个值长度 ≤ 64 字节

当超过阈值,自动转为 hashtable 编码。

💡 建议

  • 小对象(如用户 profile)非常适合 Hash
  • 大对象(如文章内容)建议用 String 或单独 key

五、实战应用场景

场景 1:用户信息缓存

java 复制代码
// Java (Lettuce)
redis.hset("user:" + userId, 
    Map.of("name", "Alice", "age", "25", "email", "a@example.com"));

String name = redis.hget("user:" + userId, "name");
List<String> fields = redis.hmget("user:" + userId, "name", "age");

场景 2:商品库存与价格

python 复制代码
# Python (redis-py)
r.hset("product:1001", mapping={
    "title": "iPhone 15",
    "price": "5999",
    "stock": "50"
})

# 扣减库存(Lua 脚本保证原子性)
script = """
if tonumber(redis.call('HGET', KEYS[1], 'stock')) >= tonumber(ARGV[1]) then
    redis.call('HINCRBY', KEYS[1], 'stock', -ARGV[1])
    return 1
else
    return 0
end
"""
r.eval(script, 1, "product:1001", 1)

场景 3:会话状态管理

bash 复制代码
HSET session:abc123 user_id 1001 login_time 1700000000 ip "192.168.1.1"
HEXPIRE session:abc123 1800  # Redis 7.0+ 支持 Hash 级 TTL

📌 注意 :Redis 7.0+ 支持 HEXPIRE,但早期版本需对整个 key 设 TTL。


六、常见误区与最佳实践

❌ 误区 1:用 Hash 存储超大对象

  • 问题HGETALL 阻塞主线程
  • 建议:大对象拆分为多个 key,或使用 String + JSON

❌ 误区 2:频繁使用 HGETALL

  • 问题:网络带宽浪费 + 性能下降
  • 建议 :明确需要哪些字段,用 HMGET

✅ 最佳实践

  1. 字段命名规范 :如 user_idcreate_time
  2. 避免动态字段爆炸 :如 HSET log:20250101 ip_192.168.1.1 1(IP 无限)
  3. 监控 Hash 大小 :通过 HLEN + 告警防止膨胀

七、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
小白勇闯网安圈2 小时前
String、Hash、List、Set 四大数据结构与通用命令
redis
2601_962071173 小时前
八. Spring Boot2 整合连接 Redis(超详细剖析)
spring boot·redis·后端
纯.Pure_Jin(g)5 小时前
靶场PHP函数整理+防御方式
开发语言·php·ctf
程序员夏洛5 小时前
Redis 数据过期后的删除策略是什么?
数据库·redis·缓存
鱼鳞_5 小时前
热门八股-Redis
数据库·redis·缓存
程序员夏洛6 小时前
Redis 的持久化机制有哪些?
java·数据库·redis
hweiyu007 小时前
Redis命令:MIGRATE
redis·缓存
神仙别闹8 小时前
基于C++ WinPcap 的网络抓包软件
网络·c++·php
A.说学逗唱的Coke9 小时前
【人工智能专题】Redis 杀进 AI 数据层:向量搜索、语义缓存与 Agent 记忆工程从入门到踩坑
人工智能·redis·缓存