expireat和pexpireat分别按秒级和毫秒级时间戳精准设置过期时刻,需注意单位差异、客户端时钟同步、persist后ttl丢失及set命令清除过期时间等问题。

Redis 的过期时间不是“设完就准”,PHP 里用 EXPIREAT 或 PEXPIREAT 才能真正按秒级/毫秒级时间戳精准控制失效时刻,但必须注意时间戳单位、客户端时钟同步、以及 persist 后的 TTL 丢失问题。
EXPIREAT 和 PEXPIREAT 的单位差异容易踩坑
两者都按绝对时间戳设置过期点,但单位不同:EXPIREAT 接收的是**秒级 Unix 时间戳**(10 位数字),PEXPIREAT 接收的是**毫秒级时间戳**(13 位)。混用会导致缓存提前数小时失效,或延后几乎永不删除。
- PHP 中生成秒级时间戳用
time() + 3600,对应$redis->expireat($key, time() + 3600) - 生成毫秒级时间戳得用
round(microtime(true) * 1000),再传给$redis->pexpireat($key, $ms_timestamp) - 直接把
time()结果传给pexpireat,等于设置了「1970 年某个毫秒时间点」,键会立刻过期
PHP 客户端时间不同步时,EXPIREAT 失效逻辑会偏移
如果你在多台 PHP 服务器上批量调用 EXPIREAT,而它们的系统时间相差几秒,那同一组 key 的实际过期时刻就会分散——这不是你想要的“精准控制”,而是意外抖动。更糟的是,若某台机器时钟快了 5 分钟,它设的「2:00 过期」在 Redis 看来其实是「1:55 就该删了」。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 生产环境务必启用 NTP 同步,检查
ntpq -p输出是否稳定 - 避免在客户端算好时间戳再传入 Lua 脚本;应让 Lua 脚本内调用
redis.call("TIME")获取服务端当前时间,再叠加偏移 - 对强时效场景(如支付订单倒计时),优先用
EXPIRE/SETEX配合相对时间,而非依赖绝对时间戳
persist 后忘记重设过期时间,缓存就“假死”了
运维手动执行 PERSIST 清除某个 key 的过期时间很常见,但之后如果 PHP 代码仍假设该 key 会自动过期,比如在缓存重建逻辑里只调用了 set() 没跟 expire(),这个 key 就会长期滞留,占用内存且数据陈旧。
- 每次执行
PERSIST后,必须确认业务代码是否重新设置了 TTL;建议在关键 key 上加监控:定期ttl($key)检查返回值是否为 -1(永不过期) - 在 PHP 缓存封装层中,可统一拦截
set()调用,强制补默认expire(),避免遗漏 - 使用
SET命令时带XX或NX参数不改变原有 TTL,但SET本身会清除过期时间——这点常被忽略
真正难的不是写对那一行 expireat,而是确保时间源一致、操作可追溯、异常后有兜底。Redis 不会提醒你“这个 key 已经三年没更新过 TTL 了”,它只会安静地把旧数据一直留着。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










