redis哨兵模式本身不支持读写分离,仅负责故障检测与自动转移;读写分离需由客户端(如lettuce配置readfrom)或proxy层(监听哨兵事件动态更新节点列表)实现。

Redis 哨兵模式本身不支持读写分离
哨兵(Sentinel)只负责故障检测、自动故障转移和配置通知,它不会代理客户端请求,也不提供读写路由能力。所谓“哨兵实现读写分离”,其实是误解——真正承担读写分离职责的是客户端或中间代理层。
常见错误现象:Sentinel.get_master_address_by_name() 返回主节点后,客户端仍把所有请求发给它;或者误以为哨兵会自动把 READONLY 请求转发到从节点,实际并不会。
- 哨兵只暴露
sentinel monitor、sentinel failover等管理命令,不监听客户端 Redis 协议端口 - 客户端必须自己识别角色:通过
INFO replication或ROLE命令判断节点是 master 还是 slave - 若用 Jedis、Lettuce 等客户端,需手动启用 read-from-slave 配置(如 Lettuce 的
ReadFrom.REPLICA_PREFERRED),且该行为与哨兵无关,只依赖节点发现结果
Proxy 层才是读写分离 + 动态扩容的关键载体
真正实现“根据哨兵状态动态调整读节点池”的,是 Proxy(如 Redis-Proxy、Twemproxy 扩展版、Codis、Redis Cluster Proxy 或自研网关)。哨兵在这里只充当元数据源,Proxy 定期调用 SENTINEL slaves <master-name></master-name> 获取从节点列表,并实时更新内部路由表。
使用场景:需要对业务无感地增减从节点,同时保证读请求不打到正在同步或断连的从节点上。
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
- Proxy 必须解析哨兵返回的每个从节点的
flags字段(如slave,online或slave,disconnected,sdown),过滤掉不可用节点 - 扩容从节点时,需等待其状态在哨兵中变为
online且lag (可通过 <code>SENTINEL sentinels <master-name></master-name>查 lag),Proxy 才将其加入读池 - 避免轮询式健康检查:Proxy 应监听哨兵的
+slave/-slave事件(通过SENTINEL subscribe),而非固定间隔拉取
Letture + Sentinel 实现轻量级动态读写分离(无 Proxy 场景)
如果不想引入 Proxy,Lettuce 是目前最稳妥的选择。它支持基于哨兵自动发现 + 内置读策略,但必须正确初始化并处理连接生命周期。
容易踩的坑:StatefulRedisMasterSlaveConnection 不会自动感知新从节点上线,除非重建连接池或触发 refreshPartitions()。
- 初始化时用
RedisURI.Builder.sentinel()构造 URI,传入多个哨兵地址,而非只写一个 - 启用
ClientResources.builder().dnsResolver(new DnsResolvingResourceResolver()),防止 DNS 缓存导致节点 IP 更新延迟 - 设置
ReadFrom.MASTER_PREFERRED而非MASTER,否则从节点宕机时会直接报错,无法降级 - 务必监听
ConnectionEvents.CONNECTED和ConnectionEvents.DISCONNECTED,在断连后主动调用ClusterTopologyRefreshOptions.builder().enableAllAdaptiveRefreshTriggers()
动态扩容时最易忽略的三个状态点
扩容一个从节点后,系统未必立刻可用。以下三个状态必须全部满足,读流量才能安全切过去:
- 哨兵中该节点显示为
slave,online(SENTINEL slaves mymaster输出中 flags 包含这两个词) - 该节点的
offset与主节点master_repl_offset差值 ≤ 5000(INFO replication中比对),否则存在明显复制延迟 - Proxy 或客户端能成功建立 TCP 连接并完成 AUTH(如有密码),且执行
PING返回PONG—— 很多时候防火墙或 TLS 配置漏改,导致连接被静默拒绝
别只盯着哨兵日志里有没有 +slave,这三个条件缺一不可。尤其是 offset 差值,线上曾有扩容后读到脏数据的案例,根源就是从节点还在追日志,但 Proxy 已把它纳入负载池。










