HadoopHDFS高可用(HA)

Hadoop高可用(HA)

高可用架构

1.Hadoop1.x版本呢所带来的问题

使用场景:

1.单点故障
a. 每个群集只有一个NameNode,NameNode存在单点故障(SPOF)。
b. 如果该计算机或进程不可用,则整个群集在整个NameNode重新启动或在另一台计算机上启动之前将不可用
c. 如果发生意外事件(例如机器崩溃),则在操作员重新启动NameNode之前,群集将不可 用。
d. 计划内的维护事件,例如NameNode计算机上的软件或硬件升级,将导致群集停机时间的延 长
2、水平扩展 将来服务器启动的时候,启动速度慢
3、namenode随着业务的增多,内存占用也会越来越多 如果namenode内存占满,将无法继续提供服务
4、日志丢失问题

2.设计思路

1、hadoop2.x启用了主备节点切换的模式(1主1备)
2、当主节点出现异常的时候,集群直接将备用节点切换成主节点
    要求备用节点马上就要工作
    主备节点内存几乎同步有
3、独立的线程对主备节点进行监控健康状态
4、需要有一定的选举机制,帮助我们确定主从关系
5、我们需要实时存储日志的中间件

3.组织架构

hadoop高可用HA

Active NameNode(ANN)

​ a. 它的功能和原理的NN的功能是一样的

​ b. 接受客户端请求,查询数据块DN信息

​ c. 存储数据的元数据信息

​ 数据文件:Block:DN的映射关系

​ d. 工作

​ 启动时:接受DN的block汇报

​ 运行时:和DN保持心跳(3s,10m)

​ e. 存储介质

​ 完全基于内存

​ 优点:数据处理效率高

​ 缺点:数据的持久化(日志edits+快照fsimage)

Standby NameNode(SNN)

​ a. Standby NameNode:NN的备用节点

​ b. 他和主节点做同样的工作,但是它不会发出任何指令(同一时刻,集群只能有一个活跃的节点)

​ c. 存储:数据的元数据信息

​ 数据文件:Block:DN的映射关系
​ 它的内存数据和主节点内存数据几乎是一致的

​ d. 工作:

​ 启动时: 接受DN的block汇报
​ 运行时: 和DN保持心跳(3s,10m)

​ e. 存储介质:完全基于内存

​ 优点:数据处理效率高

​ 缺点:数据的持久化

DataNode(DN)

​ a. 存储文件的Block数据

​ b. 介质:硬盘

​ c. 启动时:同时向两个NN汇报Block信息

​ d. 运行中:同时和两个主节点保持心跳机制

JournalNode(JN)

​ a. Quorum JournalNode Manager 共享存储系统,NameNode通过共享存储系统实现日志数据同步。

​ b. JournalNode是一个独立的小集群,它的实现原理和Zookeeper的一致( Paxos)

​ c. ANN产生日志文件的时候,就会同时发送到 JournalNode的集群中每个节点上

​ d. JournalNode不要求所有的jn节点都接收到日志,只要有半数以上的(n/2+1)节点接受收到日志,那么本条日志就生效

​ e. SNN每间隔一段时间就去QJM上面取回最新的日志

​ SNN上的日志有可能不是最新的

​ f. HA集群的状态正确至关重要,一次只能有一个NameNode处于活动状态

​ g. JournalNode只允许单个NameNode成为活跃的主节点。在故障转移期间,将变为活动状态的NameNode 将承担写入JournalNodes的角色,这将有效地防止另一个NameNode继续处于活动状态,从而使 新的Active节点可以安全地进行故障转移。

Failover Controller(ZKFC:故障转移控制器)

# 对 NameNode 的主备切换进行总体控制,能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换,为了防止因为NN的GC失败导致心跳受影响,ZKFC作为一个deamon进程从NN分离出来

1) 启动时:

​ 当集群启动时,主备节点的概念是很模糊的
​ 当ZKFC只检查到一个节点是健康状态,直接将其设置为主节点
​ 当zkfc检查到两个NN节点是的健康状态,发起投票机制
​ 选出一个主节点,一个备用节点,并修改主备节点的状态

一个常见的问题:如果启动的时候,发现有两个备用节点,肯定是因为没有选举,检查一下zookeeper有没有启动起来,如果还是失败,重启一下

问题:

​ 1、SNN为什么不直接去ANN去同步数据。

​ 2、SNN挂了谁去合并日志呢?没有人

2) 运行时:

由 ZKFailoverController、HealthMonitor 和 ActiveStandbyElector 这 3 个组件来协同实现主备切换

​ a. ZKFailoverController启动的时候会创建 HealthMonitor 和 ActiveStandbyElector 这两 个主要的内部组件
​ b. HealthMonitor 主要负责检测 NameNode 的健康状态

​ c. ActiveStandbyElector 主要负责完成自动的主备选举,内部封装了 Zookeeper 的处理逻辑

3) 主备节点正常切换
NameNode 在选举成功后, ActiveStandbyElector 会在 zk 上创建一个
ActiveStandbyElectorLock 临时节点,而没有选举成功的备 NameNode 中的ActiveStandbyElector 会监控这个节点

​ 如果 Active NameNode 对应的 HealthMonitor 检测到 NameNode 的状态异常时,ZKFailoverController 会主动删除当前在 Zookeeper 上建立的临时节点ActiveStandbyElectorLock

​ 处于 Standby 状态的 NameNode 的 ActiveStandbyElector 注册的监听器就会收到这个节点的 NodeDeleted 事件,并创建 ActiveStandbyElectorLock 临时节点,本来处于 Standby 状态的 NameNode 就选举为 Active NameNode 并随后开始切换为 Active 状态。

​ 如果是 Active NameNode 的机器整个宕掉的话,那么跟 zookeeper 连接的客户端线程也挂了 , 会话结束 , 那么根据 Zookeepe 的临时节点特性, ActiveStandbyElectorLock 节点会自动被删除,从而也会自动进行一次主备切换,

Zookeeper
为主备切换控制器提供主备选举支持。
辅助投票
和 ZKFC 保持心跳机制,确定 ZKFC 的存活

运行流程

首先要有两个主节点,一个作为活跃主节点(来接受命令执行命令),一个作为备份主节点(不能接受任何命令,拍摄快照)

​ 在客户端的发送请求的时候,主节点先写日志再处理请求(在高可用中没有secondarynamenode),在客户端发送请求或缺的主节点都会向JournalNode同步一份,( JournalNode不要求所有的jn节点都接收到日志,只要有半数以上的(n/2+1)节点接受收到日志,那么本条日志就生效),然后备份主节点就一直从JournalNode拉取日志,当拉去到达一定阈值的时候,备份主节点会与本地的镜像做合并,合并后同步一份到活跃主节点中,并由活跃主节点进行校验,检查通过后,本地保存一份,活跃主节点保存一份,(在两个主节点刚开始启动服务格式化的情况下,都会保存快照fsiamge0000000000,活跃主节点每次接受一个客户端的请求,他都会先将数据传到JournalNode中再做操作,而备份主节点就会一直拉取JournalNode上的日志文件并与自己本地的进行合并,然后发给活跃主节点一份,让活跃主节点及进行校验,检验成功活跃主节点保存一份,本地保存一份),每一个主节点都有一个zkfc来监控,通过HealthMonitor 来监控每个节点的状态,然后在zkfc上面有一个zookeeper集群(对应的集群里当然也存在相应的节点,奇数),当检测到有活跃节点的时候,向zookeeper创建临时节点,然后备份主节点的zkfc进行监控活跃主节点的临时节点,当活跃主节点挂了,随之临时节点消失了,这时候监控的备份主节点发现监控的临时文件没有了,这时候zookeeper内部通过ActiveStandbyElector 主要负责完成自动的主备选举,NameNode 在选举成功后, ActiveStandbyElector 会在 zk 上创建一个ActiveStandbyElectorLock 临时节点,而没有选举成功的备 NameNode 中的ActiveStandbyElector 会监控这个节点。如果 Active NameNode 对应的 HealthMonitor 检测到 NameNode 的状态异常时,ZKFailoverController 会主动删除当前在 Zookeeper 上建立的临时节点ActiveStandbyElectorLock。处于 Standby 状态的 NameNode 的 ActiveStandbyElector 注册的监听器就会收到这个节点的 NodeDeleted 事件,并创建 ActiveStandbyElectorLock 临时节点,本来处于 Standby 状态的 NameNode 就选举为 Active NameNode 并随后开始切换为 Active 状态。如果是 Active NameNode 的机器整个宕掉的话,那么跟 zookeeper 连接的客户端线程也挂了 , 会话结束 , 那么根据 Zookeepe 的临时节点特性, ActiveStandbyElectorLock 节点会自动被删除,从而也会自动进行一次主备切换,

脑裂

定义:

脑裂是Hadoop2.x版本后出来的问题,实际运行过程中有可能有两个namenode同时服务于整个集群的情况,这种情况称之为脑裂

原因:

在主从节点切换时,由于活跃节点的网络延迟,设备故障等问题所引起问题,另一台namenode会认为活跃的namenode成为了失效状态,此时备份主节点转换为活跃状态,此时集群里将会出现两个活跃的namenode,因此,可能出现的因素有网络延迟,心跳故障,设备故障等

脑裂场景:

在namenode垃圾回收时,可能会长时间内整个系统无响应

zkfc客户端也就无法向zk写入心跳信息,这样的话可能导致临时节点掉线,备namenode会切换到活跃状态

这种状态可能会导致整个集群会同时有两个namenode活跃主节点。

脑裂问题的解决方案是隔离( Fencing )

  1. 第三方共享存储:任一时刻,只有一个 NN 可以写入;
  2. DataNode :需要保证只有一个 NN 发出与管理数据副本有关的命令;
  3. Client 需要保证同一时刻只有一个 NN 能够对 Client 的请求发出正确的响应。
    a) 每个 NN 改变状态的时候,向 DN 发送自己的状态和一个本次选举对应的序列号。
    b) DN 在运行过程中维护此序列号,当 failover 时,新的 NN 在返回 DN 心跳时会返回自己的 active 状态和一个更大的序列号。
    DN 接收到这个返回是认为该 NN 为新的 active 。
    (c) 如果这时原来的 active (比如 GC )恢复,返回给 DN 的心跳信息包含 active 状态和原来的序列号,这时 DN 就会拒绝这个 NN 的命令。
    解决方案
    ActiveStandbyElector 为了实现 fencing ,当 NN 成为 ANN 之后创建 Zookeeper 临时节点ActiveStandbyElectorLock ,创建 ActiveBreadCrumb 的持久节点,这个节点里面保存了这个Active NameNode 的地址信息 (node-01)
    Active NameNode 的 ActiveStandbyElector 在正常的状态下关闭 Zookeeper Session 的时候,会一起删除这个持久节点
    但如果 ActiveStandbyElector 在异常的状态下关闭,那么由于 /hadoop ha/${dfs.nameservices}/ActiveBreadCrumb 是持久节点,会一直保留下来,后面当另一个NameNode 选主成功之后,会注意到上一个 Active NameNode 遗留下来的这个节点,从而会回调 ZKFailoverController 的方法对旧的 Active NameNode 进行 fencing 。
    首先尝试调用这个旧 Active NameNode 的 HAServiceProtocol RPC 接口的transitionToStandby 方法,看能不能把它转换为 Standby 状态;
    如果 transitionToStandby 方法调用失败,那么就执行 Hadoop 配置文件之中预定义的隔离措施。
  4. sshfence :通过 SSH 登录到目标机器上,执行命令 fuser 将对应的进程杀死
  5. shellfence :执行一个用户自定义的 shell 脚本来将对应的进程隔离
    在成功地执行完成 fencing 之后,选主节点成功的 ActiveStandbyElector 才会回调ZKFailoverController 的 becomeActive 方法将对应的 NameNode 转换为 Active 状态,开始对外提供服务。新的主创建临时节点 ActiveStandbyElectorLock ,创建持久化节点 ActiveBreadCrumb ,并将自己的主机地址 Node02 赋值给初始化节点

单NN局限性

Namespace(命名空间)的限制

单个datanode从4T增长到36T,集群的尺寸增长到8000个datanode。存储的需求从12PB增长到大于100PB。

性能的瓶颈

由于是单个Namenode的HDFS架构,因此整个HDFS文件系统的吞吐量受限于单个Namenode的吞吐量。毫无疑问,这将成为下一代MapReduce的瓶颈。

隔离问题

由于HDFS仅有一个Namenode,无法隔离各个程序,因此HDFS上的一个实验程序就很有可能影响整个HDFS上运行的程序。那么在HDFS Federation中,可以用不同的Namespace来隔离不同的用户应用程序,使得不同Namespace Volume中的程序相互不影响。

集群的可用性

在只有一个Namenode的HDFS中,此Namenode的宕机无疑会导致整个集群不可用。

Namespace和Block Management的紧密耦合

当前在Namenode中的Namespace和Block Management组合的紧密耦合关系会导致如果想要实现另外一套Namenode方案比较困难,而且也限制了其他想要直接使用块存储的应用。

为什么纵向扩展目前的Namenode不可行?比如将Namenode的 JVM Heap空间扩大到512GB。

这样纵向扩展带来的第一个问题就是启动问题,启动花费的时间太长。当前具有50GB Heap Namenode的HDFS启动一次大概需要30分钟到2小时,那512GB的需要多久?第二个潜在的问题就是Namenode在Full GC时,如果发生错误将会导致整个集群宕机。第三个问题是对大JVM Heap进行调试比较困难。优化Namenode的内存使用性价比比较低。

federation

hadoop联邦机制

NameNode提供了命名空间(NameSpace)和块(Block)管理功能。
HDFS 联邦拥有多个独立的命名空间,每个空间管理属于自己的一组块,这些同组的块构成了“块 池”(Block Pool)。
所有的NameNode 会共享底层的数据节点的存储资源。数据节点是一个物理概念,块池则属于逻辑概念。

Block pool(块池)

​ 所谓Block pool(块池)就是属于单个命名空间的一组block(块)管理区域。
​ 每一个datanode为所有的block pool存储块。
​ Datanode是一个物理概念,而block pool是一个重新将block划分的逻辑概念。

​ 同一个datanode中可以存着属于多个block pool的多个块。

​ Block pool允许一个命名空间在不通知其他命名空间的情况下为一个新的block创建Block ID。同时,一个Namenode失效不会影响其下的datanode为其他Namenode的服务。
​ 当datanode与Namenode建立联系并开始会话后自动建立Block pool。每个block都有一个唯一的标识,这个标识我们称之为扩展的块ID(Extended Block ID)= BlockID+BlockID。这个扩展的块ID在HDFS集群之间都是唯一的,这为以后集群归并创造了条件。
​ Datanode中的数据结构都通过块池ID(BlockPoolID)索引,即datanode中的BlockMap,storage等都通过BPID索引。
​ 在HDFS中,所有的更新、回滚都是以Namenode和BlockPool为单元发生的。即同一HDFS Federation中不同的Namenode/BlockPool之间没有什么关系。
​ 目前Hadoop版本中Block Pool的管理功能依然放在了Namenode中,将来的版本中会将Block Pool的管理功能移动的新的功能节点中。

Namespace Volume(命名空间卷)

​ 一个Namespace和它的块池合并在一起称为Namespace Volume,它是一个独立完整的管理单元。

​ 当一个Namenode/Namespace被删除,与之相对应的块池也被删除。

​ 在升级时,每一个nanespace Volume也会整体作为一个单元。

通过多个namenode/namespace把元数据的存储和管理分散到多个节点中

​ 降低单个节点数据压力,计算压力

namenode/namespace可以通过增加机器来进行水平扩展

​ 可以让更多的节点参与到运算

​ namespace命名空间,通过这种方式确定要处理数据的路径

我们可以通过namenode和namespace组合使用

​ 所有的nn共享dn

​ 但是每一个namespace会单独管理自己的模块

​ 会创建一个管理块的机制:blocks pool

注意:联邦机制和HA完全不一样的,是解决不一样的问题,联邦机制解决的是业务水平扩展的问题,HA解决的是单点故障的问题

Linux搭建高可用服务

1、上传安装包到master并解压
tar -xvf zookeeper-3.4.6.tar.gz

2、配置环境变量
vim /etc/profile

export ZOOKEEPER_HOME=/usr/local/soft/zookeeper-3.4.6
export PATH=$PATH:$ZOOKEEPER_HOME/bin

source /etc/profile

3、修改配置文件
cd conf

修改配置文件,重新复制一份,那个是模板

​ cp zoo_sample.cfg zoo.cfg

修改
dataDir=/usr/local/soft/zookeeper-3.4.6/data

增加
server.0=master:2888:3888
server.1=node1:2888:3888
server.2=node2:2888:3888

image-20220823194415456

4、同步到其它节点
scp -r zookeeper-3.4.6 node1:pwd
scp -r zookeeper-3.4.6 node2:pwd

配置node1和node2的环境变量
scp /etc/profile node1:/etc/
scp /etc/profile node2:/etc/

在所有节点执行
source /etc/profile

4、创建/usr/local/soft/zookeeper-3.4.6/data目录,所有节点都要创建

mkdir /usr/local/soft/zookeeper-3.4.6/data

在data目录下创建myid文件
vim myid 
master,node1,node2分别加上0,1,2

5、启动zk,
zkServer.sh start 三台都需要执行

zkServer.sh status 查看状态

当有一个leader的时候启动成功

连接zk
zkCli.sh

zk  是一个目录结构 ,每个节点可以存数据,同时可以有子节点

zk shell

创建目录
create /test test
create /test/a 1


获取数据
get /test
 
ls /test

delete 只能删除没有子节点的节点
rmr /test  删除节点

关闭命令

zkServer.sh stop

拍摄快照

重置zk
1、杀掉所有zk进程
kiil -9 pid

2、删除data目录下的version文件, 所有节点都要删除
rm -rf /usr/local/soft/zookeeper-3.4.6/data/version-2

2、启动zk
zkServer.sh start

HDFS高可用搭建(HA)

	ZK	NN	DN	RM	NM	JN	ZKFC

master 1 1 1 1 1
node1 1 1 1 1 1 1 1
node2 1 1 1 1

1、防火墙
service firewalld stop
2、时间同步
yum install ntp
ntpdate -u s2c.time.edu.cn

或者
date -s 20180503

3、免密钥 (远程执行命令)
在两个主节点生成密钥文件
ssh-keygen -t rsa
ssh-copy-id ip

master-->master,node1,node2
node1-->master,node1,node2

4、修改hadoop配置文件
core-site.xml
hdfs-site.xml

停止HDFS集群:stop-dfs.sh


同步到其它节点
	cd /usr/local/soft/hadoop-2.7.6/etc/hadoop
	scp ./* node1:`pwd`
	scp ./* node2:`pwd`
	配置环境变量使其生效

5、删除hadoop数据存储目录下的文件 每个节点都需要删除
rm -rf /usr/local/soft/hadoop-2.7.6/tmp

6、启动zookeeper 三台都需要启动
zkServer.sh start
zkServer.sh status

7、启动JN存储hdfs元数据
三台JN上执行 启动命令:
hadoop-daemon.sh start journalnode

8、格式化 在一台NN上执行,这里选择master
hdfs namenode -format
启动当前的NN
hadoop-daemon.sh start namenode(作为主节点)

9、执行同步 没有格式化的NN上执行 在另外一个namenode上面执行 这里选择node1
hdfs namenode -bootstrapStandby(作为备用主节点)

10、格式化ZK 在master上面执行
!!一定要先 把zk集群正常 启动起来
hdfs zkfc -formatZK

11、启动hdfs集群,在master上执行
start-dfs.sh

12.如果想在浏览器上查看活跃主节点的状态,可以通过master01:50070进行查看,也可以通过node01:50070进行查看备用节点。

13.如果关闭集群的话

stop-all.sh

关闭Hadoop的所有服务,接着使用zkServer.sh stop关闭三台zookeeper的服务,至此hdfs的高可用搭建完毕!

posted @ 2022-08-23 22:40  996开发  阅读(482)  评论(0)    收藏  举报