hdfs100问
title: hdfs100问
tags:
grammar_cjkRuby: true
1.hdfs架构
和zookeeper的写流程的管理手段非常像,都是作为分布式存储的,二级结构。
2.namenode格式化是什么 为什么要进行
格式化就是相当于格式化磁盘一样,清楚索引块信息,重新使用hdfs物理存储。
3.namenode宕机数据恢复
通常来说一些比较大的文件(例如10T),都会分布式地存储在多个服务器的磁盘中去,文件的元数据都会保存在NameNode中去,文件的访问修改时间,文件的副本个数,以及block大小以及组成文件的block信息,文件的内容保存在DataNode中。为了能够在启动时快速加载这些文件信息(元数据),这些信息都会保存在内存中去。但是只要namenode所在的服务器关机,这些信息就会马上丢失,所以就有了两种方式在NameNode本地持久化:命名空间镜像文件(fsimage)和编辑日志(edits log)。
VERSION文件是一个Java的属性文件
namespaceID是该文件系统的唯一标志符,当NameNode第一次格式化的时候生成。
clusterID是HDFS集群使用的一个唯一标志符,在HDFS联邦的情况下,就看出它的作用了,因为联邦情况下,集群有多个命名空间,不同的命名空间由不同的NameNode管理。
blockpoolID是block池的唯一标志符,一个NameNode管理一个命名空间,该命名空间中的所有文件存储的block都在block池中。
edits表示edits log日志文件
fsimage表示文件系统元数据镜像文件
3.0Fsimage和edits概念
3.1edits文件如何防止事务丢失/secondnamenode如何加速数据恢复
edits log在磁盘上表现为一定数量的文件。每个文件称为片段(Segment),前缀“edits”,后缀是其中包含的事务ID(transaction IDs)。每个写操作事务都仅仅打开一个文件(比如:edits_inprogress_00000000000010),写完后冲刷缓冲区并同步到磁盘,然后返回客户端success状态码。如果NameNode的元数据需要写到多个目录中,则对于每个写事务需要所有的写操作都完成,并冲刷缓冲区同步到磁盘才返回success状态码。这样就可以保证在发生宕机的时候没有事务数据丢失。
edits log:记录用户对文件的若干操作并同步到磁盘中去。edits log会随着对文件系统的操作而无限制地增长,这对正在运行的NameNode而言没有任何影响,如果NameNode重启,则需要很长的时间执行edits log的记录以更新fsimage(元数据镜像文件)。在此期间,整个系统不可用。解决方案就是运行SecondaryNameNode,它的作用就是为NameNode内存中的文件系统元数据生成检查点(checkpoint)。检测点实际就是镜像文件fsimage
EditLog:记录针对文件的操作,包括创建、删除、重命名等;这两个文件都会被加载到内存中;
3.2从上图中可以看出FsImage和EditLog在secondaryNameNode中进行了合并操作,那为什么不把这两个文件就用一个文件进行代替呢?
原因很简单:FsImage文件是一个很大的文件,大文件就不好处理,因此就会想到把增加的修改部分单独的独立出来,修改之后在合并回去,这样就会很好的管理大的文件;
SecondaryNameNode的作用就是为NameNode进行备份的角色,定期的同步数据,当NameNode出现故障的时候会起到回复NameNode的作用;
3.3 secondaryNamenode工作流程
SecondaryNameNode的工作情况:
- SecondaryNameNode会定期和NameNode通信,请求其停止使用EditLog文件,暂时将新的写操作写到一个新的文件edit.new上来,这个操作是瞬间完成,上层写日志的函数完全感觉不到差别;
- SecondaryNameNode通过HTTP GET方式从NameNode上获取到FsImage和EditLog文件,并下载到本地的相应目录下;
- SecondaryNameNode将下载下来的FsImage载入到内存,然后一条一条地执行EditLog文件中的各项更新操作,使得内存中的FsImage保持最新;这个过程就是EditLog和FsImage文件合并;
- SecondaryNameNode执行完(3)操作之后,会通过post方式将新的FsImage文件发送到NameNode节点上
- NameNode将从SecondaryNameNode接收到的新的FsImage替换旧的FsImage文件,同时将edit.new替换EditLog文件,通过这个过程EditLog就变小了
3.4 namenode和secondarynamenode流程结合
- 第一阶段:NameNode启动
(1)第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。
(2)客户端对元数据进行增删改的请求。
(3)NameNode记录操作日志,更新滚动日志。
(4)NameNode在内存中对数据进行增删改。
- 第二阶段:Secondary NameNode工作
(1)Secondary
NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查结果。
(2)Secondary NameNode请求执行CheckPoint。
(3)NameNode滚动正在写的Edits日志。
(4)将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode。
(5)Secondary NameNode加载编辑日志和镜像文件到内存,并合并。
(6)生成新的镜像文件fsimage.chkpoint。
(7)拷贝fsimage.chkpoint到NameNode。
(8)NameNode将fsimage.chkpoint重新命名成fsimage。
4.如何保证namenode高可用以及为什么使用
1)所谓HA(High Available),即高可用(7x24小时不中断服务)。
2)实现高可用最关键的策略是消除单点故障。HA严格来说应该分成各个组件的HA机制:HDFS的HA和YARN的HA。
3)Hadoop2.0之前,在HDFS集群中NameNode存在单点故障(SPOF)。
4)NameNode主要在以下两个方面影响HDFS集群
NameNode机器发生意外,如宕机,集群将无法使用,直到管理员重启
NameNode机器需要升级,包括软件、硬件升级,此时集群也将无法使用
HDFS HA功能通过配置Active/Standby两个NameNodes实现在集群中对NameNode的热备来解决上述问题。如果出现故障,如机器崩溃或机器需要升级维护,这时可通过此种方式将NameNode很快的切换到另外一台机器。
4.0有待进一步搞清楚机制包括yarn HA
4.1namenode集群高可用难点
- 主NameNode(active)和从NameNode(standby)要状态同步
- 防止脑裂(split-brain)。顾名思义,就是双机热备的系统中,两个主节点突然失去联系,这时,两个节点会同时以为对方出现故障,会本能地争抢资源,就像脑裂人一样。即隔离(Fence),即同一时刻仅仅有一个 NameNode 对外提供服务
- 在准备切换时,对上层应用要做到无感知
- 必须保证两个 NameNode 之间能够 ssh 无密码登录。
5.文件块大小限制,文件块大小取决条件
最佳应用寻址时间为传输时间的百分之一最好,所以文件块大小取决于磁盘传输速率
5.1为什么文件块大小不能设置过大或过小
6.hdfs读写数据流程
6.1 写数据流程
相当于两个线程,一个是meta源数据,请求数据可以写在哪儿,一个是IO流真正的请求建立通道,然后写入流程。
1)客户端通过Distributed FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在。
2)NameNode返回是否可以上传。
3)客户端请求第一个 Block上传到哪几个DataNode服务器上。
4)NameNode返回3个DataNode节点,分别为dn1、dn2、dn3。
5)客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。
6)dn1、dn2、dn3逐级应答客户端。
7)客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答。
8)当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)。
6.2.hdfs写的过程中如何计算相邻发送数据位置最近的datanode
节点距离:两个节点到达最近的共同祖先的距离总和。
如上图所示
- 同一节点上的进程节点距离为0
- 同一机架上不同节点的距离为两个节点到共同机架r1的距离总和,为2
- 同一数据中心不同机架的节点距离为两个节点到共同祖先集群d1的距离之和,为4
- 不同数据中心的节点距离为两个节点到达共同祖先数据中心的距离之和,为6
6.3.hdfs如何选择存储副本的节点
副本的数量我们可以从配置文件中设置,那么HDFS是怎么选择副本存储的节点的呢?
如上图所示,为了提高容错性,有如下设置,加入现在有3个副本:
- 第一个副本在Client所在的节点上,如果客户端在集群外,则随机选一个
- 第二个副本和第一个副本位于相同机架,随机节点
- 第三个副本位于不同机架,随机节点
这样做的目的就是为了提高容错性。
6.4.hdfs读流程
也是相当于两个线程,一个先从meta得到文件块位置,另一个在datanode读取
1)客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。
2)挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
3)DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
4)客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。
7.hdfs重启过程
重启和格式化之后启动不一样,一个是已经包含多个块,一个是第一次启动。涉及到的问题可查看图片红色字体区域。
8.datanode工作机制
1)一个数据块在DataNode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
2)DataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报所有的块信息。
3)心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用。
4)集群运行中可以安全加入和退出一些机器。
8.1datanode如何检查数据完整性–相当于数字签名,校验一致性,不一致就是损坏
1)当DataNode读取Block的时候,它会计算CheckSum。
2)如果计算后的CheckSum,与Block创建时值不一样,说明Block已经损坏。
3)Client读取其他DataNode上的Block。
4)DataNode在其文件创建后周期验证CheckSum,如图3-16所示。
用户肯定都希望系统在存储和处理数据时,数据不会有任何丢失或损坏。但是,受网络不稳定、硬件损坏等因素,IO操作过程中难免会出现数据丢失或脏数据,难免会出现数据丢失或脏数据,数据传输的量越大,出现错误的概率就越高。
检测数据是否损坏的常见措施是,在数据第一次引入系统时计算校验和(checksum)并存储,在数据进行传输后再次计算校验和进行对比,如果计算所得的新校验和和原来的校验和不匹配,就认为数据已损坏。但该技术并不能修复数据——它只能检测出数据错误。(这正是不使用低端硬件的原因。具体说来,一定要使用ECC内存。)注意,校验和也是可能损坏的,不只是数据,但由于校验和比数据小得多,所以损坏的可能性非常小。
8.2datanode 宕机或掉线处理
datanode进程死亡或者网络故障造成datanode无法与namenode通信,namenode不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长。HDFS默认的超时时长为10分钟+30秒。
datanode宕机后,hdfs会将缺失的block根据副本因子数再复制一份,宕机的datanode恢复之后,该datanonde上多余的块不会立即删除,因为hdfs block数量有一个上限,一般会大于副本因子,只要block数量不超过上限,hdfs不会删除多余的block,除非手动触发balancer。
9.hdfs小文档处理
至少有两种场景下会产生大量的小文件:
(1)这些小文件都是一个大逻辑文件的一部分。由于HDFS在2.x版本开始支持对文件的append,所以在此之前保存无边界文件(例如,log文件)(译者注:持续产生的文件,例如日志每天都会生成)一种常用的方式就是将这些数据以块的形式写入HDFS中(a very common pattern for saving unbounded files (e.g. log files) is to write them in chunks into HDFS)。
(2)文件本身就是很小。设想一下,我们有一个很大的图片语料库,每一个图片都是一个独一的文件,并且没有一种很好的方法来将这些文件合并为一个大的文件。