hadoop8天课程——第五天,hadoop的HA机制

老子叫甜甜 提交于 2020-04-06 16:40:27

hadoop的机制,是在hadoop的2.x中才有的功能,该功能的实现,非常依赖于一个分布式组件:zookeeper。

zookeeper简要介绍

zookeeper主要做分布式协调服务。主要实现的功能:1.提供对少量数据的存储和管理。2.提供对数据节点的监听功能。

zookeeper的角色:leader(负责数据的写操作)和follower。leader和follower实在启动的时候动态选举出来的。

zookeeper的作用:主控机器选举,分布式协调操作。

zookeeper管理数据采用了类似于文件树结构。每个节点成为一个datanode。节点能够保存一定的数据(小于1M)也可以拥有子节点。

zookeeper的应用场景。

  1. 统一命名服务:Dubbo 远程调用:webservice和rpc。统一命名:将多个机器上的服务给予 一个统一的命名。
  2. 统一配置管理 将所有分布式应用的数据存入到zookeeper集群中。
  3. 集群管理 利用zookeeper实现动态主控节点的选举

NN高可用方案实现机制

问题:相应客户的读写请求的是角色是NN,所以一旦NN宕机了,那么整个集群的服务就停止了。NN+SN机制,只能实现元数据的可靠性,但无法做到服务的高可用性。

解决方案:再加入一个NN。思考点:

  1. 能否两个NN收正常客户请求? 否,两个NN只能有一个相应客户请求(状态为active),另一个状态为standBy状态。
  2. standby状态的节点必须要能够快速无缝的切换为active,这就要求两个NN上的元数据时刻保持一致。 元数据=fsimage+edits,所以主要问题就是edits的实时保持一致性,如果两个NN上的edits每条元数据修改都立刻同步,那么会增加操作失败的概率(acNN向stNN同步时候要通过网络,可能会失败),如果是批量积累再去同步,那么如果同步之前NN宕机了,那么两个NN上拥有的元数据就不是一致的了)。那么两个NN谁都不要单独持有edits,将它放到一个第三方应用上,这个第三方应用应该是个集群,具备高可用和高可靠性。hadoop设计的这个第三方集群就是qjournal(底层依赖于zookeeper集群来实现)。这样就实现了两个NN上的元数据的完全一致性。
  3. standby如何感知active的NN已经出现异常情况了 可以用NN通过向一个zookeeper上注册会话级数据,掉线自动删除。也可以在每个NN上创建一个单独进程zkfc,用来管理两个NN的状态,也是用zookeeper来实现协调:向zookeeper集群注册本NN的状态数据,监控读取另一个NN的状态数据,需要状态切换时候更新自己的状态。如何解决zkfc读到了假死现象呢,也即如何避免状态切换时候发生脑裂:当stNN发现acNN出现异常,stNN不会立刻进行状态切换,会先通过ssh向acNN发送一条远程命令,来杀掉acNN上的所有相关进程,如果命令被acNN节点成功执行会获得一个返回码,根据返回码确保acNN上的进程死透了,然后stNN再进行状态切换。但是如果发出去的命令迟迟没有等到返回结果,当超过一个预定时间后,stNN会执行一个自定义的脚本程序来确保acNN完全挂掉,比如关掉acNN上的电源,之后再去进行状态切换。
  4. federation的概念 一对acNN和stNN成为一个federation。作用就是可以实现多个一个主机集群中含有多个federation。
  5. 一个最小的高可用hadoop集群需要的角色: (NN1,zkfc1),(NN2,zkfc2),(zk1,zk2,zk3),(jn1,jn2,jn3),(DN1,nodemanager),(resourcemanager)至少需要三台机器。

HA的hadoop集群搭建

1.配置文件修改

hadoop-env.sh

将文件中JAVA_HOME的地址写死成自己机器上的java安装路径。

core-site.xml的修改

<configuration>
	<!-- 指定hdfs的nameservice为ns1 -->
	<property>
		<name>fs.defaultFS</name>
		<value>hdfs://ns1/</value>
	</property>

	<!-- 指定hadoop临时目录 -->
	<property>
		<name>hadoop.tmp.dir</name>
		<value>/home/hadoop/app/hadoop-2.4.1/tmp</value>
	</property>

	<!-- 指定zookeeper地址 -->
	<property>
		<name>ha.zookeeper.quorum</name>
		<value>weekend05:2181,weekend06:2181,weekend07:2181</value>
	</property>
</configuration>

hdfs-site.xml的修改

<configuration>
	<!--指定hdfs的nameservice为ns1,需要和core-site.xml中的保持一致 -->
	<property>
		<name>dfs.nameservices</name>
		<value>ns1</value>
	</property>

	<!-- ns1下面有两个NameNode,分别是nn1,nn2 -->
	<property>
		<name>dfs.ha.namenodes.ns1</name>
		<value>nn1,nn2</value>
	</property>

	<!-- nn1的RPC通信地址 -->
	<property>
		<name>dfs.namenode.rpc-address.ns1.nn1</name>
		<value>weekend01:9000</value>
	</property>
	<!-- nn1的http通信地址 -->
	<property>
		<name>dfs.namenode.http-address.ns1.nn1</name>
		<value>weekend01:50070</value>
	</property>

	<!-- nn2的RPC通信地址 -->
	<property>
		<name>dfs.namenode.rpc-address.ns1.nn2</name>
		<value>weekend02:9000</value>
	</property>
	<!-- nn2的http通信地址 -->
	<property>
		<name>dfs.namenode.http-address.ns1.nn2</name>
		<value>weekend02:50070</value>
	</property>

	<!-- 指定NameNode的元数据在JournalNode上的存放位置 -->
	<property>
		<name>dfs.namenode.shared.edits.dir</name>
  		<value>qjournal://weekend05:8485;weekend06:8485;weekend07:8485/ns1</value>
	</property>
	<!-- 指定JournalNode在本地磁盘存放数据的位置 -->
	<property>
		<name>dfs.journalnode.edits.dir</name>
		<value>/home/hadoop/app/hadoop-2.4.1/journaldata</value>
	</property>

	<!-- 开启NameNode失败自动切换 -->
	<property>
		<name>dfs.ha.automatic-failover.enabled</name>
		<value>true</value>
	</property>
	<!-- 配置失败自动切换实现方式 -->
	<property>
		<name>dfs.client.failover.proxy.provider.ns1</name>
		<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
	</property>
	<!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行,shell后面括号里面是所使用的的脚本路径-->
	<property>
		<name>dfs.ha.fencing.methods</name>
		<value>
			sshfence
			shell(/bin/true)
		</value>
	</property>
	<!-- 使用sshfence隔离机制时需要ssh免登陆 -->
	<property>
		<name>dfs.ha.fencing.ssh.private-key-files</name>
		<value>/home/hadoop/.ssh/id_rsa</value>
	</property>
	<!-- 配置sshfence隔离机制超时时间 -->
	<property>
		<name>dfs.ha.fencing.ssh.connect-timeout</name>
		<value>30000</value>
	</property>
</configuration>

mapred-site.xml的修改

<configuration>
	<!-- 指定mr框架为yarn方式 -->
	<property>
		<name>mapreduce.framework.name</name>
		<value>yarn</value>
	</property>
</configuration>

yarn-site.xml的修改

<configuration>
	<!-- 开启RM高可用 -->
	<property>
		<name>yarn.resourcemanager.ha.enabled</name>
		<value>true</value>
	</property>
	<!-- 指定RM的cluster id -->
	<property>
		<name>yarn.resourcemanager.cluster-id</name>
		<value>yrc</value>
	</property>
	<!-- 指定RM的名字 -->
	<property>
		<name>yarn.resourcemanager.ha.rm-ids</name>
		<value>rm1,rm2</value>
	</property>
	<!-- 分别指定RM的地址 -->
	<property>
		<name>yarn.resourcemanager.hostname.rm1</name>
		<value>weekend03</value>
	</property>
	<property>
		<name>yarn.resourcemanager.hostname.rm2</name>
		<value>weekend04</value>
	</property>
	<!-- 指定zk集群地址 -->
	<property>
		<name>yarn.resourcemanager.zk-address</name>
		<value>weekend05:2181,weekend06:2181,weekend07:2181</value>
	</property>
	<property>
		<name>yarn.nodemanager.aux-services</name>
		<value>mapreduce_shuffle</value>
	</property>
</configuration>

修改slaves文件

DN和RM的在那些机器上没有在配置文件中体现出来,其实是通过文本文件slaves中写入的。启动hdfs的脚本文件和启动yarn的脚本文件都会去读这个文件,不一定要一样。slaves文件只是给启动脚本用的,及时没有在slaves中写入,手动的一个个启动DN或者RM,启动之后也能够成功的加入到集群中。

设置无密登录机制

启动NN1的节点要和启动NN1,NN2的节点以及所有的DN节点完成无密配置(sshgen和ssh-copy-id),启动RM1的节点和所有启动NM的节点要完后才能无密配置。RM2还要再去手动启动。NN1和NN2向相互配置无密登录。

开始启动集群

  1. 启动zookeeper集群 执行命令zkServer.sh start
  2. 手动启动每一个journalNode 在每个计划部署journalNode的节点上执行命令hadoop-daemon.sh start journalnode
  3. 格式化hdfs的namenode 首先在NN1上执行格式化命令,然后可以将NN1上格式化之后的数据拷贝到NN2上,也可以在NN2上执行hdfs namenode -bootstrapStandby命令。保证两个NN的fsimage一致。
  4. 格式化zkfs 执行命令:hdfs zkfc -formatZK,只在一个NN(NN1)上执行就可以了。
  5. 启动hdfs 执行命令:start-dfs.sh,只在一个NN(NN1)上执行就可以了
  6. 启动yarn 在RM1 上执行命令:start-yarn.sh,但是还要在RM2上去手动启动resourcemanager进程,利用hadoop-daemon.sh来启动。

##hdfs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!