分布式存储—HDFS详解


### 分布式存储—HDFS详解 HDFS(Hadoop Distributed File System)是Hadoop项目的核心子项目,是分布式计算中数据存储管理的基础,是基于流数据模式访问和处理超大文件的需求而开发的,可以运行于廉价的商用服务器上。它所具有的高容错、高可靠性、高可扩展性、高获得性、高吞吐率等特征为海量数据提供了不怕故障的存储,为超大数据集(Large Data Set)的应用处理带来了很多便利
—————————————————————————————————————————
设计思想分而治之(安全性):将大文件、大批量文件,分布式的存放在大量服务器上
存储方式存放数据的单位是块。2.0以后,块的默认大小:128M

主从架构
1.client 客户端

  • 文件切分,文件上传HDFS的时候,client将文件切分成一个一个的block
  • 与NameNode交互,获取文件的位置信息
  • 与DataNode交互,读取或写入数据
  • Client提供一些命令来管理HDFS,比如启动或关闭HDFS
  • Client可以通过一些命令来访问HDFS
    2.NameNode就是master,是一个主管、管理者。管理HDFS的名词空间。主节点仅存放元数据信息(元数据:管理数据的数据,数据结构的描述。文件大小、位置、块索引)。配置副本策略,处理客户端读写请求,分配client去访问哪个从节点
    3.DataNode就是slave,从节点存放真实文件(实际文件)即实际的数据块,执行数据块的读写操作。namenode下达命令,datanode执行实际的操作。client客户端发起读取数据的请求,namenode接到请求后会通过元数据信息得到数据的位置,最后由datanode将数据最后输出给client客户端

架构内容1.数据块:默认128M,datanode通过数据块存储。存放在hadoopdata目录下2.心跳机制:主从节点间通过心跳机制确定互相之间的关系每3秒发送一次3.元数据管理4.负载均衡:存储数据时,由namenode进行分配存在位置5.副本存放策略:每个块都有两个副本6.机架感知:datanode机架感知互相联系

优点
1.高容错性:数据自动保存多个副本(默认有三个)当某一个副本丢失后,它可以自动恢复,这是HDFS的内部机制
2.适合处理超大文件可以批量处理,是通过移动计算而不是移动数据处理数据GB、TB设置PB级数据百万规模以上的文件数量

缺点
1.低延迟数据访问2.小文件存取3.并发写入、文件随机修改

相关特性

  1. 高容错、可扩展性及可配置性强
  2. 跨平台
  3. Shell命令接口
  4. 机架感知功能
  5. 负载均衡
  6. web界面
    设计目标
  7. 可以检测和快速回复硬件故障,故障的检测和快速自动恢复是HDFS的一个核心目标
  8. 流式数据访问
  9. 大规模数据集
  10. 移动计算代价比移动数据代价低
  11. 可移植性
    ————————————————————————————————————————————
    核心设计
    1.心跳机制2.安全模式3.副本存放策略4.负载均衡
    ——————————————————-数据块
    HDFS上最基本的存储单位,默认大小128M,小于一个块大小的文件不会占据整个块的空间,块非常适合用于数据备份进而提供数据容错能力和可用性。
    数据复制
    HDFS为了做到可靠性reliability创建了多分数据块data blocks的复制replicas,并将它们放置在服务器群的计算节点compute nodes中,MapResource就可以在它们所在的节点上处理这些数据了HDFS将每个文件存储成块序列每个文件的block大小和复制因子replication都是可配置的
    ————————————————————————
    心跳机制
    1.master中有NameNode和ResourceManager ,slave中有DataNode和NodeManager
  • Master启动时会启动一个IPC Server服务,等待slave的连接;
  • Slave启动时,会自动连接Master的IPC Server 服务,并且每隔3秒链接一次Master,这个间隔时间是可以调整的,参数为 dfs.heartbeat.interval,这个每隔一段时间去链接一次的机制,我们形象的成为心跳机制。
  • Slave 通过心跳汇报自己的信息给Master ,Master也通过心跳给Slave下达命令
    2.NameNode 通过心跳得知DataNode的状态,ResourceManager通过心跳得知NodeManager的状态; 如果Master长时间没有收到Slave的心跳。就认为该Slave挂掉了。
    3.死亡时间计算;NameNode 感知 DataNode掉线死亡的时长计算:HDFS 默认的超时时间为10分钟+30秒,这里暂且定义超时时间为timeout计算公式为:
    timeout = 2 heartbeat.recheck.interval + 10 dfs.heartbeat.interval
  • 默认的 heartbeat.recheck.interval 大小为 5 分钟,dfs.heartbeat.interval 默认的大小为 3 秒。需 要 注 意 的 是 hdfs-site.xml 配 置 文 件 中 的 heartbeat.recheck.interval 的 单位 为 毫 秒,dfs.heartbeat.interval 的单位为秒。
  • 如果 heartbeat.recheck.interval 设置为 5000(毫秒), dfs.heartbeat.interval设置为 3(秒,默认),则总的超时时间为 40 秒。
    heartbeat.recheck.interval 5000 dfs.heartbeat.interval 3

安全模式
集群启动后,可以查看目录,但是上传文件时报错,打开web页面可看到namenode正处于safemode状态。1.safemode 是 NameNode 的一种状态(active/standby/safemode 安全模式)
2.NameNode 进入安全模式的原理:
NameNode 发现集群中的 block 丢失率达到一定比例时(0.1%), NameNode 就会进入安全模式,在安全模式下,不允许客户端进行任何修改文件的操作,包括上传文件、删除文件、重命名等操作,只能查看元数据信息(比如 ls)。这个丢失率是可以手动配置的,默认是在配置文件hdfs-default.xml 中定义了最小的副本率为dfs.safemode.threshold.pct=0.999f 。
3.进入安全模式的原因:块的丢失;增加新节点时;刚启动时文件还没有加载完成
4.能做的:等待
5.如何退出安全模式?

  • 找到问题所在进行修复
    1. 比如修复宕机的datanode
  • 手动强行退出安全模式
         (没有解决真正的问题)<br />hdfs dfsadmin -safemode leave
    

在 HDFS 集群正常冷启动时, NameNode 也会在 safemode 状态下维持相当长的一段时间,此时你不需要去理会,等待它自动退出安全模式即可 。在刚运行命令start-dfs.sh时,50070页面显示的信息:分布式存储--HDFS详解 - 图13.安全模式常用的操作命令hdfs dfsadmin -safemode leave //强制 NameNode 退出安全模式hdfs dfsadmin -safemode enter //进入安全模式hdfs dfsadmin -safemode get //查看安全模式状态hdfs dfsadmin -safemode wait //等待,一直到安全模式结束

副本存放策略

  • 作用:数据分块存储和副本的存放,是保证可靠性和高性能的关键
  • 存放说明:在大多数情况下,HDFS默认的副本系数是3
  • 存放策略: 将每个文件的数据进行分块存储,每一个数据块又保存有多个副本,这些数据块副本分布在不同的机器节点Hadoop默认对3个副本的存放策略
    1)第一个block副本放在和client所在的node里(如果client不在集群范围内,则这第一个node是随机选取的,系统会尝试不选择哪些太满或者太忙的node)2)第二个副本放置在第一个节点相同的机架中的不同node中(随机选择)3)第三个副本和第一个在不同机架中,随机放在不同的node中4)更多副本随机节点存放
    (1.客户端的node里 2.和第一个节点相同机架不同的随机node中 3.和第一个节点不同机架的随机node中)

分布式存储--HDFS详解 - 图2

  • 修改副本数(将副本数修改为1) 第一种方式修改集群文件 hdfs-site.xml //修改项开始 dfs.replication 1 //修改项结束

第二种方式命令设置hadoop fs -setrep -R 1 /

负载均衡
1.数据不平衡原因机器与机器之间磁盘利用率不平衡,HDFS集群非常容易出现情况情况一;在DataNode 节点出现故障情况二;在现有的集群上增添新的DataNode 的时候
2.HDFS数据自动平衡方法影响Balancer的几个参数:

  • threshold
        默认设置:10,参数取值范围:0-100          参数含义:判断集群是否平衡的阈值。理论上,该参数设置的越小,集群就越平衡。
    
  • dfs.balance.bandwidthPerSec
       默认设置:1048576(1M/s)         参数含义;Balancer运行时允许占用的带宽<br />命令:<br />启动数据均衡,默认阈值10%sbin/start-balancer.sh<br />启动数据均衡,阈值5%sbin/start-balancer.sh –threshold 5<br /> 停止数据均衡sbin/stop-balancer.sh  <br />自动进行均衡非常慢,一天能够移动的数据量在10G-10T的级别,很难满足超大集群的需求。原因:HDFS集群默认不允许blance操作占用很大的网络带宽,这个带宽是可以调整的。<br />调整带宽:<br />(1)命令hdfs dfsadmin -setBalanacerBandwidth 10485760<br />该数值的单位是字节,上面的配置是10 M/秒,默认是1M/s<br />(2)在hdfs-site.xml中设置:<property>       <name>dfs.balance.bandwidthPerSec</name><value>10485760</value></property>
    

————————————————————————————————————————————————————— HDFS工作机制
—————————————-
1.HDFS写数据
1.客户端根据文件的大小,为它分配需要的block数,然后向NN发出写的请求,看看文件是否存在,如果不存在就创建-客户端通过调用 DistributedFileSystem 的create方法,创建一个新的文件。-DistributedFileSystem 通过 RPC(远程过程调用)调用 NameNode,去创建一个没有blocks关联的新文件。创建前,NameNode 会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过,NameNode 就会记录下新文件,否则就会抛出IO异常
2.NN为文件分配每个块写的位置,然后向client返回文件list,即元数据信息给client-第一步结束后会返回 FSDataOutputStream 的对象,和读文件的时候相似,FSDataOutputStream 被封装成 DFSOutputStream,DFSOutputStream 可以协调 NameNode和 DataNode。客户端开始写数据到DFSOutputStream,DFSOutputStream会把数据切成一个个小packet,然后排成队列 data queue。
3.client根据文件list在相应的DN上写,每写完一个DN都向client返回一个ack信息。DFSOutputStream 还有一个队列叫 ack queue,也是由 packet 组成,等待DataNode的收到响应,当pipeline中的所有DataNode都表示已经收到的时候,这时akc queue才会把对应的packet包移除掉。-如果有DN坏了,NN会重新分配,client再重新写
4.客户端写完最后一块后,client关闭数据流-客户端完成写数据后,调用close方法关闭写入流。-DataStreamer 把剩余的包都刷到 pipeline 里,然后等待 ack 信息,收到最后一个 ack 后,通知 DataNode 把文件标示为已完成。
5.当第一块block完成时,它所在的那个节点的后台会启动一个进程进行复制,分别把副本写到其它DN上(管道复制)-DataStreamer 会去处理接受 data queue,它先问询 NameNode 这个新的 block 最适合存储的在哪几个DataNode里,比如重复数是3,那么就找到3个最适合的 DataNode,把它们排成一个 pipeline。DataStreamer 把 packet 按队列输出到管道的第一个 DataNode 中,第一个 DataNode又把 packet 输出到第二个 DataNode 中,以此类推。比如要写一个文件a.txt,300M,那么它会占用3个块,默认保存3个副本
分布式存储--HDFS详解 - 图3

  • 步骤 1)Client向NameNode发起RPC请求2) NameNode检查创建的文件是否存在3) 数据队列(data queue)管理packet并向NN申请blocks,4) 以pipeline将packet写入所有的replicas中。以流的方式写入第一个DN,再传递给下一个DN,直到最后一个DN5) 最后一个DN成功存储之后会返回一个ack packet,成功收到DN返回的 ack packet 后会移除packet;某个DN出现了故障,pipeline会被关闭,出现故障的DN会移除,剩余的block会继续传输,同时NN会分配一个新的DN,保持设定的数量。6)完成写入后,关闭数据流7)告知NN,写数据完成
    步骤简述:(客户端根据文件大小,分配需要的块数,然后向NN发送写请求,NN为文件分配写的地址,并返回文件列表信息,客户端根据文件列表信息在相应的DN上写,每写完一个DN都会向客户端返回一个ack信息,当第一个块写完后,所在节点会启动一个进程进行复制,分别把副本写到其他管道上,客户端写完最后一个块,关闭数据流。告知NN,写数据完成)

2.HDFS读数据
1.客户端向NN发出请求,与NN发生交互调用FileSystem对象的open方法,其实获取的是一个DistributedFileSystem的实例
2.NN把文件的列表信息发送给client,列表信息即文件的位置索引DistributedFileSystem通过RPC(远程过程调用)获得文件的第一批block的locations,同一block按照重复数会返回多个locations,这些locations按照hadoop拓扑结构排序,距离客户端近的排在前面
3.client根据列表信息去DN上读取block块信息(客户端会找离它比较近的去读,就近原则)前两步会返回一个FSDataInputStream对象,该对象会被封装成 DFSInputStream对象,DFSInputStream可以方便的管理datanode和namenode数据流。客户端调用read方法,DFSInputStream就会找出离客户端最近的datanode并连接datanode数据从datanode源源不断的流向客户端
4.一直读,直到所有块读完如果第一个block块的数据读完了,就会关闭指向第一个block块的datanode连接,接着读取下一个block块如果只有第一行有信息,也会把整个块读完
5.关闭读操作如果第一批block都读完了,DFSInputStream就会去namenode拿下一批blocks的location,然后继续读,如果所有的block块都读完,这时就会关闭掉所有的流
比如要读一个文件a.txt,300M,那么它会占用3个块,默认保存3个副本,所以存在三个DN上
分布式存储--HDFS详解 - 图4

  • 步骤 1)Client向NameNode发起RPC请求2)NN返回有block拷贝的DN地址3)Client 会选取DN读取block(就近原则)4)读取完当前block的数据后,关闭当前的DN链接,寻找下一个最佳的DN5)当读完列表后,且没有结束,会继续向NN获取下一批block列表6)读取完一个block都会进行checksum验证,如都没有错误,则关闭资源
    步骤简述:(客户端向NN发送读请求,与NN发生交互,NN把文件的列表信息发送给客户端,客户端根据列表信息去DN上读取block块信息[就近原则],并进行验证,一直读,直到第一批所有的块读完,DFSInputStream就会去namenode拿下一批block的location,然后继续读,如果所有的block块都读完,这时就会关闭所有的流 ,即关闭读操作)

——————————————————————————————————————————-
NameNode工作机制
——————————————
1.NameDode对数据的管理

  • 内存元数据metadata
    1)从形式上讲,元数据可分为内存元数据和元数据文件两种。其中NameNode在内存中维护整个文件系统的元数据镜像,用于HDFS的管理;元数据文件则用于持久化存储。
    2)从类型上讲,元数据有三类重要信息:-第一类是文件和目录自身的属性信息,例如文件名、目录名、父目录信息、文件大小、创建时间、修改时间等。-第二类记录文件内容存储相关信息,例如文件块情况、副本个数、每个副本所在的Data Node 信息等。-第三类用来记录HDFS中所有Data Node信息,用于Data Node管理。
    3)内存元数据结构INode文件和目录是文件系统的基本元素,HDFS将这些元素抽象成INode,每一个文件或目录都对应一个唯一的INode。它由FSNamesystem的成员变量dir实现对整个HDFS中INode的组织和操作,它是一个FSDirectory类。
    INode信息完全位于内存,因此有效的提高元数据的服务性能,然而一旦掉电将不再存在,故需要将INode信息保存到磁盘,这个功能是由FSImage完成的,它是架构在内存元数据与磁盘元数据文件之间的桥梁。
    由于所有的元数据位于内存,其大小随文件系统的规模增大而增大,如果每次都将整个内存元数据导出磁盘,将会带来很大的系统开销,所以HDFS在实现时,没有采用定期导出元数据的方法,而是采用元数据镜像文件(FSImage)+日志文件(edits)的备份机制,其中镜像文件是某一时刻内存元数据的真实组织情况,而日志文件则记录了该时刻以后所有的元数据操作 。
    BlockBlock是对于文件内容组织而言的,按照固定大小,顺序对文件进行划分并编号,划分好的每一个块就称之为一个Block,HDFS默认的Block大小为128MB。
    当一个客户端访问某一个文件特定偏移量的内容时,HDFS首先根据路径信息找到该文件对应的INode ,根据偏移计算出Block位置,然后找出相应的BlockInfo,再找到副本所在Data Node 的信息,选择其中一个Data Node进行连接,获取相应的内容。
    4)磁盘元数据文件磁盘元数据文件包括以下四个:
  1. fsimage:元数据镜像文件
  2. edits:日志文件
  3. fstime:保存最近一次Checkpoint的时间。
  4. VERSION:标志性文件,最后被创建,它的存在表明前三个元数据文件的创建成功。
  • 磁盘数据镜像文件fsimage
    镜像文件实际是存放目录结构、文件属性等相关信息。fsimage文件是NameNode中关于元数据的镜像,一般称为检查点,它是在NameNode启动时对整个文件系统的快照。fsimage文件是hadoop文件系统元数据的一个永久性的检查点,其中包含hadoop文件系统中的所有目录和文件idnode的序列化信息。
  • 数据操作日志文件edits
    记录着对集群的每一个操作。编辑日志是记录对文件或者目录的修改信息,比如删除目录,修改文件等信息。编辑日志一般命名规则是“edits_*”,它在NameNode启动后,记录对文件系统的改动序列。edits文件存放的是hadoop文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先会被记录到edits文件中。

2.存储机制
内存中有一份完整的元数据(内存metadata)磁盘有一个”准完整“的元数据镜像文件(在NN的工作目录中)用于衔接内存metadata和持久化元数据镜像fsimage之间的操作日志(edits文件)

———————————————————————————————————————————-
DataNode工作机制
————————————-
工作职责

  • 存储管理用户的文件块数据
  • 定期向NameNode汇报自身所持有的bock块信息(通过心跳信息上报)

————————————————————————————————————————————
SecondaryNamenode工作机制
——————————————————
edits文件会在集群运行的过程中不断增多,占用更多的存储空间,虽然有合并,但是只有在namenode重启时才会进行。并且在实际工作环境很少重启namenode,这就带来了一下问题:(1)edits文件不断增大,如何存储和管理?(2)因为需要合并大量的edits文件生成fsimage,导致namenode重启时间过长。(3)一旦namenode宕机,用于恢复的fsiamge数据很旧,会造成大量数据的丢失。

1.SNN通知NN切换edits文件SecondaryNameNode通知NameNode准备提交edits文件,此时主节点将新的写操作数据记录到一个新的文件edits.new中。
2.SNN从NN获得fsimage和editsSecondaryNameNode通过HTTP GET方式获取NameNodFailed to locate the winutils binary in the hadoop binary path java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.e的fsimage与edits文件(在SecondaryNameNode的current同级目录下可见到 temp.check-point或者previous-checkpoint目录,这些目录中存储着从namenode拷贝来的镜像文件)。
3.SNN将fsimage载入内存,然后开始合并editsSecondaryNameNode开始合并获取的上述两个文件,产生一个新的fsimage文件fsimage.ckpt。
4.SNN将新的fsimage发回给NNSecondaryNameNode用HTTP POST方式发送fsimage.ckpt至NameNode。
5.NN用新的fsimage替换旧的fsimageNameNode将fsimage.ckpt与edits.new文件分别重命名为fsimage与edits,然后更新fstime,整个checkpoint过程到此结束。
分布式存储--HDFS详解 - 图5
从工作过程可以看出,SecondaryNameNode的重要作用是定期通过编辑日志文件合并命名空间镜像,以防止编辑日志文件过大。SecondaryNameNode一般要在另一台机器上运行,因为它需要占用大量的CPU时间与namenode相同容量的内存才可以进行合并操作。它会保存合并后的命名空间镜像的副本,并在namenode发生故障时启用。

———————————————————————————————————————————————————
HDFS的HA(高可用)运行机制
————————————————-
分布式存储--HDFS详解 - 图6

  • Active NameNode 和 Standby NameNod
       两台 NameNode 形成互备,一台处于 Active 状态,为主 NameNode,另外一台处于                 Standby 状态,为备 NameNode,只有主 NameNode 才能对外提供读写服务。<br />
    
  • 主备切换控制器 ZKFailoverController
       ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控制。                ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借            助 Zookeeper 实现自动的主备选举和切换,当然 NameNode 目前也支持不依赖于                      Zookeeper 的手动主备切换。<br />
    
  • Zookeeper 集群
       为主备切换控制器提供主备选举支持。<br />
    
  • 共享存储系统:
       共享存储系统是实现 NameNode 的高可用最为关键的部分,共享存储系统保存了                         NameNode 在运行过程中所产生的 HDFS 的元数据。<br />
    
  • NameNode
      通过共享存储系统实现元数据同步。在进行主备切换的时候,新的主 NameNode 在确认元           数据完全同步之后才能继续对外提供服务。<br />
    
  • DataNode 节点
      除了通过共享存储系统共享 HDFS 的元数据信息之外,主 NameNode 和备 NameNode 还           需要共享 HDFS 的数据块和 DataNode 之间的映射关系。DataNode 会同时向主                           NameNode 和备 NameNode 上报数据块的位置信息。
    

流程:
分布式存储--HDFS详解 - 图7

1.HealthMonitor 初始化完成之后会启动内部的线程来定时调用对应 NameNode 的HAServiceProtocol RPC 接口的方法,对 NameNode 的健康状态进行检测。
2.HealthMonitor 如果检测到 NameNode 的健康状态发生变化,会回调 ZKFailoverController 注册的相应方法进行处理。
3.如果 ZKFailoverController 判断需要进行主备切换,会首先使用 ActiveStandbyElector 来进行自动的主备选举。
4.ActiveStandbyElector 与 Zookeeper 进行交互完成自动的主备选举。
5.ActiveStandbyElector 在主备选举完成后,会回调 ZKFailoverController 的相应方法来通知当前的 NameNode 成为主 NameNode 或备 NameNode。
6.ZKFailoverController 调用对应 NameNode 的 HAServiceProtocol RPC 接口的方法将 NameNode 转换为 Active 状态或 Standby 状态。

分布式存储--HDFS详解 - 图8