Redis 6.0 Docker版MULTI事务中EXPIRE设置后key异常失效问题
结论
该异常完全是由Redis容器和宿主机的时钟严重偏差导致,根本原因和Redis过期时间的实现逻辑、树莓派32位系统的2038年时间溢出特性直接相关。
原因解释
- Redis的
EXPIRE命令传入的是相对过期秒数,Redis内部会自动转换为基于自身运行环境系统时钟的绝对时间戳,存储为key的过期元数据。只要当前系统时钟超过这个绝对时间戳,key就会被判定为过期。 - 你提供的输出显示容器时钟跳到了2071年,对于32位树莓派系统来说,这是典型的
time_t溢出问题(32位有符号整数最大只能表示到2038年的时间,溢出后会出现时间跳变到几十年后的异常)。此时计算相对过期时间的绝对时间戳时,会出现逻辑混乱:- 设置100秒过期时,换算出的绝对时间戳刚好落在Redis判定的「已过期」区间,因此事务执行完key立刻被清理,查询返回空集
- 设置200秒过期时,换算出的绝对时间戳刚好落在「未过期」区间,因此查询正常返回结果
- 非事务场景下命令是逐条立即执行,过期时间计算的时序和事务场景(所有命令入队后一次性执行)存在差异,刚好避开了溢出的异常区间,因此表现正常。
修复方案
- 运行Redis容器时挂载宿主机的时间配置,保证容器和宿主机时钟同步:
docker run -d \ -v /etc/localtime:/etc/localtime:ro \ -v /etc/timezone:/etc/timezone:ro \ --name redis \ redis:6.0
- 如果使用的是32位树莓派操作系统,建议升级到64位版本,从根本上解决2038时间溢出问题。
- 临时验证可手动将容器时间修改为和宿主机一致,重新测试100秒过期的事务即可复现正常结果。
内容的提问来源于stack exchange,提问作者cdupont
相关产品推荐
相关产品推荐

