ThinkPHP 6 配置 Redis Cluster 需替换默认驱动为 Predis 并自定义 RedisCluster 类,强制添加 hash tag 支持 slot 路由,禁用内置 Redis 驱动,配置 nodes 数组及超时参数,不可使用 phpredis 扩展直连因接口不兼容。

ThinkPHP 6 如何配置 Redis 集群(非哨兵,真 Cluster)
ThinkPHP 6 默认的 redis 缓存驱动不支持 Redis Cluster 协议——它只认单节点或哨兵(Sentinel),直接填多个 host 会报 Connection refused 或静默降级为单节点。必须换用原生支持 Cluster 的客户端,并手动接管连接逻辑。
核心路径是:禁用内置 redis 驱动 → 引入 predis/predis(v1.1+)→ 自定义缓存类实现 thinkcachedriverRedis 接口 → 在配置中指定该类。
-
predis/predis是目前 ThinkPHP 6 生态中最稳定兼容 Redis Cluster 的客户端(phpredis扩展本身支持 Cluster,但 TP6 官方驱动未封装其RedisCluster类) - 不要尝试给
cache.php的redis.host写成数组(如['127.0.0.1:7000', '127.0.0.1:7001']),这会被 TP 当作多个单节点轮询,不是 Cluster - 集群模式下,key 必须带 hash tag(即
{user:123}这种),否则Predis无法路由到正确 slot;TP 默认 key 不加 tag,需在自定义驱动里重写doRead/doWrite补上
配置 predis 并启用 Cluster 连接的具体步骤
先安装依赖:composer require predis/predis:^1.1。然后新建 app/cache/driver/RedisCluster.php:
namespace appcachedriver;
use PredisClient;
use thinkcachedriverRedis as BaseRedis;
class RedisCluster extends BaseRedis
{
protected $handler;
public function __construct(array $options = [])
{
$this->options = array_merge([
'scheme' => 'tcp',
'nodes' => [
['host' => '127.0.0.1', 'port' => 7000],
['host' => '127.0.0.1', 'port' => 7001],
['host' => '127.0.0.1', 'port' => 7002],
],
'parameters' => ['password' => null, 'database' => 0],
], $options);
$this->handler = new Client($this->options['nodes'], [
'cluster' => 'redis',
'parameters' => $this->options['parameters'],
]);
}
protected function doRead(string $name)
{
// 强制添加 hash tag,避免跨 slot 路由失败
$tagged = '{' . md5($name) . '}' . $name;
return $this->handler->get($tagged);
}
protected function doWrite(string $name, $value, int $expire = 0)
{
$tagged = '{' . md5($name) . '}' . $name;
if ($expire > 0) {
return $this->handler->setex($tagged, $expire, $value);
}
return $this->handler->set($tagged, $value);
}
}
再修改 config/cache.php:
'default' => 'redis_cluster',
'drivers' => [
'redis_cluster' => [
'type' => 'app\cache\driver\RedisCluster',
'host' => '', // 此处留空,由自定义类内部控制
'port' => '',
'password' => '',
'select' => 0,
],
],
为什么不能直接用 phpredis 扩展 + TP6 原生 Redis 驱动?
因为 TP6 的 thinkcachedriverRedis 底层调用的是 new Redis() 实例,而 phpredis 的 Cluster 支持需要 new RedisCluster(),二者接口不兼容。即使你启用了 phpredis 扩展,TP6 也不会自动切换到 Cluster 模式。
- 错误现象:配置了多个节点却始终只连第一个,或抛出
Uncaught RedisException: Invalid cluster configuration - 若坚持用 phpredis,必须完全绕过 TP 的缓存驱动体系,自己 new
RedisCluster并注册为容器对象(如Container::getInstance()->bind('redis_cluster', function () { ... })),但这样就无法享受Cache::get()等统一接口 -
predis是纯 PHP 实现,对 Cluster 协议封装更完整,且与 TP6 的依赖注入和配置体系更容易对接
连接验证与常见超时问题
集群模式下最常遇到的是连接后卡住或 read error on connection,多数因网络或配置不一致导致:
- 确认所有 Redis 节点已执行
redis-cli --cluster create成功,且redis-cli -c -h 127.0.0.1 -p 7000 cluster nodes返回正常节点列表 -
predis默认无超时,务必在构造参数里加'timeout' => 2.0, 'read_write_timeout' => 2.0,否则一个节点假死会导致整个请求阻塞 - 如果集群启用了密码,
parameters.password必须传字符串(哪怕为空字符串''),传null会触发认证失败 - TP6.3+ 对
serialize类型敏感,若存对象,确保所有节点的php.ini中unserialize_callback_func一致,否则反序列化失败静默返回false
Cluster 不是“多节点堆一起就行”,slot 分配、故障转移、key 路由规则都得对齐,配置错一个参数,可能只在高并发时才暴露问题。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











