生产环境连接 Redis 集群应优先选用 Predis\Client,因其内置集群拓扑发现、自动重定向、重试及故障转移机制;而 phpredis 原生扩展不支持 MOVED/ASK 重定向,易抛异常。

PHP 连 Redis 集群用 Predis\Client 最稳
原生 Redis 扩展(phpredis)对 Redis Cluster 的支持非常有限——它不自动重定向、不识别槽位迁移、遇到 MOVED 或 ASK 错误就直接抛异常。所以生产环境连 Redis 集群,Predis 是更可靠的选择,它内置了集群拓扑发现、重试、重定向和故障转移逻辑。
安装方式:
composer require predis/predis
关键点:
-
Predis默认启用cluster => 'redis'模式,会自动解析多个节点并维护槽映射表 - 连接时传入的是节点列表(不是单个地址),它会主动
CLUSTER NODES获取拓扑 - 不建议手动指定 slots 映射,除非你有强一致性的分片控制需求
初始化集群客户端要传节点数组,别只写一个地址
常见错误是把集群当单机用,只传一个 tcp://127.0.0.1:7000,这样 Predis 无法发现其他节点,后续命令可能因槽位不在该节点而失败。
立即学习“PHP免费学习笔记(深入)”;
正确写法示例:
$client = new Predis\Client([
'scheme' => 'tcp',
'cluster' => 'redis',
'parameters' => [
'password' => 'yourpass',
'database' => 0,
],
'nodes' => [
['host' => '192.168.1.10', 'port' => 7000],
['host' => '192.168.1.10', 'port' => 7001],
['host' => '192.168.1.10', 'port' => 7002],
// 至少包含 3 个主节点(推荐全量主从节点都列上)
],
]);
说明:
-
nodes数组里尽量包含所有主节点;如果知道从节点地址,也可以加上,Predis会按需读取 - 如果集群启用了密码,必须在
parameters里统一配password,不能每个 node 单独设 - 首次连接会触发拓扑拉取,耗时略高,建议复用
$client实例,不要每次请求都 new
执行命令时 key 必须带 hash tag 才能跨节点协作
Redis Cluster 要求同一个命令涉及的 key 必须落在同一槽位,否则报 CROSSSLOT Keys in request don't hash to the same slot。比如 MGET key1 key2,如果这两个 key 的 CRC16 不同,就会失败。
解决办法是用花括号包住公共部分,强制哈希到同一槽:
-
user:{123}:profile和user:{123}:settings→ ✅ 同槽 -
user:123:profile和user:456:settings→ ❌ 可能不同槽 -
HMGET user:{123} name age email→ ✅ 支持 -
PIPELINE中多个命令若涉及不同槽的 key,也会被拒绝
注意:Predis 不会帮你加 hash tag,这是业务层必须遵守的约束。
超时、重试、断线这些得自己兜底
Predis 默认不开启自动重试,网络抖动或节点临时不可用时,ConnectionException 或 ServerException 会直接冒泡。集群场景下节点状态变化频繁,建议加一层容错:
- 用
try/catch捕获Predis\Connection\ConnectionException和Predis\Response\ServerException - 对非事务性操作(如
GET、SET)可简单重试 1–2 次 - 设置合理的超时:
'connections' => [ 'tcp' => [ 'timeout' => 1.0, 'read_write_timeout' => 1.0, ], ] - 避免在长循环里反复 new client;连接池不是必需,但连接复用 + 异常后重建实例是基本操作
集群拓扑变更(如扩缩容、failover)后,Predis 会在下次命令出错时自动刷新节点列表,但这个过程不是实时的——如果刚好卡在旧拓扑里,可能短暂失败。这点容易被忽略,线上要留监控看 ClusterDownException 出现频率。











