连载中 14/20

哨兵:主从架构的自动值班员

2026-06-01 · 2291 阅读 · 0 评论 · 0 赞

半夜三点,谁去切主

主从复制解决了读扩展与数据冗余,但留了个没人接的活:主库挂了,故障转移靠谁。人工切换意味着半夜告警、手忙脚乱、停服窗口;Redis Sentinel(哨兵)把这个活自动化——它本身不存数据,是一组独立运行的监控进程,干的就一件事:盯着主从,主库失联时自动把合适的从库提升为新主库,再把客户端指过去。

下线判定:一票不算,多数投票

哨兵判定主库故障是两段式的,处处透着「别误判」的谨慎。主观下线(sdown):单个哨兵在 down-after-milliseconds 内没收到主库的合理回复,它自己记一笔「我觉得主库挂了」——可能只是这个哨兵自己网络抽风。客观下线(odown):这个哨兵去问其他哨兵「你们觉得呢」,达到 quorum 配置的票数,主库被正式定性为客观下线——网络抖动、哨兵单点故障都被这套仲裁挡在误判之外。

定性之后还有一场选举:多个哨兵协商出一个领队哨兵(leader)来执行切换,选举规则用的就是熟悉的 Raft 多数派思想——必须拿到过半哨兵的同意。所以哨兵要至少部署三个、且奇数:两个哨兵挂一个就凑不出多数派,整套机制瘫在半空。领队选出后执行 failover:从从库里挑一个数据最新的(优先看 offset),提升为新主库,其余从库改挂到新主,旧主恢复后降级为从库。

客户端怎么找到主库

故障转移之后主库地址变了,客户端不能写死 IP——接入哨兵架构时,客户端配置的是哨兵的地址列表,用的时候先问哨兵「主库是谁」,拿到地址再连。主库切换后,哨兵会在订阅频道里发布新主库地址,客户端收到通知刷新本地缓存。这一步让「切换」对业务代码完全透明:

JedisSentinelPool pool = new JedisSentinelPool(
    "mymaster",                       // 主库逻辑名
    Set.of("10.0.0.1:26379",          // 哨兵列表,不是redis地址
           "10.0.0.2:26379",
           "10.0.0.3:26379"),
    poolConfig, "pass");
// 读写主库地址由哨兵实时告知,切换自动跟随

脑裂:旧主还魂的那几秒

哨兵架构有个著名的暗坑叫脑裂:主库与从库之间网络分区,哨兵们判主库客观下线、把某个从库提升为新主——但旧主库还活着,客户端(尤其是没及时收到通知的)还在往旧主写数据。分区恢复后旧主降级为从库、全量同步新主的数据,分区期间写进旧主的那几秒数据,全部蒸发。缓解手段是 min-replicas-to-write 1:主库至少有一个从库在线才接受写入——被孤立的旧主写不进数据,蒸发窗口被大幅压缩。防不到零,但够用。

哨兵解决了高可用,但主从架构的内存天花板没变:一台机器装不下的数据量,加再多从库也没用。哨兵管可用性,数据分片找 Cluster——横向扩展的最后一讲,下一篇收官这个话题。

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#Sentinel#哨兵#故障转移#主观下线#客观下线#脑裂

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10101 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9873 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9294 阅读 · 21 评论 · 287 赞