Redis 的 Hash 类型一直适合存储对象或聚合数据,比如用户资料、购物车条目、设备状态等。但长期以来,TTL 只能针对整个键设置,无法对 Hash 中的某一个字段单独指定存活时间。如果业务里只需要让某个属性在一段时间后自动失效,开发者往往要把字段拆成独立的键,或者借助 Sorted Set 记录时间戳,再通过后台任务不断扫描删除。这些方案要么增加键数量,要么引入额外的维护成本。Redis 7.4 版本正式加入了 Hash 字段级别的过期时间支持,让这个需求变得原生、直接且高效。

命令族与基础用法
Redis 7.4 为 Hash 字段过期提供了一组新命令,分为秒级和毫秒级两类。秒级命令是 HEXPIRE 和 HEXPIREAT,毫秒级命令是 HPEXPIRE 和 HPEXPIREAT。查询剩余时间使用 HTTL(秒)和 HPTTL(毫秒),移除字段过期设置使用 HPERSIST。
先看一个最简单的例子。假设有一个用户会话 Hash,包含 token、ip 和 last_active 三个字段,其中 token 字段需要在 60 秒后自动删除,而其他字段保持不变。命令写法如下:
HSET user:1001 token "abc123" ip "10.0.0.1" last_active "1700000000" HEXPIRE user:1001 60 FIELDS 1 token HTTL user:1001 FIELDS 1 token
HEXPIRE 命令的第一个参数是键名,第二个参数是过期秒数,FIELDS 后面先写字段数量,再列出具体字段名。命令执行后会返回一个数组,每个字段对应一个结果:1 表示成功设置了过期时间,-2 表示字段不存在,0 表示未能设置(例如因为条件不满足)。HTTL 也会返回数组,其中 -1 表示字段没有过期时间,-2 表示字段已过期或被删除。
这些命令都支持 NX、XX、GT、LT 选项,用法与 EXPIRE 命令一致。NX 表示仅在字段不存在过期时间时设置,XX 表示仅在字段已有过期时间时设置,GT 表示新过期时间必须大于当前过期时间才生效,LT 则相反。利用这些选项可以避免覆盖更早或更晚的过期时间,比如业务想给 token 续期,但只允许缩短不允许延长,就可以用 LT 选项。
底层实现与过期删除机制
Hash 字段过期并不是简单地在键级别加一个辅助 TTL,而是在内部为每个字段维护独立的过期时间元数据。具体实现上,Redis 对 Hash 的底层编码做了扩展。当 Hash 使用 listpack 编码时,每个 entry 除了原始 field 和 value 之外,还会额外存储一个过期时间戳;当 Hash 使用 hashtable 编码时,则会通过一个额外的字典或字段属性来记录过期时间。这样一来,字段的过期判断可以精确到单个条目,而不是整个键。
过期字段的删除机制与键过期类似,采用惰性删除和定期删除相结合的方式。惰性删除发生在客户端访问某个字段时,如果发现该字段的过期时间已经小于当前时间,就会立即删除该字段并返回 -2。定期删除则是在 Redis 的后台过期扫描中,对 Hash 字段进行抽样检查,如果发现过期字段则将其从 Hash 中移除。需要强调的是,字段过期后只是删除了该字段,Hash 键本身依然存在,即使所有字段都过期了,键也不会自动消失,除非键本身也设置了 TTL。
与键过期相比,Hash 字段过期有几个明显的区别。键过期删除的是整个键及其所有数据,而字段过期只删除一个字段,影响范围小得多。同时,字段过期的时间精度可以是秒或毫秒,但底层存储仍然以毫秒为单位,秒级设置最终会转换成毫秒时间戳。另外,过期字段并不会触发键空间通知中的 expired 事件,而是会产生字段删除的通知,具体事件类型需要根据 Redis 版本确认。内存回收方面,字段被删除后其占用的空间会被释放,但如果 Hash 的字段数量很多且过期频繁,删除操作本身也会带来性能开销。
持久化与主从复制注意事项
在 RDB 持久化方面,Redis 7.4 会将 Hash 字段的过期时间一并写入 RDB 文件。这样即使服务器重启,字段的存活时间也能正确恢复。如果某个字段在写 RDB 时已经过期,那么它不会被保存。加载 RDB 时,Redis 会根据时间戳重新计算剩余 TTL,确保过期状态尽可能准确。
在 AOF 持久化方面,设置字段过期的命令会以写命令的形式追加到 AOF 文件。重放 AOF 时,这些命令会重新执行,字段的过期时间也得以恢复。需要注意的是,如果字段在 AOF 记录后、重放前已经过期,重放时该字段可能已经不存在,此时 HEXPIRE 命令会返回 -2。这属于正常现象,不会影响数据一致性。另外,定期删除产生的字段删除操作也会被记录为 HDEL 或等效命令,保证主从和 AOF 恢复后状态一致。
主从复制场景下,字段过期由主节点主导。主节点通过惰性删除或定期删除发现某个字段过期后,会将对应的删除操作传播给所有从节点。从节点不会独立判断字段是否过期,避免因为时钟偏差导致主从不一致。如果主节点发生故障转移,新的主节点会继续根据字段的过期时间进行删除。集群模式下,Hash 键根据键名计算哈希槽,字段过期不会影响槽位分配。但要注意,如果客户端使用 HEXPIRE 命令操作同一个键的多个字段,必须确保这些字段属于同一个 Hash 键,否则会收到错误提示。
应用场景与性能建议
Hash 字段过期非常适合那些需要临时保留部分属性的场景。比如用户登录后,token 字段需要 30 分钟过期,而用户的基本信息可以长期保留;又比如购物车中,秒杀商品的库存锁定字段需要 5 分钟过期,而其他普通商品字段不受影响。过去这类逻辑要么把敏感字段拆成单独的键,要么在业务层维护定时任务,现在只需一条 HEXPIRE 命令即可完成。
另一个典型场景是缓存对象的部分字段缓存。假设一个对象包含基础信息和实时统计信息,实时统计信息变化频繁且时效性强,可以给实时统计字段设置较短的 TTL,基础信息字段不设置过期。这样既能满足缓存更新的需求,又不会因为整个对象过期而频繁回源。
性能方面,Hash 字段过期虽然带来了便利,但也不要滥用。如果同一个 Hash 键中字段数量非常大,并且大量字段频繁过期,定期删除的扫描成本会随之上升。同时,字段过期元数据会占用额外内存,特别是当 Hash 使用 listpack 编码时,每个 entry 都会增加固定大小的过期时间存储。建议将字段数量控制在合理范围,例如不超过几千个,并避免给单个 Hash 设置过多的短时过期字段。如果业务需要大规模、高频率的字段级过期,可以考虑拆分成多个 Hash 键,或者用独立键加 EXPIRE 的方式分担压力。
总的来看,Redis 7.4 的 Hash 字段过期特性填补了长期以来的功能空白,让 Hash 类型在缓存和临时数据场景中更加灵活。掌握命令用法、理解删除机制,并注意持久化与复制的行为,就能在实际项目中安全高效地使用这一新能力。
RedisHash Field过期时间修改时间:2026-09-26 09:37:35