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 这类暂时不用的值一起取回。我不会仅凭这一点宣称接口性能提升了多少,实际收益还与对象大小和网络有关。

需要字段滑动续期时,改用 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”不是一个意思,不能作为不理解默认行为时的通用参数。

旧代码继续使用整键 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。新能力解决的是组合表达,不是替你决定数据何时失效。
-
236 收藏
-
313 收藏
-
484 收藏
-
463 收藏
-
166 收藏
-
250 收藏
-
204 收藏
-
244 收藏
-
173 收藏
-
458 收藏
-
306 收藏
-
146 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习