



















脑裂定义: 在分布式系统中,因网络分区导致集群被分割成多个子集,每个子集都认为自己是唯一正确的集群,从而出现多个"大脑"同时决策的问题。
CAP定理体现:
网络分区(P)发生时:
- 选择一致性(C):停止服务,等待网络恢复
- 选择可用性(A):继续服务,可能产生数据不一致
正常状态:
Primary NameNode (Active) ←→ Standby NameNode (Standby)
网络分区后:
分区A: Primary NameNode (认为自己是Active)
分区B: Standby NameNode (升级为Active)
结果: 两个Active NameNode同时提供服务
正常状态:
ResourceManager1 (Active) ←→ ResourceManager2 (Standby)
脑裂状态:
分区A: RM1继续调度资源,接受新任务
分区B: RM2升级为Active,也开始调度资源
结果: 集群资源被重复分配,任务冲突
常见原因:
节点A → 心跳超时 → 节点B (认为A已死亡)
节点B → 心跳超时 → 节点A (认为B已死亡)
实际情况: 两个节点都正常,只是网络不通
超时检测的局限性:
NameNode脑裂 → DataNode注册混乱 → 副本状态不一致
ResourceManager脑裂 → NodeManager重复注册 → 资源分配冲突
核心思想: 通过奇数个JournalNode构成的分布式日志系统,确保只有一个NameNode能成功写入元数据。
架构设计:
NameNode1 (Active) ←→ JournalNode1
NameNode2 (Standby) ←→ JournalNode2
JournalNode3
写入要求: 必须获得多数JournalNode(≥2)确认
防脑裂原理:
java
// NameNode尝试写入日志
try {
journalManager.startLogSegment(txid);
// 需要获得多数JournalNode确认
if (confirmedNodes >= (totalNodes + 1) / 2) {
return SUCCESS; // 成为/保持Active状态
} else {
return FAILED; // 降级为Standby状态
}
} catch (QuorumException e) {
// 无法获得多数确认,自动降级
transitionToStandby();
}
ZKFailoverController机制:
ZKFC进程监控本地NameNode健康状态
↓
在ZooKeeper中竞争分布式锁
↓
获得锁的ZKFC将对应NameNode切换为Active
↓
失去锁的ZKFC将对应NameNode切换为Standby
防脑裂保证:
当检测到可能的脑裂时,主动隔离旧的Active节点:
bash
# 通过SSH杀死旧NameNode进程
ssh old-namenode "kill -9 `cat /var/run/hadoop/namenode.pid`"
bash
# 自定义隔离脚本
/path/to/fence-script.sh <target-namenode>
# 可以包括:关闭进程、断开网络、重启机器等
bash
# 通过网络ACL阻止旧节点访问
iptables -A INPUT -s <old-namenode-ip> -j DROP
yaml
# 高可用配置建议
JournalNode部署:
- 奇数个节点: 3或5个
- 跨机架部署: 避免单点故障
- 独立磁盘: SSD提升性能
ZooKeeper集群:
- 奇数个节点: 3或5个
- 独立部署: 不与Hadoop节点混部
- 网络隔离: 独立网络段
xml
<!-- hdfs-site.xml -->
<configuration>
<!-- QJM配置 -->
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://jn1:8485;jn2:8485;jn3:8485/mycluster</value>
</property>
<!-- 自动故障转移 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- Fencing配置 -->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop/.ssh/id_rsa</value>
</property>
<!-- 超时设置 -->
<property>
<name>ha.zookeeper.session-timeout.ms</name>
<value>5000</value>
</property>
</configuration>
bash
# 关键监控指标
namenode_ha_state # NameNode HA状态
journalnode_sync_lag # JournalNode同步延迟
zkfc_election_count # ZKFC选举次数
fencing_success_rate # Fencing成功率
# 告警规则
- 多个NameNode同时为Active状态
- JournalNode集群少于多数节点可用
- ZKFC频繁选举(可能网络不稳定)
- Fencing操作失败
案例:机房网络中断导致的脑裂
时间轴:
T0: NameNode1(Active)在机房A,NameNode2(Standby)在机房B
T1: 机房间网络中断
T2: NameNode2检测不到NameNode1心跳,尝试升级为Active
T3: 由于JournalNode分布在两个机房,NameNode2无法获得多数确认
T4: 系统进入只读状态,等待网络恢复
正确结果: QJM机制阻止了脑裂,保证数据一致性
bash
# 1. 检查NameNode状态
hdfs haadmin -getServiceState nn1
hdfs haadmin -getServiceState nn2
# 2. 检查JournalNode日志
tail -f /var/log/hadoop/journalnode.log | grep -i "fencing\|split-brain"
# 3. 检查ZooKeeper中的锁信息
zkCli.sh -server zk1:2181
ls /hadoop-ha/mycluster
# 4. 检查集群整体状态
hdfs dfsadmin -report
bash
# 1. 确认当前Active节点
hdfs haadmin -getServiceState nn1
hdfs haadmin -getServiceState nn2
# 2. 如果出现双Active,手动切换
hdfs haadmin -transitionToStandby nn2 --forcemanual
# 3. 检查数据一致性
hdfs fsck / -files -blocks -locations
# 4. 重启ZKFC服务
systemctl restart hadoop-zkfc
# 5. 验证自动故障转移
hdfs haadmin -failover nn1 nn2
通过以上综合防护措施,可以有效避免Hadoop集群脑裂问题,确保生产环境的高可用性和数据一致性。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。