[DFS #0] HDFS论文解读

[DFS #0] HDFS论文解读

参考论文: The Hadoop Distributed File System

分布式文件系统HDFS作为HBase的下层服务,以及众多存储服务的支持项目,已经被广泛使用,下面通过解读上述论文来记录并介绍一下HDFS的架构,以及功能,还有设计

整体架构 Overview

如图所示

 

document_2016-12-17_23-04-40-1

 

每一个HDFS集群由一个NameNode,多个DataNode,以及BackupNode, CheckpointNode组成,上图中的三角形为使用HDFS的客户端,客户端和DataNode之间的线表示客户端到DataNode的物理距离,对于这个架构,有下面几点要说的

  • 一个集群的NameNode只有一个,客户端想要使用这个HDFS的时候,一定是先和NameNode进行交流,获得需要的DataNode信息之后,才能和DataNode进行通信
  • 因为NameNode只有一个,所以NameNode如果出现单点故障可就不好玩惹,而且对于存储这种要求数据一致性很高的系统,也不能容忍NameNode出故障系统就瘫痪这种情况,因而使用CheckpointNode和BackupNode对NameNode进行备份,他们的区别和备份方式下文会详细说
  • NameNode不会主动去和DataNode通信,他们之间的通信是这样的: DataNode每隔一定时间发送heartbeat到NameNode(默认3s)(通知NameNode他还活着可以干活=w=(划掉 ,然后NameNode在这个时候会将要发送到DataNode的指令通过Response的形式发送到DataNode
  • Client对数据的操作精简来看,无非是读写两种,当Client想要读取HDFS的数据的时候,首先Client先去询问NameNode,哪些DataNode有他要的数据,并且选择距离他最近的DataNode,然后Client直接连接距离最近的DataNode并获取数据 e.g: 如上图的ClientA想要获取一个数据,且数据在DataNode A B C内都有存放,那么ClientA首先要和NameNode进行通信,获得DataNode列表(ordered by distance to the client)然后选择距离它最近的DataNode B进行通信获取数据
  • 当Client想要向一个文件写入数据的时候(无论文件存不存在),其他的Client会无法对此文件进行写入操作(以此来保证文件不会因为同时写而corrupt data)写入完毕之后,会将Block进行Replica复制到不同的DataNode上(默认为复制3份),具体会在下面介绍

 

模块 & 术语

NameNode

HDFS Namespace ,是存储着所有DataNode以及每一个DataNode上的文件的元信息的一个目录结构,NameNode通过inode的方式来表示每一个文件和文件夹。Namespace 就可以理解为Linux的目录树的inode list,每一个inode指向一个datablock,datablock存在datanode上 HDFS将整个Namespace放在RAM内,完整的文件系统信息(包含inode信息,以及每一个inode对应的Datablock list 元信息)称为Image, Image持久存储在NameNode本地存储里,称为一个Checkpoint, NameNode同时维护了数据操作的日志journal

DataNode

显然,这就是数据真正存放的地方,每一个Datablock由两个文件组成,该Block的数据,和该Block的[checksum,创建时间]信息组成的元数据

如下图

document_2016-12-18_01-35-54

一个占3个Block的文件存放在DataNode里的情况简图,该文件有三个block,每一个block的信息含有Data & MetaData,三个Block组成了整个文件file1, 然后在NameNode的某一个inode存储着信息对应着文件名file1,block数3,物理位置在该DataNode上

DataNode的Startup

 

  • 当DataNode Startup时,会和NameNode进行handshake,进行namespaceID(每一个HDFS都有一个唯一的NamespaceID,在创建HDFS的时候就确定了)&version的认证,二者必须均与NameNode完全一致,如果不一致的话,该DataNode就会停止工作。保证了不会因为错误的NameNode或者软件版本不兼容而导致数据出问题,
  • 如果这个DataNode没有保存任何Namespace信息,说明这是一个新的DataNode,没有任何Block数据,因而允许加入此HDFS cluster。
  • 当DataNode握手成功之后,会register自己到该NameNode,如果为第一次加入该NameNode,则会被NameNode分配一个唯一的StorageID,并且永远不会改变,DataNode会将此ID持久存在自己的storage中,这个StorageID保证了就算IP变动或者端口变动,NameNode仍然可以识别该DataNode的身份

DataNode与NameNode的通信

  • Block Report: Block Report是DataNode用于通知NameNode自己所持有的Block的信息(如blockid,block大小,generation stamp)的一种数据,因为这个数据是会随时改变的,所以需要定期发送Block Report给NameNode,使得NameNode能得到整个Block分布的信息。当DataNode注册到NameNode时,会立即发送一个Block Report,之后会每隔一段时间(1h)发送一次BlockReport
  • HeartBeat:  DataNode通过定期的心跳与NameNode进行通信,使NameNode确认DataNode存活,并且同时carry其他信息,如存储可用量,目前正在传输的数据量等信息,用于NameNode进行负载均衡。 NameNode则在收到DataNode心跳,对DataNode进行Response的时候进行通信,可以发送的指令有:
    • 将自己持有的数据块复制到其他DataNode
    • 移除该DataNode上的数据块
    • 重新注册、或者停止该DataNode
    • 使DataNode立即发送一个Block Report

Block Scanner

  • 每一个DataNode都有一个BlockScanner,周期性地对Block的完整性进行认证
  • 当Block Corrupt的时候,Scanner会通知NameNode该Block Corrupt了
  • Verification Time存储在日志内,对Block的扫描顺序是按照VerificationTime早的先扫描进行排序的(待定)

HDFS Client

Client的作用就是用来Access HDFS的文件信息的,功能即为文件系统的基本操作

  • 读: 如上文所说,读距离Client最近的DataNode
  • 写: 通过流水线,写入三个DataNode

Image & Journal

  • NameNode上的全部元数据信息称作该NameNode的一个Image,Image的本地备份称作Checkpoint
  • Journal的写入方式是write ahead即在进行相应操作前,先写日志,保证数据强一致,对于每一个操作,首先进行记录,然后将日志flush & sync到磁盘,之后才会进行相应的操作
  • NameNode不会改变Checkpoint文件,每一次Checkpoint改变的时候,都是完整的重写,将原本的Checkpoint替换掉
  • Checkpoint的生成是在系统重启的时候,或者Admin手动操作,或者CheckpointNode自行生成
  • 因为flush & sync操作的耗时,该操作成为性能瓶颈,优化的方法是: 将所有的操作作为一批任务保存下来,当某一个thread触发了flush的时候,将全部thread的操作进行flush&sync(这样会不会不能保证数据的持久性?)
  • =A=因为Journal/Image丢了一个都会对存储造成影响,所以,将这些数据备份多份是一个好的选择,最好还要再NFS上备份一个

CheckpointNode & BackupNode

CheckpointNode

  • CheckpointNode就是一个对NameNode的快照,定期对NameNode的journal和checkpoint进行备份,并且将journal应用在Image上之后,清空journal,然后将新的Checkpoint发送给NameNode
  • CheckpointNode清理journal使得不会出现巨大的journal,巨大的journal文件出现corrupt的可能性较大,论文作者建议我们每天创建一个Checkpoint

BackupNode

  • BackupNode也会创建Checkpoint,具有和Checkpoint一样的功能,在此之上,BackupNode还可以实时的将NameNode Image同步到自己的内存中,保证了实时的同步性
  • 实现方式:BackupNode可以读取到NameNode的实时日志流,将日志存到本地,并且将日志里的每一个操作在自己的Image上进行操作
  • 当BackupNode创建Checkpoint的时候,不需要从NameNode下载Image和Journal,它本身就已经是和NameNode同步的了,只需要将Image存到本地,效率比CheckpointNode高很多
  • BackupNode可以看做是一个ReadOnly NameNode

Comparation

  • BackupNode具有CheckpointNode的全部功能
  • BackupNode还具有实时快照NameNode的功能,可以使Checkpoint的创建效率提升

Upgrade & File System SnapShots

系统升级的时候,数据丢失问题出现的可能性会增加,为了减小在升级的时候对数据损伤的可能性,HDFS引入了File System Snapshot,即一个全局的,唯一的,能够描述整个HDFScluster的所有信息的Snapshot

  • Snapshot在系统启动的时候Admin可以决定是否创建
  • 当选择创建Snapshot的时候,在NameNode启动时会对目前的NameNode Image生成Checkpoint,这个Checkpoint不会覆盖掉旧的Checkpoint,会存在另一个位置
  • 在DataNode与NameNode进行handshake的时候,NameNode通知DataNode,创建一个Snapshot,DataNode很显然不能复制每一个数据的内容一个副本,备份使用的方式是创建到每一个block的hardlink,当对数据进行修改时,使用COW,将被修改的数据生成一个新的副本,这样可以保证原来的所有block不会被修改
  • Rollback: 在系统重启的时候,Admin可以选择回滚到上一个Snapshot

功能及实现

文件读写

HDFS的Datablock在写入并关闭(Close the file)掉后不可以进行修改,除非这个修改是可以通过对原文件进行append就可以完成的, HDFS实现的为多读单写模型

  • 当客户端发起对数据的读的请求时,之前已经介绍了会找到最近的持有数据的Datanode进行读操作如果该操作失败,client会去读列表中的下一个Datanode
  • Checksum: 当Client读取一个Datablock时,会首先验证这个Datablock的Checksum是否和metadata吻合,如果不吻合,Client会通知DataNode当前读取的block corrupt了,并且去读取另一个DataNode上的该数据
  • 当读取一个正在被写入的文件时,Client首先询问最近的该文件的长度,然后再进行读取
  • Client读取一个正在被写入的文件时,被写入的那些修改HDFS不保证对Client可见

  • 当一个Client对文件进行写入的时候,该Client获得一个锁(lease),其他Client不能对此文件进行写入
  • 该锁有hardlimit和softlimit,正在写入的Client需要发送heartbeat到NameNode,未超过softlimimt时,该writer独占此文件的锁,超过softlimit之后,可以被其他client抢占此锁,超过hardlimit(即到了hardlimit writer也没有发送心跳也没有关闭文件,也没有人来抢占锁)HDFS认为client已经退出并且自动关闭文件,释放掉锁
  • 当写入需要分配新的Block的时候,NameNode会为该block分配一个新的blockID,并且决定哪几个DataNode会持有该Block的replica,这几个DataNode形成一个流水线(pipeline),然后Client通过向流水线写入数据,以TCPpacket的形式传递给每一个DataNode
  • Client发出一个packet不需要等待DataNode的ACK,可以继续发送packet,只要不超过packet窗口的大小即可
  • 正在被写入的数据HDFS不保证在Client读取的时候可以看到,不过可以通过hflush指令,将所有收到的Packet全部ACK响应之后,让数据对Client可见
  • 如下图,写入block数据的三个阶段
    • pipeline setup: Client将数据准备好,NameNode将要接受写入的NameNode准备好,并且建立pipeline
    • Data Streaming: Client传送packet到pipeline,DataNode对每一个packet发送ACK
    • close: 所有数据都已经发送完毕,ACK均接收到,关闭链接

pipeline

 

Replica管理

对于HDFS来说,每一个Block不能存储在所有的DataNode上一个副本,这样存储空间也十分有限,也造成了大量的不必要的重复和资源浪费,因而对Block的副本的管理就是很关键的一个问题,HDFS采用了如下的几个技术来对Replica进行管理

 

Block Placement

对于很大的集群,无法通过一个扁平的网络将其链接起来,而是将DataNode分布在多个rack里,一个rack里的所有Node使用一个交换机,rack与rack之间再通过交换机相连,构成树状结构。因而网络带宽在rack与rack之间和rack内部通信相比,通常是rack内的带宽更大。 HDFS给出的用于估计两个网络节点之间的带宽的方式是:将这两个节点到他们最近的公共祖先的距离加和

dn

如图,DN00 和 DN01之间的距离为2, DN00 和 DN12之间的距离为4

当DataNode注册到NameNode的时候,NameNode通过DataNode的IP以及设置好的脚本得出该DataNode在哪一个rack

Block replica的存放对于HDFS的数据的可靠性非常重要,默认的Replica placement policy是在cost和reliablility,以及bandiwidth 之间的一个tradeoff。具体的placement为:first replica on the node that client write to, second & third in a different rack , others randomly

Replication 管理

NameNode保证block的副本数是预期的数量,当过多or过少的时候,都会进行Replica Manage 通过多个策略对Block副本进行增加和删除,当Block过少的时候,会将该Block放入replica count越少优先级越高的优先队列里等待replicate,过多的时候则会根据一个策略在需要的时候对副本进行清理。

Balancer

HDFS的Block Placement策略没有考虑磁盘的利用情况,Block Placement策略的作用是防止数据集中分布在某几个DataNode上,却无法防止DataNode的磁盘利用不均匀的问题(可能出现一个DataNode有100GB数据,另一个却有1T数据)。Balancer就是为了解决此问题的工具

Balancer会对不均匀分布的数据进行移动,不过在移动的时候他也会保证满足Block Placement,即数据所分布的rack数不会减少,数据的replica不会减少,同时通过减少跨rack拷贝数据提高Balance效率

Balancer的带宽占用是可以config的,这样可以控制Balancer在不影响HDFS的正常运作的前提下移动数据

 

Decommission — DataNode退役

(即静默期)

  • 当一个DataNode被Admin标记为不能加入该集群(或者说退出该集群)时,该DataNode进入退役(Decommissioning)状态
  • 变为退役状态的DataNode不会再接收到Block Replica创建的请求,但是可以进行读取
  • NameNode会将该DataNode上的所有数据replicate到其他的DataNode上
  • 当Replicate结束时,这个节点进入到退役完毕(Decommissioned)状态,可以安全的移除

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

19 + 9 =