hadoop的机制,是在hadoop的2.x中才有的功能,该功能的实现,非常依赖于一个分布式组件:zookeeper。
zookeeper简要介绍
zookeeper主要做分布式协调服务。主要实现的功能:1.提供对少量数据的存储和管理。2.提供对数据节点的监听功能。
zookeeper的角色:leader(负责数据的写操作)和follower。leader和follower实在启动的时候动态选举出来的。
zookeeper的作用:主控机器选举,分布式协调操作。
zookeeper管理数据采用了类似于文件树结构。每个节点成为一个datanode。节点能够保存一定的数据(小于1M)也可以拥有子节点。
zookeeper的应用场景。
- 统一命名服务:Dubbo 远程调用:webservice和rpc。统一命名:将多个机器上的服务给予 一个统一的命名。
- 统一配置管理 将所有分布式应用的数据存入到zookeeper集群中。
- 集群管理 利用zookeeper实现动态主控节点的选举
NN高可用方案实现机制
问题:相应客户的读写请求的是角色是NN,所以一旦NN宕机了,那么整个集群的服务就停止了。NN+SN机制,只能实现元数据的可靠性,但无法做到服务的高可用性。
解决方案:再加入一个NN。思考点:
- 能否两个NN收正常客户请求? 否,两个NN只能有一个相应客户请求(状态为active),另一个状态为standBy状态。
- standby状态的节点必须要能够快速无缝的切换为active,这就要求两个NN上的元数据时刻保持一致。 元数据=fsimage+edits,所以主要问题就是edits的实时保持一致性,如果两个NN上的edits每条元数据修改都立刻同步,那么会增加操作失败的概率(acNN向stNN同步时候要通过网络,可能会失败),如果是批量积累再去同步,那么如果同步之前NN宕机了,那么两个NN上拥有的元数据就不是一致的了)。那么两个NN谁都不要单独持有edits,将它放到一个第三方应用上,这个第三方应用应该是个集群,具备高可用和高可靠性。hadoop设计的这个第三方集群就是qjournal(底层依赖于zookeeper集群来实现)。这样就实现了两个NN上的元数据的完全一致性。
- 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上的电源,之后再去进行状态切换。
- federation的概念 一对acNN和stNN成为一个federation。作用就是可以实现多个一个主机集群中含有多个federation。
- 一个最小的高可用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向相互配置无密登录。
开始启动集群
- 启动zookeeper集群
执行命令
zkServer.sh start
- 手动启动每一个journalNode
在每个计划部署journalNode的节点上执行命令
hadoop-daemon.sh start journalnode
- 格式化hdfs的namenode 首先在NN1上执行格式化命令,然后可以将NN1上格式化之后的数据拷贝到NN2上,也可以在NN2上执行hdfs namenode -bootstrapStandby命令。保证两个NN的fsimage一致。
- 格式化zkfs
执行命令:
hdfs zkfc -formatZK
,只在一个NN(NN1)上执行就可以了。 - 启动hdfs
执行命令:
start-dfs.sh
,只在一个NN(NN1)上执行就可以了 - 启动yarn
在RM1 上执行命令:
start-yarn.sh
,但是还要在RM2上去手动启动resourcemanager进程,利用hadoop-daemon.sh来启动。
##hdfs
来源:oschina
链接:https://my.oschina.net/u/4489002/blog/3221634