(1) 第一阶段:NameNode启动
a) 第一次启动NameNode格式化后,创建fsimage和edits文件。如果不是第一次启动,直接加载编辑日志(位于磁盘上,存储的是生成元数据的步骤,执行后会生成元数据)和镜像文件(位于磁盘上,存储的是文件的元数据)到内存。
b) 客户端向namenode发出对元数据进行增删改的请求。Namenode在接收这些请求的时候,并不是直接写到内存里面,因为写到内存的话,断电会丢失,因此将这些请求分为一个个小步骤写入到位于磁盘上的编辑日志,这样即使断电,也能从磁盘中恢复出这些数据。
c) NameNode将存储完成的编辑日志执行一遍形成元数据写入到内存,如果edits.inprogress中的编辑日志满了(100万条数据),则会按照编号将其重命名,并创建新的edits.inprogress文件接收新请求,即滚动编辑日志。
d) NameNode在内存中对数据进行增删改查。
(2) 第二阶段:Secondary NameNode工作
a) Secondary NameNode询问NameNode是否需要checkpoint。直接带回NameNode是否检查结果。
b) Secondary NameNode请求执行checkpoint。
c) NameNode滚动正在写的edits日志。
d) 将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode。
e) Secondary NameNode加载编辑日志和镜像文件到内存,并合并。
f) 生成新的镜像文件fsimage.chkpoint。
g) 拷贝fsimage.chkpoint到NameNode。
h) NameNode将fsimage.chkpoint重新命名成fsimage。
NN和2NN工作机制详解:
fsimage:namenode内存中元数据序列化后形成的文件。
edits:记录客户端更新元数据信息的每一步操作(可通过edits运算出元数据)。
namenode启动时,先滚动edits并生成一个空的edits.inprogress,然后加载edits(归档后的)和fsimage(最新的)到内存中,此时namenode内存就持有最新的元数据信息。client开始对namenode发送元数据的增删改查的请求,这些请求的操作首先会被记录在edits.inprogress中(查询元数据的操作不会被记录在edits中,因为查询操作不会更改元数据信息),如果此时namenode挂掉,重启后会从edits中读取数据的操作信息。然后,namenode会在内存中执行edits文件中记载的增删改查的操作御用恢复元数据。
由于edits中记录的操作会越来越多,edits文件会越来越大,导致namenode在启动加载edits时会很慢,所以需要对edits和fsimage进行合并(所谓合并,就是将edits和fsimage加载到内存中,照着edits中的操作一步步执行,最终形成新的fsimage)。Secondarynamenode:帮助namenode进行edits和fsimage的合并工作。
secondarynamenode首先会询问namenode是否需要checkpoint(触发checkpoint需要满足两个条件中的任意一个,定时时间到(1个小时)和edits中数据写满了(100万条数据,这个每隔一分钟就会检查一次))。直接带回namenode是否检查结果。secondarynamenode执行checkpoint操作,首先会让namenode滚动edits并生成一个空的edits.inprogress,滚动edits的目的是给edits打个标记,以后所有新的操作都写入edits.inprogress,其他未合并的edits和fsimage会拷贝到secondarynamenode的本地,然后将拷贝的edits和fsimage加载到内存中进行合并,生成fsimage.chkpoint,然后将fsimage.chkpoint拷贝给namenode,重命名为fsimage后替换掉原来的fsimage。namenode在启动时就只需要加载之前未合并的edits和fsimage即可,因为合并过的edits中的元数据信息已经被记录在fsimage中。