phpredis + laravel 7.x 无法直接配哨兵,因其 phpredisconnection 驱动仅支持固定 host/port,不解析 sentinel 配置、不调用 sentinel 命令,硬加 sentinels 选项会报错,且连接始终直连旧 master 导致故障后 connection refused。

phpredis 本身不原生支持 Redis Sentinel 自动发现与故障转移,Laravel 7.x 默认也**不兼容哨兵模式下的 phpredis 客户端**。你必须绕过 Laravel 的默认连接逻辑,手动构造带哨兵感知能力的 Redis 实例,或改用 predis ——它对 Sentinel 有开箱即用的支持。
为什么 phpredis + Laravel 7.x 无法直接配哨兵
Laravel 7.x 的 phpredis 驱动(Illuminate\Redis\Connections\PhpRedisConnection)只接受固定 host/port,不解析 sentinel 配置项,也不调用 sentinel get-master-addr-by-name。即使你在 .env 或 config/database.php 里硬塞 sentinel 字段,它会被忽略。
- 尝试在
redis.default中加'sentinels' => [...]→ 启动报错:Unknown option sentinels - 用
Redis::connection()获取连接 → 仍是直连,不走哨兵发现流程 - 哪怕哨兵集群正常运行,
phpredis仍会死连旧 master IP,故障后直接Connection refused
可行方案:用 predis 替代 phpredis(推荐)
predis/predis 支持原生 Sentinel 连接,Laravel 7.x 官方也明确支持该客户端。只需三步:
- 执行
composer require predis/predis(确保没装phpredis扩展冲突) - 在
.env中设REDIS_CLIENT=predis,并改用哨兵配置格式:
REDIS_CLIENT=predis REDIS_HOST=null REDIS_PORT=null REDIS_PASSWORD=null REDIS_SENTINEL_HOSTS=192.168.242.41:26379,192.168.242.42:26379,192.168.242.43:26379 REDIS_SENTINEL_SERVICE=mymaster REDIS_DB=0
- 修改
config/database.php的redis.default部分,用options注入哨兵参数:
'default' => [
'scheme' => 'tcp',
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
'options' => [
'replication' => 'sentinel',
'service' => env('REDIS_SENTINEL_SERVICE', 'mymaster'),
'parameters' => [
'password' => env('REDIS_PASSWORD'),
'database' => env('REDIS_DB', 0),
],
'sentinels' => array_map(function($h) {
[$host, $port] = explode(':', $h);
return ['host' => $host, 'port' => (int)$port];
}, explode(',', env('REDIS_SENTINEL_HOSTS', ''))),
],
],
- 确认
REDIS_PASSWORD是主节点密码(不是哨兵密码),且哨兵配置中已设sentinel auth-pass mymaster your_password
强行用 phpredis?只能手写连接管理器
如果你因历史原因必须用 phpredis(比如已有大量 Redis:: 调用、或扩展已强制安装),那就得自己封装一个哨兵感知的连接池:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 写一个
SentinelRedisManager类,启动时调用redis-cli -h sentinel-host -p 26379 SENTINEL get-master-addr-by-name mymaster获取当前 master 地址 - 定期轮询(如每 5 秒),或监听
__sentinel__:hello频道捕获 failover 事件 - 把新地址注入
Redis实例,并替换 Laravel 的默认连接(需重写RedisServiceProvider) - 所有
Redis::调用必须经过你的代理层,不能直连Redis原生类
这工作量远超换 predis,且容易漏掉重连、连接复用、超时等边界问题。
验证是否真走哨兵
别只看 php artisan tinker 能连上就以为 OK。真实故障转移时,关键看两点:
- 手动 kill 主节点后,
Cache::get('test')是否在 30 秒内自动恢复(不是抛异常) - 查日志:
tail -f storage/logs/laravel.log,确认没有Connection refused或Failed to connect - 进哨兵节点执行:
redis-cli -p 26379 SENTINEL masters,看ip和port是否已更新
最容易被忽略的是:哨兵配置里的 quorum 值(如 sentinel monitor mymaster ... 2)必须 ≤ 实际运行的哨兵数,否则故障转移不会触发 —— 这个值在 Laravel 配置里完全不体现,纯靠运维侧保障。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










