完全解析大数据的高可用集群部署

好程序员IT教育


HA介绍


什么是HA


HA: High Availability,高可用集群,指的是集群7*24小时不间断服务。


为什么需要HA


在HDFS中,有NameNode、DataNode和SecondaryNameNode角色的分布,客户端所有的操作都是要与NameNode交互的,同时整个集群的命名空间信息也都保存在NameNode节点。但是,现在的集群配置中只有一个NameNode,于是就有一个问题: 单点故障


那么,什么是单点故障呢?现在集群中只有一个NameNode,那么假如这个NameNode意外宕机、升级硬件等,导致NameNode不可用了,整个集群是不是也就不可用了?这就是单点故障的问题。


为了解决这样的问题,就需要高可用集群了。


高可用的备份方式


    主从模式(冷备)


准备两台服务器, 准备相同的程序。 一台服务器对外提供服务, 称为主节点(Active节点); 另外一台服务器平时不对外提供服务, 主要负责和Active节点之间进行数据的同步, 称为备份节点(Standby节点). 当主节点出现故障, Standby节点可以自动提升为Active节点, 对外提供服务。
ZooKeeper实现的集群高可用, 采用的就是这种模式。


我作为一个班级的讲师,在班级负责授课的工作。如果我有一天生病请假了,是不是咱们班级就得自习一天了?为了解决这样的问题,教学部安排另外一个讲师,每天跟着我。我上课讲课,他就在旁边听着;我上课提问问题,他就在旁边看着;我去吃饭,他也在旁边跟着;我去上个厕所,他也在跟着!做为我的一个影子存在着。由于这个同时每天都会跟着我,因此我的一言一行,讲了什么内容,留了什么作业,吃了什么饭,抽了几根烟,他都知道!那么,如果有一天我生病请假了,他是不是就可以直接替代我为班级上课呢?


    双主互备(热备)(了解)


准备两台服务器, 准备相同的程序. 同时对外提供服务(此时, 这两台服务器彼此为对方的备份), 这样, 当一台节点宕机的时候, 另外一台节点还可以继续提供服务.


小明到肯德基吃饭,找服务员点餐,这是正常的流程。但是,如果服务员只有一个,并且恰好生病了,那么小明是不是将没有办法正常点餐了。为了解决这个问题,肯德基雇了两个服务员,同时提供服务,这样一个服务员出问题了,另外一个服务员依然可以提供服务。


    集群多备(了解)


基本上等同于双主互备, 区别就在于同时对外提供服务的节点数量更多, 备份数量更多 肯德基觉得两个服务员也不保险,有两个同时生病的可能性,于是又多雇了几个服务员。


高可用的实现


我们在这里采用的是主从模式的备份方式,也就是准备两个NameNode,一个对外提供服务,称为Active节点;另外一个不对外提供服务,只是实时的同步Active节点的数据,称为Standby的节点。


为了提供快速的故障转移,Standby节点还必须具有集群中块位置的最新信息。为了实现这一点,DataNodes被配置了两个NameNodes的位置,并向两者发送块位置信息和心跳信号。也就是说,DataNode同时向两个NameNode心跳反馈。


高可用架构图



编辑


JournalNode


    JournalNode的功能


Hadoop2.x版本之后, Clouera提出了QJM/QuromJournal Manager, 这是一个基于Paxos算法实现的HA的实现方案
1. 基本的原理就是使用2N+1台JN存储EditLog, 每次写入数据的时候, 有半数以上的JN返回成功的信息, 就表示本次的操作已经同步到了JN
2. 在HA中, SecondaryNameNode这个角色已经不存在了, 保证Standby节点的元数据信息与Active节点的元数据信息一致, 需要通过若干个JN
3. 当有任何的操作发生在Active节点上的时候, JN会记录这些操作到半数以上的节点中. Standby节点检测JN中的log日志文件发生了变化, 会读取JN中的数据到自己的内存中, 维护最新的目录树结构与元数据信息
4. 当发生故障的时候, Active节点挂掉, 此时Standby节点在成为新的Active节点之前, 会将读取到的EditLog文件在自己的内存中进行推演, 得到最新的目录树结构. 此时再升为Active节点, 可以无缝地继续对外提供服务.


    防止脑裂的发生


对于HA群集的正确操作至关重要,一次只能有一个NameNode处于Active状态。否则,名称空间状态将在两者之间迅速分散,从而有数据丢失或其他不正确结果的风险。为了确保该属性并防止所谓的“裂脑情况”,JournalNode将一次仅允许单个NameNode成为作者。在故障转移期间,变为活动状态的NameNode将仅承担写入JournalNodes的角色,这将有效地防止另一个NameNode继续处于活动状态,从而使新的Active可以安全地进行故障转移。
- 怎么理解脑裂?
就是Active节点处于网络震荡状态,假死状态,Standby就转为Active。等网络震荡过后,就有两个Active了,这就是脑裂。


    JournalNode集群正常工作的条件


- 至少3个Journalnode节点
- 运行个数建议奇数个(3,5,7等)
- 满足(n+1)/2个以上,才能正常服务。即能容忍(n-1)/2个故障。


    JournalNode的缺点


在这种模式下,即使活动节点发生故障,系统也不会自动触发从活动NameNode到备用NameNode的故障转移,必须需要人为的操作才行。要是有一个能监视Active节点的服务功能就好了。
这个时候,我们就可以使用zookeeper集群服务,来帮助我们进行自动容灾了。


自动容灾原理


如果想进行HA的自动故障转移,那么需要为HDFS部署两个新组件:ZooKeeper quorum和ZKFailoverController进程(缩写为ZKFC)


Zookeeper quorum


Apache ZooKeeper是一项高可用性服务,用于维护少量的协调数据,将数据中的更改通知客户端并监视客户端的故障。HDFS自动故障转移的实现依赖ZooKeeper进行以下操作:


- 故障检测
集群中的每个NameNode计算机都在ZooKeeper中维护一个持久性会话。如果计算机崩溃,则ZooKeeper会话将终止,通知另一个NameNode应触发故障转移。
- 活动的NameNode选举(HA的第一次启动)
ZooKeeper提供了一种简单的机制来专门选举一个节点为活动的节点。如果当前活动的NameNode崩溃,则另一个节点可能会在ZooKeeper中采取特殊的排他锁,指示它应成为下一个活动的NameNode。


ZKFC


ZKFailoverController(ZKFC)是一个新组件,它是一个ZooKeeper客户端,它监视和管理namenode的状态。运行namenode的每台机器都会运行一个ZKFC,该ZKFC负责以下内容:


- 运行状况监视
ZKFC使用运行状况检查命令定期ping其本地NameNode。只要NameNode以健康状态及时响应,ZKFC就会认为该节点是健康的。如果节点崩溃,冻结或以其他方式进入不正常状态,则运行状况监视器将其标记为不正常。
- ZooKeeper会话管理
当本地NameNode运行状况良好时,ZKFC会在ZooKeeper中保持打开的会话。如果本地NameNode处于活动状态,则它还将持有一个特殊的“锁定” znode。该锁使用ZooKeeper对“临时”节点的支持。如果会话到期,则锁定节点将被自动删除。
- 基于ZooKeeper的选举
如果本地NameNode运行状况良好,并且ZKFC看到当前没有其他节点持有锁znode,则它本身将尝试获取该锁。如果成功,则它“赢得了选举”,并负责运行故障转移以使其本地NameNode处于活动状态。故障转移过程类似于上述的手动故障转移:首先,如有必要,将先前的活动节点隔离,然后将本地NameNode转换为活动状态。


自动容灾的过程描述


ZKFC(是一个进程,和NN在同一个物理节点上)有两只手,分别拽着NN和Zookeeper。(监控NameNode健康状态,并向Zookeeper注册NameNode);集群一启动,2个NN谁是Active?谁又是Standby呢?
2个ZKFC先判断自己的NN是否健康,如果健康,2个ZKFC会向zoopkeeper集群抢着创建一个节点,结果就是只有1个会最终创建成功,从而决定active地位和standby位置。如果ZKFC1抢到了节点,ZKFC2没有抢到,ZKFC2也会监控watch这个节点。如果ZKFC1的Active NN异常退出,ZKFC1最先知道,就访问ZK,ZK就会把曾经创建的节点删掉。删除节点就是一个事件,谁监控这个节点,就会调用callback回调,ZKFC2就会把自己的地位上升到active,但在此之前要先确认ZKFC1的节点是否真的挂掉?这就引入了第三只手的概念。
ZKFC2通过ssh远程连接NN1尝试对方降级,判断对方是否挂了。确认真的不健康,才会真的 上升地位之active。所以ZKFC2的步骤是:
1.创建新节点。
2.第三只手把对方降级。
3.把自己升级
那如果NN都没毛病,ZKFC挂掉了呢?Zoopkeeper有一个客户端session机制,集群启动之后,2个ZKFC除了监控自己的NN,还要和Zoopkeeper建立一个tcp长连接,并各自获取自己的session。只要一方的session失效,Zoopkeeper 就会删除该方创建的节点,同时另一方创建节点,上升地位。


HA的配置


守护进程布局


qianfeng01: NameNode、DataNode、JournalNode、QuorumPeerMain、ZKFC
qianfeng02: NameNode、DataNode、JournalNode、QuorumPeerMain、ZKFC
qianfeng03: DataNode、JournalNode、QuorumPeerMain


现在,先停止HDFS的进程,修改如下的配置文件吧!


hdfs-site.xml


<!-- 注意: 高可用的集群,没有SecondaryNameNode的存在,因此在这个文件中之前存在的SecondaryNameNode的配置需要删除 --> <configuration><!-- 配置NameNode的逻辑名称 --><!-- 注意: 后面的很多参数配置都是需要使用到这个名称的 --><property><name>dfs.nameservices</name><value>supercluster</value></property><!-- 配置两个NameNode的唯一标识符 --><property><name>dfs.ha.namenodes.supercluster</name><value>nn1,nn2</value></property><!-- 针对每一个NameNode,配置自己的RPC通信地址和端口 --><property><name>dfs.namenode.rpc-address.supercluster.nn1</name><value>qianfeng01:9820</value></property><property><name>dfs.namenode.rpc-address.supercluster.nn2</name><value>qianfeng02:9820</value></property><!-- 针对每一个NameNode,配置WebUI的地址和端口 --><property><name>dfs.namenode.supercluster.nn1</name><value>qianfeng01:9870</value></property><property><name>dfs.namenode.supercluster.nn2</name><value>qianfeng02:9870</value></property><!-- 定义journalnode进程的数据存储的父路径, 目录在上面已经定义好了的:journalData --><property><name>dfs.journalnode.edits.dir</name><value>/usr/local/hadoop-3.3.1/tmp</value></property><!-- 配置journalnode的服务器地址和存储目录(数目为奇数个) --><!-- 服务器地址使用分号“;”作为分隔符--><property><name>dfs.namenode.shared.edits.dir</name><value>qjournal://qianfeng01:8485;qianfeng02:8485;qianfeng03:8485/journalData</value></property><!-- 指定客户端连接Active的namenode节点的java类型 --><property><name>dfs.client.failover.proxy.provider.supercluster</name><value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value></property><!--为了保证系统的正确性,在任何时间只有一个NameNode处于Active状态,需要配置一个防护机制 --><property><name>dfs.ha.fencing.methods</name><value>sshfence</value></property><!--为了使该防护选项起作用,它必须能够在不提供密码的情况下SSH到目标节点。因此,还必须配置以下属性--><property><name>dfs.ha.fencing.ssh.private-key-files</name><value>/root/.ssh/id_rsa</value></property><!-- 免密登陆超时时间,超过此时间未连接上,则登陆失败,此配置可选--><property><name>dfs.ha.fencing.ssh.connect-timeout</name><value>30000</value></property><!-- 支持自动容灾属性 --><property><name>dfs.ha.automatic-failover.enabled</name><value>true</value></property><!-- 块的副本数量 --><property><name>dfs.replication</name><value>3</value></property> </configuration>


core-site.xml


<configuration><!--注意:使用到的是在hdfs-site.xml中配置的逻辑名称 --><property><name>fs.defaultFS</name><value>hdfs://supercluster</value></property><!-- hdfs的数据保存的路径,被其他属性所依赖的一个基础路径 --><property><name>hadoop.tmp.dir</name><value>/usr/local/hadoop-3.3.1/tmp</value></property><!-- ZooKeeper服务的地址 --><property><name>ha.zookeeper.quorum</name><value>qianfeng01:2181,qianfeng02:2181,qianfeng03:2181</value></property> </configuration>


hadoop-env.sh


# 添加两行export HDFS_JOURNALNODE_USER=rootexport HDFS_ZKFC_USER=root


分发配置文件到其他节点


[root@qianfeng01 ~]# cd $HADOOP_HOME/etc [root@qianfeng01 hadoop]# scp -r hadoop qianfeng02:$PWD [root@qianfeng01 hadoop]# scp -r hadoop qianfeng03:$PWD


启动集群


现在,集群已经搭建成为了高可用的集群了。在启动集群之前,我们需要先明确一件事情: 集群现在的状态有两种:


    这个集群我之前使用过,NameNode已经存储有数据了(fsimage和edits已生成)

    这个集群是我新搭建的,我直接搭建集群的时候就搭建的高可用的集群,之前从来没有启动过


如果你是第一种情况,请跳转到 普通集群转HA


如果你是第二种情况,请跳转到 直接搭建HA


启动: 普通集群转HA


# 1. 启动集群的JournalNode服务。#注意事项: 如果之前集群还在运行,需要先将其停止!使用命令 stop-dfs.sh[root@qianfeng01 ~]# hdfs --daemon start journalnode[root@qianfeng02 ~]# hdfs --daemon start journalnode[root@qianfeng03 ~]# hdfs --daemon start journalnode# 2. 启动以前节点上的namenode进程[root@qianfeng01 ~]# hdfs --daemon start namenode# 3. 在新的namenode节点上拉取镜像文件[root@qianfeng02 ~]# hdfs namenode -bootstrapStandby# 4. 同步日志到journalnode集群上,再启动集群#先关namenode[root@qianfeng01 ~]# hdfs --daemon stop namenode# 再同步日志[root@qianfeng01 ~]# hdfs namenode -initializeSharedEdits# 5. 格式化zkfc# 5.1. 前提QuorumPeerMain服务必须处于开启状态,客户端zkfc才能格式化成功[root@qianfeng01 ~]# zkServer.sh start[root@qianfeng02 ~]# zkServer.sh start[root@qianfeng03 ~]# zkServer.sh start# 5.2. 选择其中一个namenode节点进行格式化zkfc[root@qianfeng01 ~]# hdfs zkfc -formatZK# 6. 你就可以快乐的开启HA集群进行测试了[root@qianfeng01 ~]# start-all.sh# 查看NameNode的状态[root@qianfeng01 ~]# hdfs haadmin -getServiceState nn1# 注意: 以后开HA集群时,要先开zookeeper服务,再开HDFS。


启动: 直接搭建HA


# 1. 启动三个节点上的journalnode服务[root@qianfeng01 ~]# hdfs --daemon start journalnode[root@qianfeng02 ~]# hdfs --daemon start journalnode[root@qianfeng03 ~]# hdfs --daemon start journalnode# 2. 格式化namenode#- 先删除所有节点的${hadoop.tmp.dir}/tmp/的数据(可选,这一步表示弃用fsimage.)#- 选择其中一个namenode进行格式化[root@qianfeng01 ~]# hdfs namenode -format#- 并启动namenode进程[root@qianfeng01 ~]# hdfs --daemon start namenode# 3. 在另一台namenode上拉取已格式化的那台机器的镜像文件(数据的一致性)[root@qianfeng02 ~]# hdfs namenode -bootstrapStandby# 4. 然后关闭已经启动的namenode[root@qianfeng01 ~]# hdfs --daemon stop namenode# 5. 格式化zkfc# 5.1. 前提QuorumPeerMain服务必须处于开启状态,客户端zkfc才能格式化成功[root@qianfeng01 ~]# zkServer.sh start[root@qianfeng02 ~]# zkServer.sh start[root@qianfeng03 ~]# zkServer.sh start# 5.2. 选择其中一个namenode节点进行格式化zkfc[root@qianfeng01 ~]# hdfs zkfc -formatZK# 6. 你就可以快乐的开启HA集群进行测试了[root@qianfeng01 ~]# start-all.sh# 注意:以后开HA集群时,要先开zookeeper服务,再开HDFS。


自动容灾测试


由于CentOS7的minimal版本缺少容灾切换ActiveNameNode节点时所需要的组件,因此需要手动安装一下:


yum install -y psmisc


1. 首先查看当前活跃的Active节点是谁
2. Kill掉活跃节点上的NameNode进程,模拟宕机
3. 观察另外一个节点,是否已经变成Active的状态




优秀的你与大厂之间只差一个“好程序员”!

版权声明:完全解析大数据的高可用集群部署内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系 删除。本文链接:https://www.qi520.com/n/17484.html