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 + 告警防止膨胀

七、结语

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

相关推荐
BullSmall14 小时前
Redis 双机部署 完整方案(两种架构,适配两台机器)
java·redis·架构
贾斯汀玛尔斯15 小时前
每天学一个算法--一致性哈希(Consistent Hashing)
算法·哈希算法
石榴树下的七彩鱼16 小时前
智能抠图 API 多语言接入实战:从零到上线的 Python / Java / PHP / JS 完整教程(附避坑指南)
java·python·php·智能抠图·api接入·石榴智能·shiliuai
小张成长计划..17 小时前
【C++】25:哈希表的实现
数据结构·哈希算法·散列表
M--Y17 小时前
Redis集群和典型应用场景
redis·算法·哈希算法·集群
Magic@17 小时前
Redis学习[1] ——基本概念和数据类型
linux·开发语言·数据库·c++·redis·学习
Irene199117 小时前
SQL查询优化:NOT EXISTS与LEFT JOIN性能对比
oracle·哈希算法
XS03010618 小时前
Java 基础(九) IO流
java·开发语言·php
_Evan_Yao18 小时前
缓存金字塔上的红色闪电:Redis 如何借力 CPU 的 L1/L2/L3 与 TLB 飞驰
java·数据库·redis·后端·缓存
独隅18 小时前
此电脑网络位置异常的AD域排错指南
开发语言·php