最稳妥方式是统一使用Cache::set()的第三个参数设置秒级过期时间,如Cache::set('user:1001', $data, 3600),它自动处理序列化、兼容Redis集群前缀,且避免绕过框架直接调用Redis命令破坏缓存逻辑。

ThinkPHP 用 Cache::set() 设置过期时间最稳妥
ThinkPHP 默认封装了 Redis 缓存驱动,不建议绕过框架直接调用 $redis->setex() 或 $redis->expire(),否则容易破坏缓存键命名规则、序列化逻辑或标签管理。正确方式是统一走 Cache::set() 的第三个参数:
-
Cache::set('user:1001', $data, 3600)—— 秒级过期,等价于 Redis 的SETEX -
Cache::set('token:abc', $token, 300)—— 5 分钟后自动清理,无需手动expire - 如果传
0或负数(如-1),部分版本会设为永不过期,但行为不稳定,应避免
注意:该方法底层会自动处理序列化(如 serialize() 或 json_encode()),且兼容 Redis 集群模式下的键前缀配置(如 prefix 选项)。
别在 Cache::remember() 里漏掉过期参数
Cache::remember() 是常用缓存查询封装,但很多人只写前两个参数,导致缓存永不超时:
- ❌ 错误写法:
Cache::remember('user_list', function () { return Db::table('user')->select(); });—— 没传过期时间,默认可能永不过期 - ✅ 正确写法:
Cache::remember('user_list', 1800, function () { return Db::table('user')->select(); });—— 明确设为 30 分钟 - ThinkPHP 6+ 支持数组形式传参,例如
Cache::remember('key', ['ttl' => 600], $callback),更清晰
漏掉这个参数是线上内存暴涨的常见源头——尤其当 remember() 被用于高频接口且结果集较大时,缓存会持续堆积。
Redis 过期策略本身不保证“准时删除”
ThinkPHP 设了 TTL,不代表 Redis 会在整点秒级精准删掉 key。它依赖“惰性删除 + 定期删除”双机制:
- 惰性删除:只有你
Cache::get('key')时,Redis 才检查是否过期并顺手删掉;若 key 一直没人访问,它就赖在内存里 - 定期删除:Redis 每 100ms 随机抽 20 个带过期时间的 key 检查,删掉其中过期的;所以大量 key 同一时刻设为 3600 秒,大概率会在第 3600 秒前后集中触发批量清理压力
- 后果:内存不会突降,但
INFO memory里的used_memory_peak可能悄悄升高;redis-cli --stat可观察到expired_keys突增
因此防内存暴涨不能只靠“设了过期时间”,还得配合错峰和监控。
真正防内存暴涨要盯住三件事
过期时间只是手段,不是保险丝。以下三点漏掉任意一个,都可能让 Redis 内存缓慢爬升甚至 OOM:
- 避免批量 key 同一时刻过期:比如不要全用
Cache::set($key, $val, 3600),改用rand(3600, 4200)加随机抖动 - 检查 Redis 配置中的
maxmemory和maxmemory-policy:ThinkPHP 不管这个,但它是兜底防线;推荐设为allkeys-lru或volatile-lru,别留空 - 定期用
redis-cli --bigkeys或MEMORY USAGE user:*查大 key;有些业务误把图片 base64 或日志 dump 进缓存,过期时间再短也扛不住单 key 几 MB
最常被忽略的是:ThinkPHP 的缓存标签(tag)功能默认不支持 Redis 原生过期,Cache::tag('list')->set() 存的 key 实际无 TTL,必须手动管理或换用其他方案。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











