ZooKeeper 03 - ZooKeeper集群的脑裂问题 (Split Brain问题)

本文深入探讨ZooKeeper的主从机制与脑裂现象,分析脑裂产生的原因及表现,详细阐述ZooKeeper如何利用Quorums法定人数机制解决脑裂问题,确保集群一致性。

1.ZooKeeper的主从机制

Leader == Master, Follower == Slaver.

集群中的各个节点都会尝试注册为leader节点, 其他没有注册成功的则成为follower(随从)节点.

这些follower节点通过watcher(观察者)监控着leader节点:

—— ZooKeeper内部通过心跳机制来确定leader的状态, 一旦leader节点出现问题, : 就能很快获悉并迅速通知其他follower节点, 这些follower节点得知消息之后将及时采取相关操作.

2 什么是ZooKeeper的脑裂

2.1 脑裂现象的表现

ZooKeeper集群中, 各个节点间的网络通信不良时, 容易出现脑裂(split-brain)现象:

集群中的节点监听不到leader节点的心跳, 就会认为leader节点出了问题, 此时集群将分裂为不同的小集群, 这些小集群会各自选举出自己的leader节点, 导致原有的集群中出现多个leader节点.

—— 这就是脑裂现象.

2.2 为什么会出现脑裂

设想这样一种情况:

① 集群中网络通信不好, 导致心跳监测超时 —— follower认为leader节点由于某种原因挂掉了, 可其实leader节点并未真正挂掉 —— 这就是假死现象.
② leader节点假死后, ZooKeeper通知所有follower节点进行选举 ==> 某个follower节点升级为新的leader. —— 此时集群中存在2个leader节点.
③ 此时ZooKeeper需要将新leader节点的信息通知给所有的follower节点, 还要通知到所有的client(比如通过: 搭建的Solr集群中的Solr实例就是一个client), 而这个过程由于网络等环境的影响, 消息到达就会存在快慢之分.
④ 如果部分client获得了新leader节点的信息, 而部分没有获得, 而此时client向ZooKeeper发起读写请求, ZooKeeper内部的不一致就会导致: 部分client连接到了新的leader节点上, 而部分client连接到了旧的leader节点上 —— 服务中出现了2个leader, client不知道听谁的好, 就像1个大脑被分裂成2个, 很形象吧O(∩_∩)O

3 ZooKeeper如何解决"脑裂"

3.1 3种可行的思路

(1) Quorums(ˈkwɔrəm, 法定人数)法:

通过设置法定人数, 进而确定集群的容忍度, 当集群中存活的节点少于法定人数, 集群将不可用. 比如:

3个节点的集群中, Quorums = 2 —— 集群可以容忍 (3 - 2 = 1) 个节点失败, 这时候还能选举出leader, 集群仍然可用;
4个节点的集群中, Quorums = 3 —— 集群同样可以容忍 1 个节点失败, 如果2个节点失败, 那整个集群就不可用了.

(2) Redundant communications(冗余通信):

集群中采用多种通信方式, 防止一种通信方式失效导致集群中的节点无法通信.

(3) Fencing(共享资源):

通过共享资源的方式, 将所有共享资源添加到集群中, 能对共享资源进行写操作(即加锁)的节点就是leader节点.

3.2 ZooKeeper采用的方法

ZooKeeper默认采用了Quorums(法定人数)的方式: 只有获得超过半数节点的投票, 才能选举出leader.

这种方式可以确保要么选出唯一的leader, 要么选举失败.

ZooKeeper中Quorums的作用:

① 指定集群中选举leader所需的最少节点数, 保证集群可用;
② client的数据被安全保存到集群中所需的最少节点数, 一旦这些节点保存了数据, 客户端将被通知数据已经安全保存, 可以继续其他任务 —— 基于最终一致性, 集群中剩余的节点最终也会保存相关的数据.

ZooKeeper的写也遵循quorum机制, 因此得不到大多数支持的写是无效的.

3.3 ZooKeeper的具体解决思路

假设: leader发生了假死, followers选举出了一个新的leader.

当旧的leader复活并认为自己仍然是leader, 它向其他followers发出写请求时, 会被拒绝.

—— 因为ZooKeeper维护了一个叫epoch的变量, 每当新leader产生时, epoch都会递增, followers如果确认了新的leader存在, 同时也会知道其epoch的值 —— 它们会拒绝epoch小于现任leader的epoch的所有旧leader的任何请求.

注意: 仍然会存在有部分followers不知道新leader的存在, 但肯定不是大多数, 否则新leader将无法产生.

参考资料

zookeeper(二)常见问题汇总

Zookeeper集群节点数量为什么要是奇数个?

文章来源:https://www.cnblogs.com/shoufeng/p/10591526.html

### Redis Cluster Split-Brain 问题及解决方案 Redis Cluster 是一种分布式数据库架构,旨在通过数据分片和节点间通信提供高可用性和扩展性。然而,在某些网络分区或故障情况下,可能会出现 **Split-Brain脑裂)** 问题,即集群中的多个子集独立运行并认为自己是“合法”的主节点集合,从而导致数据不一致和服务中断。 #### Split-Brain 的成因 在 Redis Cluster 中,每个节点定期发送心跳包以检测其他节点的状态。如果某个节点在一定时间内未响应,则被认为下线。当网络分区发生时,不同子集的节点可能无法相互通信,并各自独立地将部分节点标记为下线,进而选举新的主节点。这种情况下,集群被分割成两个或多个独立的部分,每个部分都可能继续处理客户端请求,造成数据冲突[^2]。 #### Split-Brain 的影响 1. 数据不一致性:不同子集可能对相同的键值进行修改,导致数据冲突。 2. 客户端行为异常:客户端可能连接到不同的子集,读取或写入不一致的数据。 3. 服务不可用:在脑裂恢复过程中,需要手动或自动合并数据,可能导致服务中断。 #### 解决方案与预防措施 ##### 1. 使用奇数个节点部署集群 为了提高集群对网络分区的容忍度,建议使用奇数个节点构建集群。例如,三主三从的结构比两主两从更能有效避免脑裂情况的发生。这样可以确保大多数节点能够达成共识,防止孤立节点形成合法子集。 ##### 2. 启用 `cluster-require-full-coverage` 参数 Redis 提供了 `cluster-require-full-coverage` 配置项来控制是否允许部分节点故障时整个集群继续对外提供服务。默认情况下该参数为开启状态,表示只有当所有哈希槽都被覆盖时,集群才接受写操作。若关闭此选项,则即使部分节点失效,剩余节点仍可提供服务,但增加了脑裂风险。因此,在关键业务场景中应谨慎调整此参数[^2]。 ##### 3. 引入外部仲裁机制 引入外部协调服务(如 ZooKeeper、Consul 或 etcd)作为第三方投票机制,帮助集群判断哪个子集应该保留为主节点集合。这种方式可以显著降低脑裂发生的概率,但也增加了系统复杂性和运维成本。 ##### 4. 设置合理的超时时间 Redis Cluster 使用 `cluster-node-timeout` 参数定义节点被认为失败的时间阈值。适当调高该值可以在短暂网络波动期间避免误判节点下线,从而减少脑裂的可能性。但需注意,过高的超时值可能导致故障转移延迟增加。 ##### 5. 客户端感知与重试策略 客户端应具备识别集群拓扑变化的能力,并支持自动重连与重试机制。当发现连接的节点属于非主节点集合时,应主动切换至正确的主节点,以保证数据的一致性和服务连续性。 ##### 6. 监控与报警 建立完善的监控体系,实时跟踪集群状态、节点健康状况以及网络连通性。一旦检测到潜在脑裂风险(如多个主节点同时存在),立即触发告警通知管理员介入处理。 ### 示例代码:检查当前集群配置 ```bash # 查看 cluster-node-timeout 设置 redis-cli -c config get cluster-node-timeout # 查看 cluster-require-full-coverage 设置 redis-cli -c config get cluster-require-full-coverage ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值