问题: 高可用架构之哨兵模式:Redis 哨兵(Sentinel)模式的架构与故障转移流程是怎样的?请说明哨兵集群的选主机制,以及“脑裂”问题是如何产生的?

👇 点击展开/折叠 面试背诵模板(建议先背这个) Redis 哨兵模式是一个分布式监控系统,用于为主从架构提供高可用保障。其核心工作流程分为三步:监控(Sentinel 通过心跳检测节点健康)、通知(故障时发布事件)和自动故障转移。故障转移的触发需经过“主观下线”(单个哨兵认为故障)和“客观下线”(超过 quorum 数量的哨兵达成共识)两个阶段。

随后,哨兵集群会基于 Raft 算法思想选举一个 Leader 哨兵来执行故障转移。Leader 会从健康的从节点中选出新主节点,优先考虑优先级高、数据同步偏移量大的从节点。选主成功后,会执行 SLAVEOF NO ONE 命令将其提升为主,并通知其他从节点和客户端。

“脑裂”问题产生于网络分区等异常情况,导致哨兵集群与主节点失联并选举出新主节点,而原主节点仍在接受客户端写入,造成短时间内集群中出现两个主节点。脑裂会导致数据丢失,因为网络恢复后,旧主节点会被降级为从节点,其数据将被清空。可通过配置 min-replicas-to-write 和 min-replicas-max-lag 来限制主节点在异常情况下的写入,从而降低脑裂数据丢失的风险。


一、哨兵模式架构与核心机制

Redis 哨兵(Sentinel)是一个独立运行的分布式监控系统,它通过监控、通知、自动故障转移和配置提供这四大核心功能,为 Redis 主从集群提供高可用保障。

  • 架构组成:一个完整的哨兵架构由主节点(处理写操作)、从节点(复制数据,作为热备)和哨兵节点(独立监控进程,通常部署3个及以上奇数个)共同构成。
  • 核心工作机制:
    1. 监控(Monitoring):哨兵节点会以每秒一次的频率向所有 Redis 实例(主、从)发送 PING 命令,通过响应来判断其健康状态。
    2. 故障判断:
      • 主观下线(SDOWN):单个哨兵在指定时间(down-after-milliseconds)内未收到 PONG 响应,则认为该节点主观下线。
      • 客观下线(ODOWN):当超过配置的法定人数(quorum)的哨兵都认为主节点主观下线时,主节点被确认为客观下线,从而触发故障转移流程。

二、故障转移与选主流程

当主节点被判定为客观下线后,哨兵集群会自动执行一套标准的故障转移流程。

  1. 选举 Leader 哨兵:为了协调故障转移,哨兵集群需要选举出一个 Leader。该选举过程遵循 Raft 算法的核心思想:
    • 资格与投票:只有标记主节点下线的哨兵才有资格参选。
    • 多数派原则:获得超过半数哨兵投票的节点将成为 Leader。
  2. 选择新主节点:Leader 哨兵会从所有健康的从节点中,根据以下优先级规则选出新主节点:
    • 优先级:首先选择 slave-priority 配置值最高的从节点(值越小优先级越高)。
    • 数据同步度:其次选择复制偏移量(offset)最接近原主节点的从节点,确保数据最新。
    • 运行 ID:若以上都相同,则选择运行 ID 最小的从节点。
  3. 执行故障转移:
    • 对选中的从节点执行 SLAVEOF NO ONE 命令,将其提升为新主节点。
    • 将其余从节点重新配置为复制新主节点。
    • 通过发布订阅(Pub/Sub)机制通知客户端,更新其连接地址。

三、脑裂问题(Split-Brain)的产生与应对

  • 产生原因:脑裂是分布式系统中常见的网络分区问题。主要发生在哨兵集群与主节点之间的网络出现故障,导致哨兵无法与主节点正常通信。哨兵集群因此误判主节点下线,并选举出一个新的主节点。但此时,原主节点仍在运行并可能继续接收客户端的写请求。这就导致在短时间内,集群中存在两个“大脑”(主节点),即脑裂。
  • 后果:脑裂最严重的后果是数据丢失。当网络恢复后,旧主节点会被强制降级为新主节点的从节点,其数据会被清空,并从新主节点重新同步数据。这意味着在脑裂期间客户端写入旧主节点的数据将永久丢失。
  • 防护措施:可以通过配置以下两个参数来限制主节点在异常情况下的写入,从而降低数据丢失的风险:
    • min-replicas-to-write:指定主节点至少需要连接的从节点数量。
    • min-replicas-max-lag:指定从节点与主节点之间允许的最大复制延迟(秒)。
      如果从节点数量或复制延迟不满足这些条件,主节点将拒绝客户端的写入请求。

四、生产环境最佳实践

  • 哨兵节点数量:部署奇数个(至少3个)哨兵节点,以确保在 Leader 选举时能形成多数派,避免投票僵局。
  • quorum 配置:合理设置 quorum 值(通常为哨兵总数的一半加一),以平衡故障检测的灵敏度和准确性。
  • 客户端支持:确保使用的 Redis 客户端库支持哨兵模式,以便能自动处理故障转移和地址更新。