ThinkPHP连Redis哨兵必须用sentinels配置而非host,否则无法触发哨兵发现逻辑;集群模式需自定义RedisCluster驱动,禁用Tag功能,哨兵密码需单独配置,tag_prefix在集群下无效。

ThinkPHP 连 Redis 哨兵必须用 sentinels 而不是 host
直接写 host 指向某个哨兵节点,TP 会当普通 Redis 实例连,根本不会触发哨兵发现逻辑——连接成功但主从切换后立刻报错 READONLY You can't write against a read only replica。
正确做法是显式声明哨兵集群地址,并让 TP 驱动走 SentinelConnection 流程:
-
'type' => 'redis'(不能写redis-sentinel,TP 没这个类型) -
'host' => ''(留空,否则驱动优先走 host 直连) 'sentinels' => [['host' => '192.168.1.10', 'port' => 26379], ['host' => '192.168.1.11', 'port' => 26379]]-
'sentinel_master' => 'mymaster'(和哨兵配置里的sentinel monitor名称严格一致)
Redis 集群模式下 cache 方法不支持哈希槽自动重定向
TP 自带的 RedisCache 类底层调用的是 phpredis 的 connect(),而集群模式必须用 open() 或 create() 初始化 RedisCluster 实例——否则所有 set/get 请求都发到第一个节点,遇到跨槽 key 直接抛 MOVED 错误。
绕过方法只有两个:
立即学习“PHP免费学习笔记(深入)”;
- 改用
think-queue或第三方扩展里封装好的RedisClusterCache(需确认是否兼容当前 TP 版本) - 手动在
config/cache.php中注册自定义驱动,newRedisCluster实例并传入完整节点列表:['192.168.1.20:7000','192.168.1.20:7001',...] - 避免在集群环境用
Tag功能——TP 的 tag 实现依赖 keys 扫描,集群不支持
哨兵 + 密码场景下 auth 参数位置极易填错
哨兵本身可能设了密码(requirepass),主从节点也可能单独设密码(masterauth 和 requirepass),TP 配置里只有一处 password 字段,但它只作用于最终选中的 master/replica 连接,**对哨兵通信无效**。
结果就是:哨兵能连上,但取 master 地址时因没认证被拒绝,报错 NOAUTH Authentication required。
解决方案:
- 确保哨兵配置中
requirepass和masterauth一致(推荐) - 在
sentinels数组每个节点里加'password' => 'xxx'字段(TP 6.1+ 支持,低版本需打补丁) - 检查
sentinel.conf是否开启sentinel auth-pass <master-name> <pass>,漏配会导致哨兵间认证失败
缓存驱动切换后 Tag 失效且无提示
TP 的 Tag 功能底层靠前缀 + keys 扫描实现,Redis 单机/哨兵可用,但集群模式禁用 keys 命令——驱动切换后调用 $cache->tag('user')->set('1001', $data) 看似成功,实际数据没写入,后续 get 返回 null,也不报错。
这不是 TP bug,是 Redis 集群设计限制。真要用 tag,只能:
- 降级回哨兵或单机模式
- 改用业务层模拟 tag:把 tag 名拼进 key,比如
user:1001、user:1002,批量清理时用scan游标遍历(注意 scan 不保证实时性) - 放弃 tag,用更细粒度的 key 命名 + 设置合理过期时间
最常被忽略的一点:TP 缓存配置里 'prefix' 在集群下仍生效,但 'tag_prefix' 字段压根不参与集群驱动初始化——这个字段只在单机/哨兵驱动里读取。



















