一. Hadoop 高可用原理
背景: 完全分布式只有一个namenode,存在单点故障问题.
解决: 高可用有2个namenode(active|standy热备),但同一时间只有一个对外提供服务.
问题: 一旦active宕机,stanby需立即切换为actice,让集群一直有namenode.
实现: 保证两件事:1.元数据一致 2.无缝衔接
(一). stanby namenode 和 active namenode的元数据 保持一致
namenode: fsiamge (集群启动时产生的初始文件) + edits (后续运行中产生的文件)
fsimage文件:
- 最开始 hdfs 格式化的生成最初的 fsimage 文件 /
- 后面的 fsiamge 文件: 通过最初的 faimage + edits 文件合并得来的
faimage 文件要想保证一致, 只需要保证: 格式化时候 faimage 文件保持一致.(最开始在一个 namenode 进行格式化生成 fsimage 文件, 将这个 fsiamge 文件发送给另一个 namenode 即可)
edits文件:
只要集群一启动, 持续不断的产生在 active namenode 中.
如何保持 edits 文件在 stanby 中的更新:
将 edits 文件放在一个共享平台 (hadoop2.0自带的 Quorum journal manager 共享日志管理平台,节点奇数 ), standby 监听这个共享平台的数据, 一旦数据更新就将 edits 数据拉取到 stanby 本地
(二). stanby 需要能立即感知 active 状态变化
使用 zk 保存 active namenode 0 / 1 的状态 (znode 1M 1kb)
-
active namenode 将状态信息写入到 zookeeper 中的一个 znode 上
-
stanby namenode 对这个 znode 添加监听 (getData)
-
一旦发现这个 znode 内容变化, 立即将自己的状态切换为 active
但是为了防止脑裂现象 (两个 active namenode, 产生原因是 active 由于网络或其它原因未及时回复standy 导致standy 误以为对方已经挂了, 导致双双 active), 所以stanby 切换之前会远程向原来的 actice 发送一个 shell 脚本(ssh 远程命令, kill -9 xx 甚至 init 0), 以此保证原来的 active 确实宕机的.
每个 namenode 都有一个助理 zkfc : Zookeeper Failover Controller, zk 失败控制器. ( 用来监控每一个namenode的健康状况, 将信息写入zk中. 因为 namenode 主要工作是接收客户端的读写请求, 所以将状态信息写入 zk 或 拉取 zk 中信息不应该使用太多资源, 因此使用 zkfc 来完成. )
注意:在hadoop的HA中, 没有 secondary namenode, stanby namenode 负责原先 sn 元数据合并的任务.
二. 集群规划
hadoop01 | Hadoop02 | hadoop03 | |
---|---|---|---|
hdfs (HA) | namenode | namenode | |
zkfc | zkfc | ||
journalnode | journalnode | journalnode | |
datanode | datanode | datanode | |
mapreduce | |||
yarn (HA) | resourcemanager | resourcemanager | |
nodemanager | nodemanager | nodemanager | |
zookeeper | quorumpeermain | quorumpeermain | quorumpeermain |
6 | 7 | 5 |
三. 前置条件
1. ip
2. 主机名
3. 主机映射
4. 防火墙
5. selinux
6. sudoers (非root用户搭建需配置)
7. 免密登陆
8. 时间同步
四. Hadoop 高可用搭建
1.关闭集群
stop-all.sh
2.删除安装包
rm -rf /opt/hadoop-2.7.6
3.删除数据目录
rm -rf /home/hadoop/data/hadoopdata
tar -zxvf hadoop-2.7.7.tar.gz -C /opt/
vim /etc/profile
export HADOOP_HOME=/opt/hadoop-2.7.7
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
source /etc/profile
[root@hadoop01 soft]# hadoop version
Hadoop 2.7.7
Subversion Unknown -r c1aad84bd27cd79c3d1a7dd58202a8c3ee1ed3ac
Compiled by stevel on 2018-07-18T22:47Z
Compiled with protoc 2.5.0
From source with checksum 792e15d20b12c74bd6f19a1fb886490
This command was run using /opt/hadoop-2.7.7/share/hadoop/common/hadoop-common-2.7.7.jar
hadoop-env.sh
export JAVA_HOME=/opt/jdk1.8.0_73
core-site.xml
<!-- 指定 hdfs 抽象目录树的入口的 nameservice 为 wangdfs -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://wangdfs/</value>
</property>
<!-- 指定 hadoop 工作目录 datanode|namenode存储的数据目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/data/hadoopdata/</value>
</property>
<!-- 指定 zookeeper 集群访问地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>hadoop01:2181,hadoop02:2181,hadoop03:2181</value>
</property>
hdfs-site.xml
<!-- 指定 hdfs 副本数 -->
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<!--指定 hdfs 的 nameservice 为 wangdfs,需要和 core-site.xml 中保持一致-->
<property>
<name>dfs.nameservices</name>
<value>wangdfs</value>
</property>
<!-- wangdfs 下面有两个 NameNode,分别是 nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.wangdfs</name>
<value>nn1,nn2</value>
</property>
<!-- nn1 的 RPC 通信地址 -->
<property>
<name>dfs.namenode.rpc-address.wangdfs.nn1</name>
<value>hadoop01:8020</value>
</property>
<!-- nn1 的 http 通信地址 -->
<property>
<name>dfs.namenode.http-address.wangdfs.nn1</name>
<value>hadoop01:50070</value>
</property>
<!-- nn2 的 RPC 通信地址 -->
<property>
<name>dfs.namenode.rpc-address.wangdfs.nn2</name>
<value>hadoop02:8020</value>
</property>
<!-- nn2 的 http 通信地址 -->
<property>
<name>dfs.namenode.http-address.wangdfs.nn2</name>
<value>hadoop02:50070</value>
</property>
<!-- 指定 NameNode 的 edits 元数据在 JournalNode 上存放位置 journalnode 通信端口8485(用多个;隔开) -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hadoop01:8485;hadoop02:8485;hadoop03:8485/wangdfs</value>
</property>
<!-- 指定 JournalNode 在本地磁盘存放数据的位置 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/home/hadoop/data/hadoopdata/journalnodedata</value>
</property>
<!-- 开启 NameNode 失败自动切换 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!-- 配置失败自动切换实现方式 -->
<!-- 此处配置在安装的时候切记检查不要换行-->
<property>
<name>dfs.client.failover.proxy.provider.wangdfs</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!-- 配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行-->
<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>
mapred-site.xml
mv mapred-site.xml.template mapred-site.xml
<!-- 指定 mr 框架为 yarn 方式 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!-- 设置 mapreduce 的历史服务器地址和端口号 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop03:10020</value>
</property>
<!-- mapreduce 历史服务器的 web 访问地址 -->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop03:19888</value>
</property>
yarn-site.xml
<!-- 开启 RM 高可用 -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!-- 指定 RM 的 cluster id 两个 resourcemanager 起一个 nameservice -->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>wangyarn</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>hadoop02</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>hadoop03</value>
</property>
<!-- 指定 zk 集群地址 -->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>hadoop01:2181,hadoop02:2181,hadoop03:2181</value>
</property>
<!-- 要运行 MapReduce 程序必须配置的附属服务 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!-- 开启 YARN 集群的日志聚合功能 -->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<!-- YARN 集群的聚合日志最长保留时长 -->
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>86400</value>
</property>
<!-- 启用自动恢复 -->
<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
<!-- 制定 resourcemanager 的状态信息存储在 zookeeper 集群上-->
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
slaves, 注意多余空格
hadoop01
hadoop02
hadoop03
scp -r /opt/hadoop-2.7.7 hadoop02:/opt/
scp -r /opt/hadoop-2.7.7 hadoop03:/opt/
scp /etc/profile hadoop02:/etc/
scp /etc/profile hadoop03:/etc/
source /etc/profile
1.在每个节点都启动 zookeeper
zkServer.sh start
2.在每个节点都启动 jounalnode日志平台
hadoop-daemon.sh start journalnode
3.选择一个namenode节点初始化文件系统, hadoop01
hdfs namenode -format
成功: Storage directory /home/hadoop/data/hadoopdata/dfs/name has been successfully formatted.
注意:
成功的格式化只能有一次,若想重新初始化: rm -r /home/hadoop/data/hadoopdata
报错之后按照错误提示修改后重新格式化即可.
4.将 hadoop01 初始化元数据发送至 hadoop02, 保证初始 fsiamge 文件一致
scp -r /home/hadoop/data/hadoopdata hadoop02:/home/hadoop/data/
5.初始化 zkfc, 监控 namenode 的健康状况并写入 zk, 在 hadoop01 或者 hadoop02, 仅执行一次
hdfs zkfc -formatZK
成功输出: Successfully created /hadoop-ha/wangdfs in ZK.
完成后,则会在 zk 中创建一个节点 /hadoop-ha/wangdfs, 存储两个 namenode 的状态信息.
注意: 在此是初始化 zkfc 并非启动. 启动 zkfc 是伴随 hdfs 启动后才可 jps 查看相关进程.
6.启动 (注意顺序)
先在三台机器上分别启动 zookeeper, 再在1节点或者2节点启动hdfs, 然后在2节点(或者3节点)上启动yarn, 最后在3节点(或者2节点上)启动resourcemanager.
①节点1 2 3 zkServer.sh start
②节点1 start-dfs.sh
③节点3 start-yarn.sh [此时仅启动本节点 rm 和三个 nm]
④节点2 yarn-daemon.sh start resourcemanager [启动另一节点的 rm ,实现高可用]
启动成功后查看 jps 相关进程:
启动成功后查看 zk 节点:
[zk: localhost:2181(CONNECTED) 2] ls /
[zookeeper, yarn-leader-election, hadoop-ha, rmstore]
[zk: localhost:2181(CONNECTED) 3] ls /hadoop-ha
[wangdfs]
namenode
http://hadoop01:50070
http://hadoop02:50070
测试高可用:
- kill 掉 active namenode 查看, stanby 是否会自动迅速切换为 active.
- 启动之前 kill 的 active namenode 查看其状态
结果, stanby 自动无缝切换成功 , active 重启后为 stanby.
resourcemanager
http://hadoop02:8088
http://hadoop03:8088
yarn 的高可用表现形式为: 打开网页自动跳转到 active 页面
测试高可用方法, 雷同.
①节点1 stop-dfs.sh
②节点3 stop-yarn.sh [此时仅关闭本节点 rm 和三个 nm]
③节点2 yarn-daemon.sh stop resourcemanager [关闭另一节点的 rm ]
④节点1 2 3 zkServer.sh stop