HDFS-HA 的实现原理

HA概述

  • HA(High Available),即高可用
  • 实现高可用最关建的就是取消单点故障
  • HA严格来讲分成各个组件的HA:
    HDFS的HA
    YARN的HA

HDFS-HA的工作机制

通过双NN(namenode)消除单点故障

HDFS-HA工作要点

  • 元数据管理方式的变化
    内存中各自保持一份元数据
    Edits日志只有avtive状态的nn可以写
    两个nn都可以读Edits日志
    共享的Edits放在一个共享存储中管理(qjournal与NFS两个主流实现)
  • 需要一个状态管理的功能模块
    实现一个zkfailover,常驻在每一个nn所在的节点,每一个zkfailover负责监控自己所在的nn节点,通过zk进行状态标识,需要切换时有zkfailover负责切换,此时需要防止出现脑裂现象。
  • 必须保证两个nn之间能ssh无密码登录
  • 隔离(Fence),即同一时刻只有一个nn对外提供服务

HDFS-HA自动故障转移工作机制

自动故障转移在原本的集群(手动双nn集群)的基础上增加了两个新的组件:

ZooKeeper和ZKFailoverController(ZKFC)

  • zk维护少量协调数据,同志客户端这些数据的变化和监视客户端故障的高可用服务。HA的自动故障转移依赖于zk的如下功能:
  • 故障检测:当nn的机器崩溃时,zk中对应的会话中止,zk通知另一个nn触发故障转移。
  • 现役nn选择:zk提供了一个简单的机制用于唯一的选择一个节点为active的状态。若当前nn崩溃,另一个节点可能从zk获得特殊的排他锁成为现役的nn
  • ZKFC时自动故障转移中的另一个新组件,为zk的客户端,也负责监视和管理nn的状态,每个nn主机都应该有一个ZKFC进程,ZKFC负责:
  • 健康检测,ZKFC定期地ping与之在同一节点地nn,只要nn无法及时回复健康 装填,ZKFC就会标识该节点为非健康的
  • zk会话管理:当本地nn时健康的,ZKFC会保持一个在zk中打开的会话锁。如果本地nn为active状态,ZKFC还会保持一个特殊的znode锁。该锁使用了zk对短暂节点的支持,如果会话中止,znode将自动删除
  • 基于zk的选择:如果本地的nn是健康的,且ZKFC没有发现其他节点持有znode,它将为自己获取该锁。若成功,则它赢得了选择,并负责运行故障转移以使它的本地nn为active状态。

hdfs ha 选举 hdfs中ha机制_hadoop

HDFS-HA的实际实现

初始准备(集群规划

hadoop201

hadoop202

hadoop203

NameNode

NameNode

JournalNode

JournalNode

JournalNode

DataNode

DataNode

DataNode

ZK

ZK

ZK

hadoop101 hadoop103 hadoop104 NameNode NameNode JournalNode JournalNode JournalNode DataNode DataNode DataNode ZK ZK ZK

第一步

  • 确保有可以正常集群启动dfs的hadoop
  • 确保zk集群部署完成且可以正常启动。

第二步

  • 集群备份:
    cp -r hadoop-2.7.2/ hadoop-2.7.2_bak/
  • 配置core-site.xml
<!-- 把两个NameNode)的地址组装成一个集群mycluster -->
		<property>
			<name>fs.defaultFS</name>
        	<value>hdfs://mycluster</value>
		</property>

		<!-- 指定hadoop运行时产生文件的存储目录 -->
		<property>
			<name>hadoop.tmp.dir</name>
			<value>/opt/ha/hadoop-2.7.2/data/tmp</value>
		</property>
  • 配置hdfs-site.xml
<configuration>
	<!-- 完全分布式集群名称 -->
	<property>
		<name>dfs.nameservices</name>
		<value>mycluster</value>
	</property>

	<!-- 集群中NameNode节点都有哪些 节点名可以自定义,但是后续出现时要保持一致-->
	<property>
		<name>dfs.ha.namenodes.mycluster</name>
		<value>nn1,nn2</value>
	</property>

	<!-- nn1的RPC通信地址 -->
	<property>
		<name>dfs.namenode.rpc-address.mycluster.nn1</name>
		<value>hadoop101:9000</value>
	</property>

	<!-- nn2的RPC通信地址 -->
	<property>
		<name>dfs.namenode.rpc-address.mycluster.nn2</name>
		<value>hadoop103:9000</value>
	</property>

	<!-- nn1的http通信地址 -->
	<property>
		<name>dfs.namenode.http-address.mycluster.nn1</name>
		<value>hadoop101:50070</value>
	</property>

	<!-- nn2的http通信地址 -->
	<property>
		<name>dfs.namenode.http-address.mycluster.nn2</name>
		<value>hadoop103:50070</value>
	</property>

	<!-- 指定NameNode元数据在JournalNode上的存放位置 -->
	<property>
		<name>dfs.namenode.shared.edits.dir</name>
	<value>qjournal://hadoop101:8485;hadoop103:8485;hadoop104:8485/mycluster</value>
	</property>

	<!-- 配置隔离机制,即同一时刻只能有一台服务器对外响应 -->
	<property>
		<name>dfs.ha.fencing.methods</name>
		<value>sshfence</value>
	</property>

	<!-- 使用隔离机制时需要ssh无秘钥登录-->
	<property>
		<name>dfs.ha.fencing.ssh.private-key-files</name>
		<value>/home/kgg/.ssh/id_rsa</value>
	</property>

	<!-- 声明journalnode服务器存储目录-->
	<property>
		<name>dfs.journalnode.edits.dir</name>
		<value>/opt/ha/hadoop-2.7.2/data/jn</value>
	</property>

	<!-- 关闭权限检查-->
	<property>
		<name>dfs.permissions.enable</name>
		<value>false</value>
	</property>

	<!-- 访问代理类:client,mycluster,active配置失败自动切换实现方式-->
	<property>
  		<name>dfs.client.failover.proxy.provider.mycluster</name>
	<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
	</property>
</configuration>
  • 分发配置好的环境到其他集群

尝试启动HDFS-HA集群

  • 删除机器的/data文件,为后续格式化做准备
  • 单点启动journalnode
    sbin/hadoop-daemon.sh start journalnode
  • 在nn1节点上格式化nn并启动之
    bin/hdfs namenode -format

sbin/hadoop-daemon.sh start namenode style>

  • 在nn2上,同步nn1的元数据信息
    bin/hdfs namenode -bootstrapStandby
  • 启动nn2
    sbin/hadoop-daemon.sh start namenode
  • 此时已经可以在web端页面查看两个nn的状态了(此时由于是手动启动,还未指定active的nn,所以可以看到两个nn都还是standby状态

hdfs ha 选举 hdfs中ha机制_大数据_02


hdfs ha 选举 hdfs中ha机制_hdfs_03

  • 启动所有datanode
    sbin/hadoop-daemons.sh start datanode
  • 在nn1上手动将其切换为Active
    bin/hdfs haadmin -transitionToActive nn1
  • 通过指令查看是否Active:
    bin/hdfs haadmin -getServiceState nn1*通过web端同样可以看到是否active:

配置HDFS-HA自动故障转移

具体配置
  • 在hdfs-site.xml中增加
<property>
	<name>dfs.ha.automatic-failover.enabled</name>
	<value>true</value>
</property>
  • 在core-site.xml文件中增加
<property>
	<name>ha.zookeeper.quorum</name>
	<value>hadoop101:2181,hadoop103:2181,hadoop104:2181</value>
</property>
  • 分发配置文件到集群里其他机器上
    (*注 这一步在我看的文档上没有说,但是启动的手在nn2节点上看不到本该启动的zkfc的进程,我试了好几种方法,最后分发了文件才解决的。很可能是因为nn2节点的hdfs-site.xml里没有给dfs.ha.automatic-failover.enabled赋值为true,所以认为zkfc不要启动,所以没有启动。
启动
  1. 关闭所有HDFS服务
    sbin/stop-dfs.sh
  2. 启动zk集群(如果没有关闭zk集群则跳过
    bin/zkServer.sh start
  3. 初始化HA在Zookeeper中的状态
    bin/hdfs zkfc -formatZK
  4. 启动HDFS服务
    sbin/start-dfs.sh
  5. 在各个节点上启动DFSZK Failover Controller。(先在哪台机器启动,哪台机器的nn就是Active nn)
    sbin/hadoop-daemin.sh start zkfc
  6. 启动完成,使用命令查看两台nn节点的状态:
    bin/hdfs haadmin -getServiceState nn1(/nn2)

hdfs ha 选举 hdfs中ha机制_hdfs_04

验证
  • 将Active NN进程杀死
    kill -9 nn对应的进程id
  • 将Active NN进程断开网络
    service network stop