缓存不生效主因是key不一致:查询条件、模型实例、参数形式等微小差异导致md5哈希key变化,无法命中;且app_debug=true时缓存强制失效,调试易误判。

开,但必须明确知道缓存写入和读取是否真正复用,否则开了等于没开。
cache(true) 为什么经常不生效
很多人调用 cache(true) 后发现数据库还是被反复查询,根本原因是:它只在本次查询时生成一个基于 SQL 条件哈希的 key(比如 think:UserModel:md5("where status=1")),但下次执行相同链式查询时,只要中间有任意参数微调(如 order('id desc') 和 order('id','desc') 参数形式不同)、或用了不同模型实例,key 就会变——缓存压根不会命中。
- 缓存 key 是由完整查询条件、表名、模型类名、驱动配置等共同参与 md5 计算得出,极敏感
-
cache(true)不提供可预测的 key 名,调试困难,线上无法主动清理 - 开发环境
app_debug = true时,所有缓存自动失效,容易误判功能异常
cache('key') 的 key 命名陷阱
显式指定 key 看似可控,但实际踩坑最多。例如 cache('user_list') 在多模块、多应用共用同一缓存驱动时,极易冲突。
- key 必须全局唯一,建议带上应用名、模块名、版本号,例如
app_admin_user_list_v2 - 大小写、下划线、冒号都影响 key 实际存储,
userList和user_list是两个缓存 - 如果用
Db::name('user')和UserModel::where(...)分别查同数据,即使 key 相同,底层生成的完整键名也不同(前缀不同),无法共享 - 不要把 key 写死在控制器里,应从配置读取,例如
config('cache.user_list_key')
缓存标签(tag)不是 model::cache() 的参数
文档里写的 cache('key', 3600, 'user') 中第三个参数叫“标签”,但这是误导。ThinkPHP 模型层的 cache() 方法根本不调用底层缓存驱动的 tag() 功能,那个字符串只是拼进 key 里,和真正的缓存标签机制无关。
- 真正支持按 tag 清除,必须绕过
cache(),改用Cache::tag('user')->set($key, $value) - 手动缓存时,记得先
$result->toArray(),否则 Collection 对象反序列化失败 - 用
Cache::tag('user')->clear()只能清掉同 store(如 redis)下打过该 tag 的缓存,file 驱动不支持 tag - 写操作后不清 tag 或 key,是脏数据最常见来源;别指望框架自动感知数据变更
什么时候不该开查询缓存
缓存不是银弹。以下场景强行加 cache() 反而增加负担、掩盖问题:
- 接口每秒请求量低(
- 数据实时性要求高(如订单状态、库存余量),缓存过期时间难设,又不愿写清理逻辑
- 查询带用户 session、token、时间戳等动态条件,key 几乎不复用,纯属浪费磁盘/内存
- 使用了
with()关联但没限制字段,缓存体积暴涨,反而拖慢反序列化
真正省事又安全的做法,是只对「稳定、高频、体积适中」的查询加命名缓存,并配套写操作后的 Cache::rm($key) 或 Cache::tag($tag)->clear() —— 这部分逻辑漏掉,比不开缓存更危险。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











