必须显式调用Cache::connect()并传入完整配置重建驱动实例,仅修改config()无效;因缓存驱动为单例复用,连接初始化后不响应运行时配置变更。

ThinkPHP 动态修改缓存连接配置后仍连旧地址,不是配置“没生效”,而是框架在运行时仍复用已初始化的缓存实例——连接一旦建立,后续调用不会自动重连新配置。
缓存驱动实例被单例复用
ThinkPHP 的 Cache 门面或 cache() 函数底层使用单例模式管理驱动实例。首次调用 Cache::get() 或 cache('key') 时,框架根据当前配置创建并缓存一个 Redis/File/Db 驱动对象;之后所有操作都复用该对象,哪怕你中途改了 config('cache.stores.redis.host'),也不会触发重连。
- 验证方式:在修改配置后加
dump(Cache::getStore());,会发现 host/port 仍是旧值 - 根本原因:配置读取发生在驱动初始化阶段,运行时改 config 不等于重置驱动
配置未真正写入运行时上下文
直接调用 config(['cache.stores.redis.host' => 'new.ip']) 只影响配置数组快照,并不通知已加载的缓存驱动刷新连接。尤其在长生命周期环境(如 Swoole、FPM 持久化进程)中,旧连接可能维持数分钟甚至更久。
- TP6/TP8 中
Cache::connect()才能强制重建驱动,但需传完整配置数组,不能只改单个字段 - 若用
Cache::store('redis')->get('key'),store 名称必须与配置中定义的一致,否则 fallback 到默认 store(常是旧配置)
环境或部署层掩盖了配置变更
常见干扰项包括:
立即学习“PHP免费学习笔记(深入)”;
-
.env文件里的CACHE_HOST覆盖了代码中动态设置的值(环境变量优先级高于 runtime config) - FPM 进程未重启,旧进程仍在跑,新配置只对新建请求生效(但连接池可能复用旧 socket)
- Redis 连接池未释放,
phpredis扩展底层复用连接句柄,即使配置变了,connect()调用可能直接返回已有连接
正确切换缓存连接的操作路径
要让新地址立即生效,必须显式重建驱动实例:
- 先清空原有 store 实例:
Cache::clearStore('redis'); - 再用完整新配置重建:
Cache::connect(['type'=>'redis', 'host'=>'new.ip', 'port'=>6379, ...]); - 或指定 store 名重建:
Cache::store('redis')->connect([...]); - 关键点:不要只改 config,要调 connect() 并确保无其他地方提前触发了缓存读写



















