当前位置: 首页 > 图灵资讯 > 技术篇> HDFS使用QJM实现高可用(二)

HDFS使用QJM实现高可用(二)

来源:图灵教育
时间:2023-06-08 09:26:50

QJM的基本原理是用2N+1个JournalNode存储Editlog,每次写数据操作都有大部分(>=N+1)当返回成功时,我认为写作成功,数据不会丢失。当然,该算法最多可以容忍N台机器。如果超过N台机器,该算法将无效。

第二部分

2.1.写日志机制

编写操作由主节点完成。当主节点调用flush操作时,RPC将被调用到N个JN服务中,并异步编写日志。如果有N/2+1个节点返回成功,则此编写操作将成功。

主节点将标记返回失败的JN节点。在下次调用滚动日志之前,将不再编写该节点。如果JN节点恢复正常,主节点将在主节点后编写日志。虽然节点丢失了一些日志,但由于主节点写了多个日志,相应的日志并没有丢失。

为了保证每个日志文件txid的连续性,主节点确保分配的txid是连续的。同时,当JN节点接受编写日志时,将首先检查txid是否与上次连续编写。如果不连续,将向主节点报告错误,并连续编写日志文件。

2.2阅读日志机制

1、选择日志文件,建立输入流

所有未消化的日志文件从节点遍历,未处理的文件将被删除。对于每个JN节点上的日志文件,根据txid从小到大排序放入集合。这样的集合对应于从节点端的每个JN节点。然后将每个JN节点之间相同的日志文件分为一组(组内日志将检查fisrttxid是否相等,lasttxid是否相等);每组之间按txid从小到大进行排序,方便从节点按txid顺序消化日志;同时判断每组之间的txid是否连续。

2、消化日志

输入流准备好后,开始消化日志,按照txid的顺序从每个日志组从节点消化日志。在每个日志组中,首先检查txid是否正确。如果是正确的,首先从节点消化第一个日志文件,如果第一个日志文件消化失败,则消化第二个日志文件,以此类推。如果日志组中的文件在经历后没有找到所需的日志,则日志消化失败,如果消化每个日志的最后一个txid等于日志文件的lasttxid,日志文件消化结束。

处理如下图所示:

2.3.日志恢复

最近的日志段状态将在从节点切换到主节点的过程中进行检查。如果不转换为finalized状态,则将其转换为该状态,日志恢复正在进行中。

2.3.1.触发条件

QJM将检查最新日志文件的数据一致性,然后决定是否触发数据修复过程。

HDFS之前的日志文件将确保它已经从inprocess状态转变为finalized状态,因此只有最新的日志文件是新的,可能需要恢复此处理。

2.3.2.恢复流程

2.3.2.1.准备恢复preparecover

操作将RPC请求发送到JN端,查询需要恢复的日志段文件是否存在。如果存在,则判断日志段文件的状态(inprocess或finalized),还将返回epoch号,namenode根据返回的查询信息通过修复算法选择修复的源节点,准备数据修复。

修复策略:

1、首先,判断JN节点是否有指定的txid。如果没有节点,节点将不作为源节点;

2、如果JN节点中有指定的txid,则判断该文件是否处于finalized状态。如果不同的JN节点,txid所在的文件包括finalized状态文件和inprocess状态文件,则以finalized状态文件为候选源节点,当然,在finalized状态的文件之间,需要判断txid是否相等,然后返回任何节点作为源节点

如果节点间文件是inprocess状态的文件,则首先判断其epoch编号。如果epoch编号不一致,则以epoch编号较大的epoch作为候选源节点;如果epoch编号一致,则选择结束txid作为源节点。)

2.3.2.2.acceptrecovery接受恢复

计算源节点后,Namenode将恢复操作发送到JN端。JN节点根据收到的RPC恢复请求,判断当前节点是否需要日志修复。如果需要修复,则通过doget将需要恢复的目标日志文件下载到源节点。在下载过程中,首先将下载的文件放入临时目录(tmp)在目录下,下载完成后进行md5验证,检查是否有数据丢失,然后将下载的文件放入工作目录(current)这样,数据恢复就完成了。

在JN节点的实施中,有两个问题需要考虑:

您可以考虑返回URL数组,而不是单个URL,这样一个URL不能连接,也可以尝试连接其他JN节点下载文件;

2、在JN节点下载日志文件时,有可能挂掉自己的过程,在QJM中,有办法处理这个问题;

当我第一次接触时,我担心是否可能有文件从节点读取,恢复日志文件。经过分析,我发现不会发生任何情况,因为从节点消化的日志是finalized状态的文件,而不是inprocess状态的文件。