Cache::store()切换后仍走Redis,因ThinkPHP缓存驱动为实例级单例,未显式指定store的调用仍使用default配置;需统一prefix、serialize和过期时间单位,并通过telnet或dump验证Memcached写入。

为什么 Cache::store() 切换后还是走 Redis?
因为 ThinkPHP 的缓存驱动是「实例级单例」,Cache::store('memcached') 返回的新实例不会自动替换全局默认实例,原有业务代码若直接调用 Cache::get(),仍会走配置里 default 指定的驱动(比如 redis)。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 所有缓存操作必须显式使用
Cache::store('memcached')获取实例后再调用方法,不能依赖未指定 store 的静态调用 - 在
config/cache.php中把default改成memcached,否则Cache::get()这类无 store 参数的调用永远不生效 - 注意中间件、命令行任务、队列 Worker 等上下文是否复用了旧的 Cache 实例——它们可能早于配置切换就被初始化了
Redis 和 Memcached 驱动参数怎么对齐才不丢数据?
两者 key 命名规则、序列化方式、过期时间单位都不同。直接切换会导致大量 Cache::get() 返回 null,看似“缓存失效”,其实是底层读不到。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
-
prefix必须一致:Memcached 默认不加前缀,Redis 默认是thinkphp:,需统一设为空或相同字符串 -
serialize要匹配:Redis 默认用php_serialize,Memcached 默认是igbinary或php;生产环境建议都设为php,避免反序列化失败 - 过期时间:Redis 接受
0表示永不过期,Memcached 把0当作 30 天,需统一用正整数秒(如3600),避免语义错位
如何验证切换后缓存真的写进了 Memcached?
光看应用日志没用,ThinkPHP 不会记录具体驱动的写入细节。得从服务端确认。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 用
telnet 127.0.0.1 11211连上 Memcached,执行stats items查看 item 数量是否增长 - 在代码里加一句
dump(Cache::store('memcached')->get('test_key'));,再手动用get test_key在 telnet 里查,确保值能对上 - 注意 Memcached 的
max_item_size默认是 1MB,如果缓存大对象(如含图片 base64 的数组)会静默失败,set返回STORED但get返回空——这是最常被忽略的兼容性坑
平滑切换期间怎么避免双写不一致?
上线初期不敢全切,想让新老驱动并存跑几天观察。但 Cache::set() 只写一个驱动,没法自动双写。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 封装一个
MultiCache类,内部同时调用Cache::store('redis')和Cache::store('memcached'),写操作发两份,读操作优先读 Memcached,失败再 fallback 到 Redis - 不要用「先删 Redis 再写 Memcached」这种逻辑——并发下可能刚删完 Redis,另一个请求就读到旧值并回写,导致脏数据
- 双写必须带版本号或时间戳,比如用
Cache::set('user:123', ['data' => $x, 'v' => time()]),读取时校验v是否最新,否则跳过
真正麻烦的不是切驱动,而是键值结构、序列化、超时语义这些隐性约定。一旦漏掉某一项,缓存就变成「看起来在跑,其实全失效」的状态。



















