登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis Hash 怎样一次读取多个字段并设置 TTL

来源:17golang原创

时间:2026-10-23 04:56:36 104浏览 收藏

Redis Hash 一次读取指定的多个字段用 HMGET;如果还要在同一条命令中设置这些字段的 TTL,Redis 8.0 起可以用 HGETEX key EX 秒数 FIELDS 字段数 字段...。若你要的是整个 Hash 一起过期,则应使用整键 EXPIRE,不要把字段续期误当成整键续期。

官方地址:https://redis.io/docs/latest/commands/hgetex/

我会先确定,到期的是字段还是整个对象

假设我要给一个商品卡片接口设计缓存:Hash 里有 name、stock 和 note,接口只展示 name 与 stock。我会先问“访问一次后,是让这两个字段继续有效,还是让整个卡片继续有效?”这比先选客户端方法更重要。这里是用于说明取舍的设计场景,不是一次真实线上改造记录。

Redis 7.4 增加了 Hash 字段级过期能力,8.0 又增加 HGETEX,把读取与设置字段过期时间放进一个命令。对我来说,方便之处是少拼接一次字段续期操作;需要适应的地方则是:带续期的读取有写副作用,不能再当成普通只读查询。

目标选择过期范围
只取所需字段HMGET不主动设置 TTL
读取并续期所选字段HGETEX,Redis 8.0 起指定字段
整个缓存对象一起过期EXPIRE整键及其全部字段

只需要两个字段,我不会先取 HGETALL

# 以下仅供隔离测试实例尝试;不要使用已有业务键
redis-cli HSET 'demo:hash171:card' name '收纳盒' stock '32' note '演示数据'

# 返回顺序按请求字段排列;missing 不存在时保留空值位置
redis-cli HMGET 'demo:hash171:card' stock name missing

这里 HMGET 的三个位置依次对应 stock、name、missing。即使最后一个字段不存在,也不要把它从数组里过滤后再和原字段名配对,否则字段映射会错位。不存在的键被视为空 Hash;整组空值不自动等于服务异常,也可能是缓存未命中。

HGETALL 用于需要全部字段和值的场景。只要固定的两个字段时,HMGET 的字段清单更直接,也避免把 note 这类暂时不用的值一起取回。我不会仅凭这一点宣称接口性能提升了多少,实际收益还与对象大小和网络有关。

Hash字段与按需读取的静态关系
静态结构图:存储边界包含卡片字段,读取边界表达 HMGET 的字段清单与返回位置关系;不是控制台截图或实测结果。

需要字段滑动续期时,改用 HGETEX

# Redis 8.0 起:读取 name、stock,并把所选字段的 TTL 设为 120 秒
redis-cli HGETEX 'demo:hash171:card' EX 120 FIELDS 2 name stock

# 查看字段剩余秒数;执行间隔会使读数下降,不要求固定等于 120
redis-cli HTTL 'demo:hash171:card' FIELDS 2 name stock

# 这是整键剩余时间,不是字段剩余时间;本例没有给整键设置过期
redis-cli TTL 'demo:hash171:card'

FIELDS 后面的 2 是字段个数,不是值的数量;EX 的单位是秒,PX 则是毫秒。此例只续期 name 和 stock,note 不因此获得字段 TTL。应用每次访问都执行这条 EX 120 命令,就会把所选字段的截止时间向后推,这适合明确允许滑动续期的缓存。

如果对象的业务有效期不可延长,我会保留只读查询,而不是为了少写代码给每次读取附上续期。HGETEX 也提供 PERSIST 去除字段过期时间,它与“保留原 TTL”不是一个意思,不能作为不理解默认行为时的通用参数。

整键过期和字段过期的边界
静态结构图:整键策略与字段策略分别关联不同作用范围;整键删除会影响其中所有字段,HTTL 不能用 TTL 替代。

旧代码继续使用整键 TTL,不必为新命令改模型

如果整个卡片本就应该同生共死,我更倾向于保留整键 TTL。以下是独立的第二组演示数据,避免继承前面已经设置的字段 TTL。

# 独立测试键:所有字段共享整键生命周期
redis-cli HSET 'demo:hash171:whole' name '文件袋' stock '15'

# 批量读取本身不刷新 TTL;这两条是独立请求,不是原子操作
redis-cli HMGET 'demo:hash171:whole' name stock
redis-cli EXPIRE 'demo:hash171:whole' 180

# 返回整键剩余秒数,过期后整个 Hash 都不可用
redis-cli TTL 'demo:hash171:whole'

这组 HMGET 与 EXPIRE 之间可以夹入其他客户端操作,不能描述成一次不可分割的“读并续期”。需要组合原子性时应单独设计事务或脚本及错误处理,不能把 pipeline 的少往返当成原子性。

Redis 7.4 支持字段 TTL、但还没有 HGETEX 时,可以组合 HMGET 与 HEXPIRE;那仍是两条命令,不应冒充新命令的单命令语义。更老的部署不能直接获得原生字段 TTL,需保留整键方案或调整数据模型。托管服务还要考虑服务实际开放的命令和账号权限。

我会把续期视为缓存契约的一部分

有两个细节会影响我的选择。第一,HSET 修改 Hash 字段通常不清除整键 TTL,却会清除被覆盖字段自己的字段 TTL;更新值和更新有效期要一起规划。第二,整键过期与字段过期可以同时存在,但字段续期不能让一个已过期的整键继续存在。

本文未运行这些命令,所述为读者尝试时的预期判断:HMGET 应按字段顺序映射空值;HGETEX 后用 HTTL 查看字段,整键方案用 TTL 查看整键。别用“读到了值”替代“设置了所需范围的有效期”,更不要把传输失败包装成缓存未命中。

相关问题

HMGET 能直接加 EX 参数吗? 不能按 HGETEX 的语法给 HMGET 加过期选项;先确认自己需要哪种 TTL。

HGETEX 可以放到只读节点的查询链路里吗? 它是写类别命令,不能因为名称带 GET 就当成普通只读命令路由。

为什么字段快过期了,TTL 却显示没有过期设置? TTL 看整键,字段要用 HTTL;两者可以给出不同状态。

我的选择是:字段独立生命周期且允许访问续期时考虑 HGETEX;整个对象共享生命周期时保留整键 TTL;纯展示接口则继续 HMGET。新能力解决的是组合表达,不是替你决定数据何时失效。

技术参考:HGETEX、HMGET、HEXPIRE、EXPIRE。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>