主从切换后客户端继续往只读节点发写命令是连接错位而非缓存穿透,必须每次写前执行ROLE命令校验节点角色,返回slave则立即丢弃连接,禁用PING检测改用语义化验证,并定期刷新拓扑。

主从切换后客户端继续往只读节点发写命令,不是缓存穿透,是连接错位——必须主动校验角色,不能等 READONLY 错误才反应。
每次写前必须执行 ROLE 命令验证节点角色
客户端 SDK 不会自动感知主从切换,READONLY You can't write against a read only replica 是结果,不是信号。靠捕获这个错误再重试,至少浪费一次请求,还可能触发下游重试放大流量。
- 在发任何写命令(如
SET、INCR)前,先同步执行ROLE,检查返回是否为["master"] - 若返回
["slave", ...],立即丢弃当前连接,不发业务命令 - 避免用异步或批量方式做角色检查——写操作必须串行化校验,否则可能漏判
- 注意:
ROLE本身是只读命令,不会被拒绝,即使连的是从节点也能成功返回
连接池要禁用 PING 检测,改用语义化健康检查
很多连接池默认开启空闲连接的 PING 探活,但 PING 成功 ≠ 节点可写。主从切换后,旧主变从,PING 仍通,连接却被复用,问题照旧。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 关闭连接池的
testOnBorrow/validationQuery=PING类配置 - 改为在借出连接时执行
ROLE,并缓存结果时间戳(如lastRoleCheckAt) - 设阈值(如 30 秒),超时即重检;不要依赖固定周期轮询,避免无谓开销
- 连接池空闲驱逐时间建议设为 2–5 分钟,太长会导致“僵尸连接”滞留
Redis Cluster 客户端必须定期刷新拓扑,不能只靠启动加载
RedisCluster(如 phpredis)、Lettuce 等支持 Cluster 的客户端虽有自动重定向能力,但拓扑视图是静态快照。节点 IP 变更、槽迁移后,若不刷新,仍会持续打向旧地址。
- 启用
CLUSTER SLOTS定期拉取(如每 30 秒),而非仅在初始化时调用一次 - 监听
MOVED/ASK重定向响应,触发局部拓扑更新,但别全量 reload - 使用哨兵时,收到
+switch-master事件后,必须调用refreshSentinels()或等效方法(如 Jedis 的sentinelRefresh()) - 绝对不要硬编码节点 IP —— 直连模式下,客户端永远追不上切换速度
别把 READONLY 当熔断依据,要分层响应
单次 READONLY 报错可能是误发命令、临时网络抖动,甚至某个从节点被错误标为主。直接据此关闭整个连接池,容易引发雪崩。
- 第一次遇到
READONLY:只记录日志 + 上报监控,标记该连接为“待验证”,不熔断 - 同一连接连续 2 次写命令都返回
READONLY:立即关闭并从池中移除 - 连接池中超过 30% 连接被标记为“待验证”:触发全量拓扑刷新(如重拉
SENTINEL GET-MASTER-ADDR-BY-NAME) - 注意:
ROLE返回["master"]也不绝对可靠——得结合实际写命令是否成功闭环验证
真正卡点从来不在数据同步是否完成,而在客户端有没有及时拿到新主的真实地址、有没有在发写命令前确认权限。所有“优雅”都建立在主动验证和快速丢弃上,而不是等错误发生再补救。

















