1.原理图
2. HDFS HA- - Namenode HA 工作原理
2台独立的机器的来配置NameNode角色,无论在任何时候,集群中只能有一个
NameNode作为Active状态,而另一个是Standby状态。Active状态的NameNode负责
集群中所有的客户端操作,状态为Standby的NameNode这时候仅仅扮演一个Slave的
角色,以便于在任何时候Active的NameNode挂掉时能够第一时间接替它的任务,成为
主NameNode,达到一个热备份的效果.
为了保持从NameNode与主NameNode的元数据保持一致,他们之间的交互通过一系
列守护的轻量级进程JournalNode来完成,当任何修改操作在主NameNode上执行时,
它同时也会记录修改log到至少半数以上的JornalNode中,这时状态为Standby的
NameNode监测到JournalNode里面的同步log发生变化了,会读取JornalNode里面的
修改log,然后同步到自己的的目录镜像树里面.
当发生故障时,Active的NameNode挂掉后,Standby的NameNode会在它成为Active
NameNode前,读取所有的JournalNode里面的修改日志,这样就能高可靠的保证与挂
掉的NameNode的目录镜像树一致,然后无缝的接替它的职责,维护来自客户端请求,
从而达到一个高可用的目的。
为了达到快速容错掌握全局的目的,Standby角色也会接受来自DataNode角色汇报的
块信息。
3. HDFS HA- - ZKFailoverController
ZKFailoverController作为独立的进程运行,简称ZKFC,对NameNode的主备切换进行总
体控制。ZKFailoverController能及时检测到NameNode的健康状况,在主NameNode故障
时借助Zookeeper实现自动的主备选举和切换.每个运行NameNode的机器上都会运行一个
ZKFC。
ZKFC的作用如下:
NameNode健康状况监控:
ZKFC定期以RPC的方式向本地的NameNode发送健康检查命令,只要NameNode及时回复自己是健康
的,那么ZKFC则认为NameNode是健康的。如果NameNode宕机、卡死,则ZKFC则认为NameNode
是不健康的。
ZK会话管理:
当本地的NameNode是健康的,ZKFC则以心跳的方式保持一个会话。如果本地的NameNode是Active
的,ZKFC也在ZK上持有一个特殊lock znode,如果ZKFC检测到NameNode时不健康的,则停止向ZK上
报心跳,会话失效,Lock node过期删除。
ZK选举:
如果本地的NameNode是健康的,ZKFC也没有看到其他NameNode持有lock znode,它将试着获取lock
znode,如果成功,即赢得了选举,则它本地的namenode变为active.
ZKFC为什么要作为一个deamon进程从NN分离出来?
防止因为NN的GC失败导致心跳受影响。
FailoverController功能的代码应该和应用的分离,提高的容错性。
使得主备选举成为可插拔式的插件。
4.HDFS HA-共享存储QJM
NameNode记录了HDFS的目录文件等元数据,客户端每次对文件的增删改等操
作,Namenode都会记录一条日志,叫做editlog,而元数据存储在fsimage中。为了保持
Stadnby与active的状态一致,standby需要尽量实时获取每条editlog日志,并应用到
FsImage中。这时需要一个共享存储存放editlog,standby能实时获取日志。
3. HDFS HA- - 共享存储 QJM
有两个关键点需要保证:
共享存储是高可用的。
需要防止两个NameNode同时向共享存储写数据导致数据损坏。
共享存储常用的方式是Qurom Journal Manager,它包含多个JournalNode 。
QJM可以认为是包含一些JournalNode的集群,JournalNode运行在不同的机器
上,每个JournalNode是一个很轻量的守护进程,所以可以部署在hadoop集群的节点上,
QJM中至少要有3个JournalNode,因为edit log必须要写到JournalNodes中大部分节点中,
比如运行3,5,7个JournalNode,如果你运行了N个JournalNode,那么系统可以容忍最多
(N-1)/2个节点失败。
共享存储实现逻辑:
初始化后,Active NN把editlog写到大多数JN并返回成功(即大于等于N+1)即认定写
成功。
Standby NN定期从JN读取一批editlog,并应用到内存中的FsImage中。
NameNode每次写Editlog都需要传递一个编号Epoch给JN,JN会对比Epoch,如果比
自己保存的Epoch大或相同,则可以写,JN更新自己的Epoch到最新,否则拒绝操作。
在切换时,Standby转换为Active时,会把Epoch+1,这样就防止即使之前的
NameNode向JN写日志,即使写也会失败。
5.HDFS HA-防止脑裂
确保只有一个NN能命令DN。
每个NN改变状态的时候,向DN发送自己的状态和一个***。
DN在运行过程中维护此***,当failover时,新的NN在返回DN心跳时,会返回自己
的active状态和一个更大的***。DN接收到这个返回时,认为该NN为新的active。
如果这时原来的active(比如GC)恢复,返回给DN的心跳信息包含active状态和原来
的***,这时DN就会拒绝这个NN的命令。