Redis 命令及数据类型 -- Hash

摘要

Hash 核心详解

  • Redis Hash 是一种 key → field → value 的数据结构,本质上是

1
2
3
4
5
key -> Map<String, String>
# 说明
key:Redis 的键(只能是 String)
field:Hash 内的字段名(String)
value:字段值(String,二进制安全)
  • Hash 的核心特性

1
2
3
4
5
适合存储对象型数据
支持 字段级别读写
所有操作均为 原子性
内存效率优于「String + JSON」
单个 Hash 理论最大 512 MB
  • Hash 的使用场景

1
2
3
4
5
6
7
# 对象缓存
HSET user:1 name zhangsan age 20
# 电商购物车:1)以用户id为key 2)商品id为field 3)商品数量为value
HSET cart:userId commodity:1001 1 commodity:1002 5
# 分布式锁,一个命令搞不定,需要结合Lua脚本
HINCRBY lock uuid:threadId 1 # 创建锁 或 重入+1
EXPIRE lock 30 # 30 秒后自动释放锁
  • Hash结构优缺点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
• 优点
1)同类数据聚合存储,适合表达对象模型,便于管理与维护
2)相比 string 操作消耗内存与 CPU 更小
a.当多个小字段被组织在同一个 Hash 中时,整体内存与 CPU 开销通常小于使用多个 String Key,因为Redis 对 小 Hash 使用 ziplist / listpack(紧凑结构),减少了 Key 元数据、过期字典、指针等开销
b.Hash 过大时(BigHash)优势消失
3)相比 string,减少了 Key 数量,降低元数据与过期字典的额外开销
• 缺点
1) 默认过期只能作用在 key 级别,Hash field 级别过期需 Redis 7.4+ 才支持
```bash
# user:1 这个 Hash 不会过期
HSET user:1 name "Tom" age 18
# HEXPIRE key seconds [NX|XX|GT|LT] FIELDS numfields field [field ...]
# 只有 name field 60 秒后自动删除
HEXPIRE user:1 60 FIELDS 1 name
# 同时给多个 field 设置过期时间
HEXPIRE user:1 60 FIELDS 2 name age
# 使用毫秒级过期(HPEXPIRE)
# HPEXPIRE key milliseconds [NX|XX|GT|LT] FIELDS numfields field [field ...]
HPEXPIRE user:1 60 FIELDS 2 name age
# 查看 field 剩余秒数(HTTL),-1 表示 field 永不过期,-2 表示 field 已过期
# HTTL key FIELDS numfields field [field ...]
HTTL user:1 FIELDS 1 name
# 查看毫秒级 TTL(HPTTL),-1 表示 field 永不过期,-2 表示 field 已过期
# HPTTL key FIELDS numfields field [field ...]
HPTTL user:1 FIELDS 1 name
# 移出过期时间
# HPERSIST key FIELDS numfields field [field ...]
HPERSIST user:1 FIELDS 1 name
  1. 在 Redis Cluster 中,不应设计超大的 Hash Key(BigHash),否则会影响迁移、扩缩容和主从复制性能。

  • 生产环境建议

1
2
3
4
5
一个 Hash = 一个对象
field 数量建议 < 100
单 field value 建议 < 1 KB
大对象拆分为多个 Hash
避免在大 Hash 上使用 HGETALL

Hash 命令

  • SpringBoot 的 RedisTemplate<K,V>.opsForHash() 中 Hash 数据类型 的操作方法与 Redis 原生命令的对应关系如下:

写入 / 更新

方法功能 方法 Redis 原始命令 备注
设置单个 field-value put(H key, HK hashKey, HV value) HSET key field value 新增或覆盖
批量设置 field-value putAll(H key, Map<HK,HV> m) HSET key field value [field value ...] HMSET 已废弃
field 不存在时设置 putIfAbsent(H key, HK hashKey, HV value) HSETNX key field value 原子操作

读取

方法功能 方法 Redis 原始命令 备注
获取指定 field 的值 get(H key, Object hashKey) HGET key field 不存在返回 null
批量获取多个 field multiGet(H key, Collection<HK> hashKeys) HMGET key field [field ...] 不存在返回 null
获取所有 value values(H key) HVALS key O(N)
获取所有 field-value entries(H key) HGETALL key 生产环境慎用

删除 / 存在性判断

方法功能 方法 Redis 原始命令 备注
删除一个或多个 field delete(H key, Object... hashKeys) HDEL key field [field ...] 返回删除数量
判断 field 是否存在 hasKey(H key, Object hashKey) HEXISTS key field

计数与数值运算

方法功能 方法 Redis 原始命令 备注
field 整数自增 increment(H key, HK hashKey, long delta) HINCRBY key field increment value 必须是整数
field 浮点数自增 increment(H key, HK hashKey, double delta) HINCRBYFLOAT key field increment Redis ≥ 2.6
获取 field 对应 value 长度 lengthOfValue(H key, HK hashKey) HSTRLEN key field 不存在返回 0
获取 hash 中 field 数量 size(H key) HLEN key

随机访问(Random Access)

  • ⚠️ 随机访问常用于抽样、降级策略,不适合强一致业务

方法功能 方法 Redis 原始命令 备注
随机返回一个 field randomKey(H key) HRANDFIELD key Redis ≥ 6.2
随机返回一个 field-value randomEntry(H key) HRANDFIELD key WITHVALUES Redis ≥ 6.2
随机返回多个 field randomKeys(H key, long count) HRANDFIELD key count count < 0 可重复
随机返回多个 field-value randomEntries(H key, long count) HRANDFIELD key count WITHVALUES

遍历与扫描(推荐方式)

方法功能 方法 Redis 原始命令 备注
获取所有 field keys(H key) HKEYS key O(N),大 hash 慎用
游标扫描 hash scan(H key, ScanOptions options) HSCAN key cursor [MATCH] [COUNT] 推荐替代 HGETALL
  • 📌 最佳实践

    • 小 hash:HGETALL
    • 大 hash / 线上系统:HSCAN

Hash Field 级别过期(Redis 7.4+)

  • Redis 7.4 引入 field 级 TTL,这是 Hash 的重大能力增强

  • 设置过期

方法功能 方法 Redis 原始命令 备注
为指定 field 设置过期时间 expire(H key, Duration timeout, Collection<HK> hashKeys) HEXPIRE key seconds FIELDS n field [...] Redis ≥ 7.4
为指定 field 设置过期时间点 expireAt(H key, Instant expireAt, Collection<HK> hashKeys) HEXPIREAT key timestamp FIELDS n field [...] Redis ≥ 7.4
高级过期策略 expire(H key, Expiration expiration, ExpirationOptions options, Collection<HK> hashKeys) HEXPIRE / HEXPIREAT Spring 抽象封装
  • 移除过期时间

方法功能 方法 Redis 原始命令 备注
移除指定 field 的过期时间 persist(H key, Collection<HK> hashKeys) HPERSIST key FIELDS n field [...] Redis ≥ 7.4