Redis的脑裂问题

一、Redis集群的脑裂定义

Redis集群的脑裂问题,是指在集群的主从节点中,同时存在 2 个主节点能够同时对客户端提供读写服务,而导致数据丢失 或者 不一致的问题


二、Redis的脑裂分类

  • 哨兵(sentinel)模式下的脑裂

  • 集群(cluster)模式下的脑裂


三、哨兵(sentinel)模式下的脑裂,多发生在网络分区故障 或者 主节点短暂网络故障的场景


1、网络分区故障的场景是指: 主从节点和哨兵三者被分割成了 2 个网络,其中,主节点位于一个单独的网络,而从节点和哨兵则位于另一个单独的网络,

两个网络之间无法相互访问。此时,一部分客户端会继续访问主节点;而另外一个网络,哨兵发现和主节点连接不上了,就会触发故障转移,重写选举一个新的主节点。

这样一个集群中对外就出现 2 个主节点的情况


2、主节点短暂【假死】网络故障的场景是指:主节点因为所在的主机的资源问题 或者 其它原因,比如正在处理 bigkey 等而导致主节点短时

间内无法响应哨兵发出的心跳,从而会触发故障迁移,重写选举一个新的主节点。但是等主节点恢复服务后,该集群中对外就出现了 2 个主节点


3、Redis集群的脑裂问题,可能会导致数据丢失 或者 数据不一致


四、集群(cluster)模式下的脑裂,多发生在网络分区故障


如果 多个 Redis Cluster 由于网络问题变成两个孤立的子集群,那么这两个子集群可能会各自选举 Master,导致脑裂


五、Redis 集群脑裂的影响


1、数据丢失

  • 选出来的 新 Master会向所有的从节点发送 slave of 命令,让这些从节点跟其 新 Master 重新建立主从关系,让所有从节点进行全量同步,

而全量同步首先就会将从节点上的原有数据清空,所以在主从同步期间从节点在原来那个旧 Master上同步的命令将会被清空


2、数据不一致

  • 客户端 A 连接 Master 1,写入 set key "A";

  • 客户端 B 连接 Master 2,写入 set key "B";

  • 最终,集群恢复时,两个 Master 可能有不同的数据,导致数据不一致


3、客户端请求异常

  • 由于某些客户端可能连接到旧 Master,而其他客户端连接到新 Master,导致数据查询不一致或部分请求失败


六、如何防止Redis集群的脑裂问题 ?


Redis本身已经为我们提供了如下 2 个配置项来避免脑裂问题,这两个配置必须同时满足,不然主节点会拒绝写入

  • 第一个参数表示,连接到 master 的最少 slave 数量,建议这个数量按照超过集群半数配置

  • 第二个参数表示,主从节点数据复制时,从库给主库发送 ACK 消息的最大延迟秒数


按照上面的配置,要求至少3个slave节点,且数据复制和同步的延迟不能超过10秒,否则的话master就会拒绝写请求,


配置了这两个参数之后,如果发生集群脑裂,原先的 master节点 接收到客户端的写入请求会拒绝,脑裂造成的数据丢失情况自然也就解决了


七、Redis集群脑裂后的恢复方案


当Redis集群发生脑裂(Split-Brain)后,会导致数据不一致和集群状态混乱。以下是完整的恢复流程和解决方案:


1、确认脑裂状态

首先需要确认集群是否真的发生脑裂:

脑裂特征:

  • 同一个slot被多个主节点同时持有(冲突)

  • 部分节点显示 fail? 或 handshake状态

  • 不同节点报告的集群状态不一致


2、恢复方案


方案1:自动恢复(推荐)

Redis集群在某些情况下可以自动恢复:

适用场景:

  • 轻微脑裂(如短暂网络分区后恢复)

  • 仅少量slot分配冲突


方案2:手动恢复(严重脑裂时)


步骤1:停止所有客户端写入

防止新数据加重不一致情况


步骤2:确定正确的主节点

比较各分区的数据,选择:

  • 数据最新的分区

  • 包含多数主节点的分区


步骤3:重置错误的主节点

选项:

  • cluster reset soft:保留数据,仅重置集群状态

  • CLUSTER RESET HARD:清除所有数据(极端情况使用)


步骤4:重新加入集群


步骤5:修复槽分配


步骤6:数据一致性验证


恢复后必须检查数据:

处理冲突数据:

  • 使用 scan命令 找出冲突键

  • 人工判断保留哪个版本

  • 使用 restore命令 修复数据

posted @ 2025-04-29 20:14  jock_javaEE  阅读(221)  评论(0)    收藏  举报