一 Adtive NameNode / Standby NameNode的读写editlog
ActiveNameNode负责往JournalNode写editlog,Standby NameNode负责从这些JournalNameNode读取editlog,然后同步到自己的内存中,保证和Active NameNode的元数据一致
二 StandbyNameNode如何定期到JournalNode上进行同步editlog
EditLogTailer是一个会定期读取edit 日志并且应用事务的线程。
logRollPeriodMs:ActiveNameNode写入新editlog最长容忍时间,如果距离上次写完的时间已经超过此间隔时间,超过此时间限制,就会触发ActiveNameNode进行一个rollEditLog操作,此时间可以通过
dfs.ha.log-roll.period配置,默认120s,滚动写editlog
sleepTimeMs:StandbyNameNode同步editlog的周期时间,默认60s,可以通过dfs.ha.tail-edits.period设置
三 QJM机制背景介绍
我们知道HDFS NameNode宕机恢复到以前状态,需要通过读取FSImage文件,就能还原。SecondaryNameNode负责合并editlog到FSImage文件。但是这样的单节点会有单点问题,不能保证NameNode
高可用。如果需要高可用,我们需要配置HA。HA状态下,我们并不能只把日志文件保存到一个节点,如果这个机器宕机,那么备份节点,是没有办法获取到和之前Active节点相同的元数据,所以可能导致数据不一致。
所以QJM应运而生,核心思想就是用2N+1台机器写editlig,只要有N个以上的机器写操作成功就是认为该次写成功。如果少于N台就认为失败
四 读写日志的机制分析
NameNode启动之后,会根据HA的状态判断是active还是standby状态。如果是Active状态,调用FSNamesystem的startActiveServices
否则调用StartStandbyServices.
4.1Active NameNode写日志
调用FSNamesystem.startActiveServices:
4.1.1获取FSEditlog,判断editlog是否处于打开写状态,如果没有则初始化Journal。
4.1.2设置editlog下一个事务id
4.1.3开始写editlog: 首先获取所有的JN 的 editlog输出流,然后开始将segment写到日志;最后刷新并异步向其他JouranlNode写日志。ActiveNameNode会标记返回失败的JN,下一次日志不再写该节点,直到下一次调用滚动日志操作,如果此时JN节点恢复正常,才开始写日志,虽然该节点丢失部分日志,但是主节点写了多分。
4.2Standby NameNode读取editlog并更新fsimage文件
调用FSNamesystem.startStandbyServices:
4.2.1检查editlog是否可以打开读,如果不行,则需要初始化共享存储目录,然后读取
4.2.2创建EditlogTailer对象,调用其run方法,开始读取editlog并更新fsimage文件。流程如下:
首先:检查Active NameNode日志滚动是否到期,如果到期,触发日志滚动,标记为Finalized状态,然后打开一个新的segment用于记录editlog
然后:开始做StandbyNamenode的taileditlog操作:获取FSImage,获取editlog输出流;然后加载editlog