主节点宕机本身不会直接导致雪崩,但客户端不感知切换、持续打向已下线地址,才会把一次故障放大成全量穿透——这才是雪崩的真正起点。

主节点宕机本身不会直接导致雪崩,但客户端不感知切换、持续打向已下线地址,才会把一次故障放大成全量穿透——这才是雪崩的真正起点。
sentinel get-master-addr-by-name 拉不到新地址的常见原因
客户端仍连着旧 master 地址,不是因为哨兵没切成功,而是它根本没去问哨兵要新地址。典型表现是日志里反复出现 Could not connect to Redis at 192.168.1.100:6379,而新 master 实际已在 192.168.1.101:6379 运行。
- 客户端驱动未启用哨兵模式:比如用
Jedis却直接 newJedis("192.168.1.100", 6379),绕过了JedisSentinelPool - 哨兵地址配置错误:
JedisSentinelPool构造时传的是内网 IP,但应用部署在另一网络段,DNS 或防火墙阻断了与哨兵的通信 - 哨兵未正确监控 master:配置中
sentinel monitor mymaster 127.0.0.1 6379 2写成了本地地址,实际 master 是192.168.1.100,导致哨兵压根没连上主节点 - 客户端缓存了旧地址且未刷新:某些老版本驱动(如 Jedis 2.x)在故障期间不会主动轮询哨兵,需配合
MasterListener监听+switch-master事件手动更新
soTimeout 和 connectionTimeout 必须设为非零值
默认 timeout=0 是最危险的配置,它会让线程卡死在 socket read 上,连接池迅速耗尽,请求堆积,最终拖垮整个应用,比 Redis 宕机本身影响更大。
Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。
-
connectionTimeout控制建连超时,建议设为2000(2 秒),避免 DNS 解析慢或网络抖动时无限等待 -
soTimeout控制命令执行超时,建议设为1000(1 秒),防止某条慢查询阻塞整个连接 - 两者都设为 0,等于放弃超时控制;都设得过大(如 30 秒),会加剧线程堆积和级联超时
- Jedis 3.0+ 中,
JedisSentinelPool构造参数必须显式传入这两个值,不能依赖默认
maxRetries 配置为 0 或极小值才合理
哨兵切换窗口期(通常 20–40 秒)内,客户端若盲目重试,会不断向已下线的旧地址发起连接,形成无效洪峰,白白消耗 DB 连接和 CPU。
- 设
maxRetries=2并配retryInterval=500,意味着最多尝试 3 次(含首次),间隔 500ms,总耗时约 1.5 秒后就该抛异常,交给上层熔断或降级 - 设
maxRetries=0更激进:首次失败立即报错,适合对延迟极度敏感的场景(如支付核心链路) - 绝对不要设
maxRetries=10或更高——这不是容错,是在帮故障延长寿命 - 重试逻辑必须和熔断器联动:例如 Sentinel(阿里)或 Resilience4j 的
CircuitBreaker,连续失败后直接跳过 Redis 走 DB 降级
故障转移后客户端连接池必须重建
很多团队以为只要用了 JedisSentinelPool 就万事大吉,其实它只负责初始化时从哨兵拉地址,后续 master 切换后,池子里的旧连接仍指向原地址,不会自动失效或重连。
- 必须监听哨兵的
+switch-master事件,收到后调用JedisSentinelPool.destroy()+ 重新 new 一个池子 - Spring Boot 2.3+ 的
LettuceConnectionFactory原生支持自动刷新,比 Jedis 更省心,推荐生产环境优先选用 - 若用自研连接池,需确保内部维护的连接列表在
+switch-master后清空并触发重建,否则一半连接有效、一半无效,问题更难排查 - 验证方式很简单:手动 kill master 进程,观察客户端日志是否在 30 秒内出现新地址连接成功记录,而不是持续重连旧地址
真正容易被忽略的,是客户端侧对“切换完成”的定义——它不等于哨兵日志里打出 +switch-master,而等于你的应用真实建立到新 master 的第一条健康连接。中间这几十秒空窗,就是雪崩最肥沃的土壤。










