【概述】
hdfs的HA机制,具体来说可以分为两部分,一部分是基于zkfc、zookeeper完成nn之间的选主;而另一部分则是nn之间的元数据共享与同步。
从hdfs2.0版本开始,引入了HA using Quroum Journal Manager(QJM)方案。
QJM的思想最初来源于paxos协议。在具体实现中,Journal Node(JN)集群作为NN之间editlog的一致性存储系统,也是HDFS高可用方案中的核心组件。
通过JN,ANN可以尽可能及时的将元数据同步到SNN,ANN通过push的方式将editlog写入JN集群,而SNN通过pull的方式从JN中读取editlog,JN之间彼此不主动进行数据的交互。
由于paxos协议的关系,读写JN都要求至少大多数节点成功返回才认为本次请求是成功的。另外,2N+1台JN组成的集群,最多可以容忍N个JN节点异常。因此整体具有很强的HA能力。
本文就其中的一些细节展开进行说明。
【JN中的概念与持久化文件】
一些概念:
epoch
epoch是paxos协议中的一个概念,可以用于标识leader。
而具体实现中,epoch是一个单调递增的整数,用来标识每一次ANN的生命周期,每发生一次NN的主备切换,epoch就会加1。
ANN后续的每个请求中,都会携带epoch,同时JN会对请求进行校验,如果携带的epoch比本地存储的小,则抛出异常;而如果携带的epoch比本地存储的大,则更新本地的epoch。
这就意味着,不管怎样进行NN的切换,任意时刻都只能有1个NN成功写JN。
txid
每条写入的editlog都有一个对应的递增的事务ID。
segment
多个连续的事务(txid)组成一个segment,持久化到一个对应的editlog文件中。
这样,对应到具体实现中, 任何时间,JN上只会有一个segment处于正在写的状态(Inprogress),而其他的segment文件则都处于写完关闭的状态(Finalized)
JN中的持久化文件:
|-- current
| |-- committed-txid
| |-- edits_0000000000000000001-0000000000000000002
| |-- edits_inprogress_0000000000000000003
| |-- last-promised-epoch
| |-- last-writer-epoch
| |-- paxos
| |-- VERSION
|-- in_use.lock
last-promised-epoch
有两个地方会写入,一个是ANN发送新的epoch的rpc请求时,会进行更新;另一个是每次editlog的写请求时,会判断请求中的epoch是否比本地的epoch大,如果是则进行更新,否则会抛出异常。
last-writer-epoch
每写一个新的segment时,检查请求中的epoch是比上次写入的epoch大,如果大,则将当前请求中的epoch写入文件中。
committed-txid
处理每个写editlog的事务请求中,同步更新本地记录的事务ID。
edits_$starttxid-$end