HDFS (3.3.6) ha原理及部署

HDFS HA原理与集群搭建指南

1. HA背景

        在Hadoop2.x版本中,NameNode HA 支持2个节点,在Hadoop3.x版本中,NameNode高可用可以支持多台节点。

2. HA实现原理

        NameNode中存储了HDFS中所有元数据信息(包括用户操作元数据和block元数据),在NameNode HA中,当Active NameNode(ANN)挂掉后,StandbyNameNode(SNN)要及时顶上,这就需要将所有的元数据同步到SNN节点。如向HDFS中写入一个文件时,如果元数据同步写入ANN和SNN,那么当SNN挂掉势必会影响ANN,所以元数据需要异步写入ANN和SNN中。如果某时刻ANN刚好挂掉,但却没有及时将元数据异步写入到SNN也会引起数据丢失,所以向SNN同步元数据需要引入第三方存储,在HA方案中叫做“共享存储”。每次向HDFS中写入文件时,需要将edits log同步写入共享存储,这个步骤成功才能认定写文件成功,然后SNN定期从共享存储中同步editslog,以便拥有完整元数据便于ANN挂掉后进行主备切换。

HDFS将Cloudera公司实现的QJM(Quorum Journal Manager)方案作为默认的共享存储实现。在QJM方案中注意如下几点:

  • 基于QJM的共享存储系统主要用于保存Editslog,并不保存FSImage文件,FSImage文件还是在NameNode本地磁盘中。
  • QJM共享存储采用多个称为JournalNode的节点组成的JournalNode集群来存储EditsLog。每个JournalNode保存同样的EditsLog副本。
  • 每次NameNode写EditsLog时,除了向本地磁盘写入EditsLog外,也会并行的向JournalNode集群中每个JournalNode发送写请求,只要大多数的JournalNode节点返回成功就认为向JournalNode集群中写入EditsLog成功。
  • 如果有2N+1台JournalNode,那么根据大多数的原则,最多可以容忍有N台JournalNode节点挂掉。

        当客户端操作HDFS集群时,Active NameNode 首先把 EditLog 提交到 JournalNode 集群,然后 Standby NameNode 再从 JournalNode 集群定时同步 EditLog。当处 于 Standby 状态的 NameNode 转换为 Active 状态的时候,有可能上一个 Active NameNode 发生了异常退出,那么 JournalNode 集群中各个 JournalNode 上的 EditLog 就可能会处于不一致的状态,所以首先要做的事情就是让 JournalNode 集群中各个节点上的 EditLog 恢复为一致,然后Standby NameNode会从JournalNode集群中同步EditsLog,然后对外提供服务。

上图中引入了zookeeper作为分布式协调器来完成NameNode自动选主,以上各个角色解释如下:

  • AcitveNameNode:主 NameNode,只有主NameNode才能对外提供读写服务。
  • Standby NameNode:备用NameNode,定时同步Journal集群中的editslog元数据。
  • ZKFailoverController:ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控制。ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换。
  • Zookeeper集群:分布式协调器,NameNode选主使用。
  • Journal集群:Journal集群作为共享存储系统保存HDFS运行过程中的元数据,ANN和SNN通过Journal集群实现元数据同步。
  • DataNode节点:除了通过共享存储系统共享 HDFS 的元数据信息之外,主 NameNode 和备 NameNode 还需要共享 HDFS 的数据块和 DataNode 之间的映射关系。DataNode 会同时向主 NameNode 和备 NameNode 上报数据块的位置信息。

3. 脑裂问题

        当网络抖动时,ZKFC检测不到Active NameNode,此时认为NameNode挂掉了,因此将Standby NameNode切换成Active NameNode,而旧的Active NameNode由于网络抖动,接收不到zkfc的切换命令,此时两个NameNode都是Active状态,这就是脑裂问题。那么HDFS HA中如何防止脑裂问题的呢?

        HDFS集群初始启动时,Namenode的主备选举是通过 ActiveStandbyElector 来完成的,ActiveStandbyElector 主要是利用了 Zookeeper 的写一致性和临时节点机制,具体的主备选举实现如下:

3.1 创建锁节点

        如果 HealthMonitor 检测到对应的 NameNode 的状态正常,那么表示这个 NameNode 有资格参加 Zookeeper 的主备选举。如果目前还没有进行过主备选举的话,那么相应的 ActiveStandbyElector 就会发起一次主备选举,尝试在 Zookeeper 上创建一个路径为/hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock 的临时节点 (${dfs.nameservices} 为 Hadoop 的配置参数 dfs.nameservices 的值,下同),Zookeeper 的写一致性会保证最终只会有一个 ActiveStandbyElector 创建成功,那么创建成功的 ActiveStandbyElector 对应的 NameNode 就会成为主 NameNode,ActiveStandbyElector 会回调 ZKFailoverController 的方法进一步将对应的 NameNode 切换为 Active 状态。而创建失败的 ActiveStandbyElector 对应的NameNode成为备用NameNode,ActiveStandbyElector 会回调 ZKFailoverController 的方法进一步将对应的 NameNode 切换为 Standby 状态。

2. 注册 Watcher 监听

        不管创建/hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock 节点是否成功,ActiveStandbyElector 随后都会向 Zookeeper 注册一个 Watcher 来监听这个节点的状态变化事件,ActiveStandbyElector 主要关注这个节点的 NodeDeleted 事件。

3. 自动触发主备选举

        如果 Active NameNode 对应的 HealthMonitor 检测到 NameNode 的状态异常时, ZKFailoverController 会主动删除当前在 Zookeeper 上建立的临时节点/hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock,这样处于 Standby 状态的 NameNode 的 ActiveStandbyElector 注册的监听器就会收到这个节点的 NodeDeleted 事件。收到这个事件之后,会马上再次进入到创建/hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock 节点的流程,如果创建成功,这个本来处于 Standby 状态的 NameNode 就选举为主 NameNode 并随后开始切换为 Active 状态。

        当然,如果是 Active 状态的 NameNode 所在的机器整个宕掉的话,那么根据 Zookeeper 的临时节点特性,/hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock 节点会自动被删除,从而也会自动进行一次主备切换。

        以上过程中,Standby NameNode成功创建 Zookeeper 节点/hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock 成为Active NameNode之后,还会创建另外一个路径为/hadoop-ha/${dfs.nameservices}/ActiveBreadCrumb 的持久节点,这个节点里面保存了这个 Active NameNode 的地址信息。Active NameNode 的ActiveStandbyElector 在正常的状态下关闭 Zookeeper Session 的时候 (注意由于/hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock 是临时节点,也会随之删除)会一起删除节点/hadoop-ha/${dfs.nameservices}/ActiveBreadCrumb。但是如果 ActiveStandbyElector 在异常的状态下 Zookeeper Session 关闭 (比如 Zookeeper 假死),那么由于/hadoop-ha/${dfs.nameservices}/ActiveBreadCrumb 是持久节点,会一直保留下来。后面当另一个 NameNode 选主成功之后,会注意到上一个 Active NameNode 遗留下来的这个节点,从而会回调 ZKFailoverController 的方法对旧的 Active NameNode 进行隔离(fencing)操作以避免出现脑裂问题,fencing操作会通过SSH将旧的Active NameNode进程尝试转换成Standby状态,如果不能转换成Standby状态就直接将对应进程杀死。

4. HA集群搭建

4.1 环境准备

4.1.1 zookeeper部署

zookeeper安装教程https://mp.csdn.net/mp_blog/creation/editor/149740982

4.1.2 HDFS环境准备

hdfs分布式集群安装教程https://mp.csdn.net/mp_blog/creation/editor/150279539我们在此集群上进行改造

  • 关闭集群
[root@hadoop101 ~] stop-dfs.sh
  • 删除数据目录和日志目录,所有节点上执行
[root@hadoop103 data] rm -rf /data/hadoop/
[root@hadoop103 data] rm -rf /opt/modul/hadoop-3.3.6/logs

4.2 HDFS节点规划

节点NNDNZKFCJN
hadoop101
hadoop102
hadoop103
hadoop104
hadoop105

4.3 集群搭建

4.3.1 各个节点安装HDFS HA自动切换必须的依赖

        在HDFS集群搭建完成后,在Namenode HA切换进行故障转移时采用SSH方式进行,底层会使用到fuster包,有可能我们安装Centos7系统没有fuster程序包,导致不能进行NameNode HA 切换,我们可以通过安装Psmisc包达到安装fuster目的,因为此包中包含了fuster程序,安装方式如下,在各个节点上执行如下命令,安装Psmisc包:

yum -y install psmisc

4.3.2 core-site.xml 

<configuration>
<property>
<!-- 为Hadoop 客户端配置默认的高可用路径 -->
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<property>
<!-- Hadoop 数据存放的路径,namenode,datanode 数据存放路径都依赖本路径,
     不要使用 file:/ 开头,使用绝对路径即可
     namenode 默认存放路径 :file://${hadoop.tmp.dir}/dfs/name
     datanode 默认存放路径 :file://${hadoop.tmp.dir}/dfs/data -->
<name>hadoop.tmp.dir</name>
<value>/data/hadoop/</value>
</property>
<property>
<!-- 指定zookeeper所在的节点 -->
<name>ha.zookeeper.quorum</name>
<value>hadoop101:2181,hadoop102:2181,hadoop103:2181</value>
</property>
</configuration>

4.3.3 hdfs-site.xml

<configuration> 
<!-- 指定副本的数量 --> 
<property> 
<name>dfs.replication</name> 
<value>3</value> 
</property> 
<!-- 解析参数dfs.nameservices值hdfs://mycluster的地址 --> 
<property> 
<name>dfs.nameservices</name> 
<value>mycluster</value> 
</property> 
<!-- mycluster由以下三个namenode支撑 --> 
<property> 
<name>dfs.ha.namenodes.mycluster</name> 
<value>nn1,nn2,nn3</value> 
</property> <property> 
<!-- dfs.namenode.rpc-address.[nameservice ID].[name node ID] namenode 所在服务器名称和RPC监听端口号 -->
<name>dfs.namenode.rpc-address.mycluster.nn1</name> 
<value>hadoop101:8020</value> 
</property> 
<property> 
<!-- dfs.namenode.rpc-address.[nameservice ID].[name node ID] namenode 所在服务器名称和RPC监听端口号 --> 
<name>dfs.namenode.rpc-address.mycluster.nn2</name> 
<value>hadoop102:8020</value> 
</property> 
<property> 
<!-- dfs.namenode.rpc-address.[nameservice ID].[name node ID] namenode 所在服务器名称和RPC监听端口号 --> 
<name>dfs.namenode.rpc-address.mycluster.nn3</name> 
<value>hadoop103:8020</value> 
</property> 
<property> 
<!-- dfs.namenode.http-address.[nameservice ID].[name node ID] namenode 监听的HTTP协议端口 --> 
<name>dfs.namenode.http-address.mycluster.nn1</name> 
<value>hadoop101:9870</value> 
</property> 
<property> 
<!-- dfs.namenode.http-address.[nameservice ID].[name node ID] namenode 监听的HTTP协议端口 --> 
<name>dfs.namenode.http-address.mycluster.nn2</name> 
<value>hadoop102:9870</value> 
</property> 
<property> 
<!-- dfs.namenode.http-address.[nameservice ID].[name node ID] namenode 监听的HTTP协议端口 --> 
<name>dfs.namenode.http-address.mycluster.nn3</name> 
<value>hadoop103:9870</value> 
</property> 
<!-- namenode高可用代理类 --> 
<property> 
<name>dfs.client.failover.proxy.provider.mycluster</name> 
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property> 
<!-- 指定三台journal node服务器的地址 --> 
<property> 
<name>dfs.namenode.shared.edits.dir</name> 
<value>qjournal://hadoop103:8485;hadoop104:8485;hadoop105:8485/mycluster</value> 
</property> 
<!-- journalnode 存储数据的地方 --> 
<property> 
<name>dfs.journalnode.edits.dir</name> 
<value>/data/journal/node/local/data</value> 
</property> 
<!--启动NN故障自动切换 --> 
<property> 
<name>dfs.ha.automatic-failover.enabled</name> 
<value>true</value> 
</property> 
<!-- 当active nn出现故障时,ssh到对应的服务器,将namenode进程kill掉 --> 
<property> 
<name>dfs.ha.fencing.methods</name> 
<value>sshfence</value> 
</property> 
<property> 
<name>dfs.ha.fencing.ssh.private-key-files</name> 
<value>/root/.ssh/id_rsa</value> 
</property> 
</configuration>

4.3.4 workers文件

hadoop103
hadoop104
hadoop105

4.3.5 start-dfs.sh stop-dfs.sh

#分别在/opt/module/hadoop-3.3.6/sbin 目录下的 start-dfs.sh 和stop-dfs.sh文件顶部添加如下内容 
HDFS_NAMENODE_USER=root 
HDFS_DATANODE_USER=root 
HDFS_JOURNALNODE_USER=root 
HDFS_ZKFC_USER=root

4.3.6 分发配置文件

[root@hadoop101 sbin] xsync.sh /opt/module/hadoop-3.3.6/etc/hadoop/hdfs-site.xml
[root@hadoop101 sbin] xsync.sh /opt/module/hadoop-3.3.6/etc/hadoop/core-site.xml
[root@hadoop101 sbin] xsync.sh /opt/module/hadoop-3.3.6/etc/hadoop/worker
[root@hadoop101 sbin] xsync.sh /opt/module/hadoop-3.3.6/sbin/start-dfs.sh
[root@hadoop101 sbin] xsync.sh /opt/module/hadoop-3.3.6/sbin/stop-dfs.sh

4.3.7 格式化并启动集群

# 在hadoop101,格式化zookeeper 
[root@hadoop101 ~] hdfs zkfc -formatZK


# 在hadoop103,hadoop104,hadoop105上启动journalnode
[root@hadoop103 ~] hdfs --daemon start journalnode

# 在hadoop101中格式化namenode,只有第一次搭建做,以后不用做 
[root@hadoop101 ~] hdfs namenode -format

#在hadoop101中启动namenode,以便同步其他namenode 
[root@hadoop101 ~] hdfs --daemon start namenode

#高可用模式配置namenode,使用下列命令来同步namenode(在需要同步的namenode中执行,这里就是在hadoop102、hadoop103上执行): [root@node2 software]# hdfs namenode -bootstrapStandby [root@hadoop102 software] hdfs namenode -bootstrapStandby
[root@hadoop103 software] hdfs namenode -bootstrapStandby

以上格式化集群完成后就可以在NameNode节点上执行如下命令启动集群:
[root@hadoop101 ~] start-dfs.sh

4.3.8 验证ha

关闭active的namenode节点

[root@hadoop101 sbin] hdfs --daemon stop namenode

去zookeeper上查看当前的活跃节点,注册时hadoop102,所以hadoop102是active节点

4.3.9 特别事项

namenode高可用必须要集群初始创建的时候,就要确定好集群有哪些机器,不能中途添加。

<think> 嗯,用户询问的是如何将Hadoop 2.7.7升级到3.3.6版本的方法。这个问题涉及到Hadoop集群的重大版本升级,需要谨慎处理。 从引用内容来看,用户应该是在管理一个Hadoop集群,引用[1]提到了一种升级策略:只升级HDFS服务端而保持客户端不变。这说明用户可能面临组件兼容性问题,特别是Spark/Hive/Flink等组件还不支持Hadoop 3的情况。 用户给出的四个引用都很关键: - 引用[1]展示了服务端升级而客户端保持的混合部署方案 - 引用[2][3][4]都是关于Hadoop 2.7环境的搭建配置 这些引用共同说明用户需要兼容现有生态组件的升级方案 在思考解决方案时,需要注意几个技术要点: 第一,Hadoop 3.x默认端口与2.x不同,比如9820替代9000,这个在配置时要特别注意 第二,HA配置方式有变化,JournalNode被改进的基于Raft的QJM替代 第三,API兼容性方面,尽管Hadoop3保持API兼容,但用户需要关注mapreduce API的变化 考虑到用户环境,建议采取分阶段升级: 1. 先升级测试环境验证兼容性 2. 生产环境采用滚动升级方式 3. 重点验证HDFS和YARN核心功能 4. 尤其要注意Hive/Spark等组件的连接测试 升级过程中最可能遇到的坑是: - 配置文件格式变化(如需要添加新属性) - 权限模型调整(Hadoop3强化了权限控制) - 存储格式兼容性(比如Orc文件可能需要迁移) 最后生成的相关问题应该覆盖: - 兼容性验证的具体方法 - 可能遇到的常见错误 - 回滚方案 - 性能对比 用户可能还需要知道如何验证升级是否成功,这包括检查HDFS数据完整性、YARN任务调度等功能测试。 </think> 以下是将 Hadoop 2.7.7 升级到 3.3.6 的方法,结合兼容性策略和关键步骤: --- ### **升级核心策略**(参考引用[1]) 1. **服务端升级,客户端兼容** - 升级 HDFS 服务端组件(NameNode/DataNode/JournalNode/ZKFC) - Hadoop 生态组件(Spark/Hive/Flink/HBase)**保持 2.7.7 客户端版本**,通过 `HADOOP_CLASSPATH` 覆盖兼容库实现与 HDFS 3.3.6 交互[^1] - 需验证 Hadoop 2.x 客户端与 3.x 服务端的 RPC 协议兼容性(默认支持) 2. **配置文件迁移**(参考引用[4]) 需合并旧配置与新版本特性配置: ```xml <!-- hdfs-site.xml 示例 --> <configuration> <property> <name>dfs.namenode.rpc-address</name> <value>hdfs://namenode:8020</value> <!-- Hadoop 3.x 默认端口变化 --> </property> <property> <name>dfs.datanode.data.dir</name> <value>/data/hdfs/dn</value> <!-- 需同步数据目录 --> </property> </configuration> ``` --- ### **分阶段升级流程** #### **阶段1:预升级准备** 1. **备份与验证** - 备份 HDFS 元数据:`hdfs dfsadmin -fetchImage fsimage_backup` - 检查 HDFS 健康状态:`hdfs fsck /` - 记录当前组件版本(参考引用[2][3]) 2. **环境隔离** - 搭建独立 Hadoop 3.3.6 测试集群(参考引用[4]配置模板) - 使用 `tar -zxvf hadoop-3.3.6.tar.gz -C /usr/local` 解压新版本[^3] #### **阶段2:滚动升级服务端** 1. **升级顺序** ```mermaid graph LR A[停用ZKFC] --> B[升级JournalNode] B --> C[重启NameNode] C --> D[滚动升级DataNode] D --> E[启用ZKFC] ``` 2. **关键操作** - 替换二进制文件:`mv /usr/local/hadoop-2.7.7 /usr/local/hadoop-3.3.6` - 合并配置文件(核心:`core-site.xml`, `hdfs-site.xml`, `yarn-site.xml`) - 启动命令:`hdfs --daemon start namenode`(Hadoop 3.x 新脚本) #### **阶段3:兼容性处理** 1. **客户端混合配置** ```bash # 在 Hive/Spark 客户端添加配置 export HADOOP_CLASSPATH=/path/to/hadoop-2.7.7-client-libs/* export HADOOP_CONF_DIR=/etc/hadoop3_conf/ # 指向Hadoop 3.x配置 ``` 2. **验证项**: - HDFS 读写:`hadoop fs -put /test /tmp` - YARN 任务提交:`yarn jar hadoop-mapreduce-examples.jar pi 10 100` --- ### **风险规避建议** 1. **回滚方案** - 保留 Hadoop 2.7.7 二进制备份 - 出现故障时:停用新服务 → 恢复旧配置 → 重启 2.7.7 进程 2. **已知兼容问题** - **Hive 2.x 适配**:需替换 `hadoop-common` JAR 包(参考引用[2]) - **端口冲突**:Hadoop 3.x 默认端口变更(e.g., NameNode RPC: 8020→9820) --- ### **验证成功标志** 1. 服务状态:`hdfs dfsadmin -report` 显示所有 DataNode 在线 2. 生态组件任务:Spark 读写 HDFS、Hive 执行 MR 任务正常 3. Web UI:NameNode Web 端口(9870)可访问且无告警 > 注:生产环境建议先在测试集群完成全流程验证(参考引用[3][4]的配置方法)[^3][^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值