IT智囊 2020-02-20
该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览
首先,我们要提出HDFS存储特点:
1.高容错
2.一个文件被切成块(新版本默认128MB一个块)在不同的DataNode存储
3.客户端通过流水线,在NameNode的调节下,将数据以Packet的形式流式地输送到流水线上
如果不清楚NameNode,DataNode等概念请先阅读HDFS架构文档: Hadoop架构中文文档
为了确保上述这些特点,HDFS对块的状态进行了定义,以控制数据块在传输过程中的有效性。
在NameNode看来,块(Block)主要有以下4种状态。
1.UNDER_CONSTRUCTION
2.UNDER_RECOVERY
3.COMMITED
4.COMPLETED
在DataNode看来,块(Block)应该称为“备份 (Replica)”比较合适,在DataNode种,备份主要有以下几种状态
1.RBW (Replica Begin Written)
2.RWR (Replica Waiting To Be Recovered)
3.RUR (Replica Under Recovery)
4.FINALIZED
5.TEMP
前三个比较好记,都是以Replica开头,而且只有DataNode中的块被称为Replica(备份)
我们还需要介绍一下两个比较重要的概念BGS,GS。有了这两个概念才能展开讲。
1.GS ( Generation Stamp ) : 这是被NameNode维护的一个类似版本标签的全局唯一标识,他是一个8字节的整数,当一个NameNode格式化文件系统的时候,这个标识被初始化为1
以下的事件能够让GS+1
1.当客户端请求NameNode创建一个新的文件
2.当客户端请求NameNode打开一个文件来以便向里面追加(append)内容或者删减内容(truncate)
3.当客户端在流水线工作过程中失败,需要恢复流水线,客户端回向NameNode讨要一个新的GS
4.NameNode以客户端的名义续租(Lease Recovery) 详见 : Hadoop架构: 关于Recovery (Lease Recovery , Block Recovery, PipeLine Recovery)
GS + 1后将被写入到NameNode的日志记录里。
2.BGS (Block Generation Stamp) :其实是没有这个概念的,但是为了区分GS,提出来了。BGS用来标记一个Block(以及他的Replica)的版本。以区分Replica是否过期
【在NameNode中数据块被称作Block,在DataNode中数据块是Block的备份,被称为Replica】的版本。
一.BGS在文件创建或者append时的处理。
1新建. 当客户端向NameNode申请创建文件或者打开文件进行追加的时候,往往都需要一个新的Block,NameNode会为这个Block打上一个新的BGS。新BGS产生方式很简单,NameNode将现在的GS + 1就得到了新的BGS(NameNode同时要把 + 1后的GS写到日志里)。一个块的创建不仅要新的BGS,而且还需要新的BlockId来表示这个Block,并且NameNode需要给出Block的Replica能放在哪些DataNode上,也就是Block的Locations。(Locations不会被写入日志,而是在NameNode启动后接收DataNode的报告来获取)。
2获取. 客户端将得到的新BGS和BlockId发布到流水线中,让DataNode获取,DataNode获取到新的BlockId和BGS。如果客户端的意图是创建文件的话,会新建一个块文件,如果是追加的话,会打开一个块文件,最后的结果都是把新的BGS和BlockId写入DataNode的MetaFile(存储文件元数据的文件,元数据比如BGS,BlockId)。
3回复.如果第2步没有错误,客户端将通知NameNode,新建一个OpenFile事务,并且写入日志。该事务包含当前正在写入文件的完整路径信息,以及每一个块的BlockId和BGS。
二.在写入时新建Block时
1.当在对一个块进行写入,如果客户端要求NameNode创建一个新的Block,NameNode会创建新的Block并且新建StoreGS事务和OpenFile事务,并且写入日志。前者记录新产生的GS(每个Block被新建都要让NameNode的GenerationStamp + 1),后者记录文件所有Block的BGS和BlockId。
2.客户端将从NameNode那里获得的新Block的相关信息发布到流水线上,和一中的2差不多
简单地理解,GS是整个文件系统的版本号,BGS是块的版本号。
当某些退出DataNode集群很久的节点加入时,根据GS可以识别出他们是否是旧的节点。
BGS用来识别一个块是否过期。只有未过期的块才会被进行特定操作,下文会提及。
聪明的你可能已经发现,上述状态中出现了一个难以理解的词 “Recovery”
这个词在客户端记录DataStreamer运作状态的枚举类BlockConstructionStage中也有出现
我们先聊一聊什么是 “Recovery”。详见 Hadoop架构: 关于Recovery (Lease Recovery , Block Recovery, PipeLine Recovery)
如果你对Recovery有了大体理解,我们就可以来谈谈这些复杂的状态之间是怎么转换的了。
首先是在NameNode中
1.当客户端Writer申请新建一个块,NameNode就会在本地新建一个块,这个block的状态是UNDER_CONSTRUCTION
2.当NameNode为某个文件进行租约恢复(Lease Recovery),该文件的最后一个块的状态转为UNDER_RECOVERY
3.当客户端在写文件的时候向NameNode申请一个新的Block(上一个Block写满了或者以不明原因endBlock),或者请求关闭文件,NameNode会把上一个Block的状态设置为Commited,如果没有最小备份数(可以在配置里自行设置)的DataNode向NameNode汇报自己收到了和NameNode中Block同BGS的Finalized态Replica,那么Commited状态会保持下去。
4.当有最小备份数的DataNode向NameNode汇报,自己已经有关于这个块的FINALIZED态Replica,并且BGS和NameNode的Block的BSG一样。那么NameNode就会把自己的Block设置成COMPLETE态。
注:客户端写完一个块,或者客户端关闭某个文件,都会告知流水线上的DataNode,DataNode们收到了前述信息(关闭或者写完),认为这个块将被结束操作,会试图把自己的Replica设置成FINALIZED态,并且向NameNode汇报。
其次是在DataNode中
1.当一个备份(块的备份)被写入数据的时候,被设置成RBW(Replica Being Writen),一个块被创建,意味着要被写入,所以处于RBW态。
当客户端打开某个现有的文件打算追加(append)或者删减(truncate),一般是最末尾的Replica被设置成RBW,因为一般是在文件末尾追加或者删减。
RBW状态的块对Reader客户端是可见的
2.RWR(Replica Waitting To Be Recovery),等待恢复的块,当一个DataNode在流水线传输过程中宕机,那么当他重启后,所有的之前在流水线中正在被写的RBW态Replica都会转换成RWR态
RWR态的Replica是不会再加入流水线了的,但是如果DataNode和写客户端Writer一同宕机,NameNode在租约恢复(Lease Recovery)时,会让领袖DataNode对这些Replica进行操作。当租
约恢复,这些RWR状态将成为FINALIZED。
3.RUR(Replica Under Recovery) 正在恢复的备份,租约恢复文件的当前备份中,可能有RBW(正在被写入的备份)的,RWR(需要被恢复,DataNode宕机重启导致RBW -> RWR)的,FINALIZED(流水线关闭阶段会通知DataNode将Replica设置成FINALIZED)的,在租约恢复执行阶段会被设置成RUR态。(在Hadoop架构: 关于Recovery (Lease Recovery , Block Recovery, PipeLine Recovery) 中有详细讲解)
4.FINALIZED,当客户端Writer在一个Block写满后,将会通知流水线上的DataNode将对于Replica设置成FINALIZED态,尔后关闭流水线
5.TEMP 这个状态是用来暂存Replica的,某个Block的最小备份数是3,原本有3台DataNode存有Replica,但是其中一台宕机了,那么NameNode需要把备份复制到新的一台DataNode A上,于是在A
那创建了一个TEMP状态的Replica来将数据复制进去,如果复制成功那么又恢复到3个Replica了。如果A宕机,那么下次重启的时候,这个TEMP的Replica将被删除。