HDFS(Hadoop Distributed File System )Hadoop散布式文件系统的简称。HDFS被设计成合适运行在通用硬件(commodity hardware)上的散布式文件系统。DFS是1个高度容错性的系统,合适部署在便宜的机器上。HDFS能提供高吞吐量的数据访问,非常合适大范围数据集上的利用。HDFS放宽了1部份POSIX束缚,来实现流式读取文件系统数据的目的。HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的。HDFS是Apache Hadoop Core项目的1部份。
本篇首先对HDFS的重要特性和使用处景做1个扼要说明,以后对HDFS的数据读写、元数据管理和NameNode、SecondaryNamenode的工作机制进行深入分析。
HDFS是1个文件系统,用于存储和管理文件,通过统1的命名空间(类似于本地文件系统的目录树)。HDFS是散布式的系统,服务器集群中各个节点都有自己的角色和职责。理解HDFS,需要注意以下几个概念:
客户端要向HDFS写数据,首先要跟namenode通讯以确认可以写文件并取得接收文件block的datanode,然后客户端按顺序将文件逐一block传递给相应datanode,并由接收到block的datanode负责向其他datanode复制block的副本。
对HDFS写数据的流程大概可以用以下的流程图表示:
7. 客户端向namenode发送上传文件要求,namenode对要上传目录和文件进行检查,判断是不是可以上传,并向客户端返回检查结果。
8. 客户端得到上传文件的允许后读取客户端配置,如果没有指定配置则会读取默许配置(例如副本数和块大小默许为3和128M,副本是由客户端决定的)。向namenode要求上传1个数据块。
9. namenode会根据客户真个配置来查询datanode信息,如果使用默许配置,那末终究结果会返回同1个机架的两个datanode和另外一个机架的datanode。这称为“机架感知”策略。
10. 客户端在开始传输数据块之前会把数据缓存在本地,当缓存大小超过了1个数据块的大小,客户端就会从namenode获得要上传的datanode列表。以后会在客户端和第1个datanode建立连接开始流式的传输数据,这个datanode会1小部份1小部份(4K)的接收数据然后写入本地仓库,同时会把这些数据传输到第2个datanode,第2个datanode也一样1小部份1小部份的接收数据并写入本地仓库,同时传输给第3个datanode,顺次类推。这样逐级调用和返回以后,待这个数据块传输完成客户端后告知namenode数据块传输完成,这时候候namenode才会更新元数据信息记录操作日志。
11. 第1个数据块传输完成后会使用一样的方式传输下面的数据块直到全部文件上传完成。
细节:
a.要求和应对是使用RPC的方式,客户端通过ClientProtocol与namenode通讯,namenode和datanode之间使用DatanodeProtocol交互。在设计上,namenode不会主动发起RPC,而是响应来自客户端或 datanode 的RPC要求。客户端和datanode之间是使用socket进行数据传输,和namenode之间的交互采取nio封装的RPC。
b.HDFS有自己的序列化协议。
c.在数据块传输成功后但客户端没有告知namenode之前如果namenode宕机那末这个数据块就会丢失。
d.在流式复制时,逐级传输和响应采取响应队列来等待传输结果。队列响应完成后返回给客户端。
c.在流式复制时如果有1台或两台(不是全部)没有复制成功,不影响最后结果,只不过datanode会定期向namenode汇报本身信息。如果发现异常namenode会指挥datanode删除残余数据和完善副本。如果副本数量少于某个最小值就会进入安全模式。
客户端将要读取的文件路径发送给namenode,namenode获得文件的元信息(主要是block的寄存位置信息)返回给客户端,客户端根据返回的信息找到相应datanode逐一获得文件的block并在客户端本地进行数据追加合并从而取得全部文件。
HDFS读数据步骤大概可以用以下的流程图表示:
12. 客户端向namenode发起RPC调用,要求读取文件数据。
13. namenode检查文件是不是存在,如果存在则获得文件的元信息(blockid和对应的datanode列表)。
14. 客户端收到元信息后选取1个网络距离最近的datanode,顺次要求读取每一个数据块。客户端首先要校检文件是不是破坏,如果破坏,客户端会选取另外的datanode要求。
15. datanode与客户端简历socket连接,传输对应的数据块,客户端收到数据缓存到本地,以后写入文件。
顺次传输剩下的数据块,直到全部文件合并完成。
注:文件合并的问题从某个Datanode获得的数据块有多是破坏的,破坏多是由Datanode的存储装备毛病、网络毛病或软件bug酿成的。HDFS客户端软件实现了对HDFS文件内容的校验和(checksum)检查。当客户端创建1个新的HDFS文件,会计算这个文件每一个数据块的校验和,并将校验和作为1个单独的隐藏文件保存在同1个HDFS名字空间下。当客户端获得文件内容后,它会检验从Datanode获得的数据跟相应的校验和文件中的校验和是不是匹配,如果不匹配,客户端可以选择从其他Datanode获得该数据块的副本。
HDFS删除数据比较流程相对简单,只列出详细步骤:
16. 客户端向namenode发起RPC调用,要求删除文件。namenode检查合法性。
17. namenode查询文件相干元信息,向存储文件数据块的datanode发出删除要求。
18. datanode删除相干数据块。返回结果。
19. namenode返回结果给客户端。
注:当用户或利用程序删除某个文件时,这个文件并没有立刻从HDFS中删除。实际上,HDFS会将这个文件重命名转移到/trash目录。只要文件还在/trash目录中,该文件就能够被迅速地恢复。文件在/trash中保存的时间是可配置的,当超过这个时间时,Namenode就会将该文件从名字空间中删除。删除文件会使得该文件相干的数据块被释放。注意,从用户删除文件到HDFS空闲空间的增加上间会有1定时间的延迟。只要被删除的文件还在/trash目录中,用户就能够恢复这个文件。如果用户想恢复被删除的文件,他/她可以阅读/trash目录找回该文件。/trash目录仅仅保存被删除文件的最后副本。/trash目录与其他的目录没有甚么区分,除1点:在该目录上HDFS会利用1个特殊策略来自动删除文件。目前的默许策略是删除/trash中保存时间超过6小时的文件。将来,这个策略可以通过1个被良好定义的接口配置。
当1个文件的副本系数被减小后,Namenode会选择多余的副本删除。下次心跳检测时会将该信息传递给Datanode。Datanode遂即移除相应的数据块,集群中的空闲空间加大。一样,在调用setReplication API结束和集群中空闲空间增加间会有1定的延迟。
首先明确namenode的职责:响应客户端要求、管理元数据。
namenode对元数据有3种存储方式:内存元数据(NameSystem)、磁盘元数据镜像文件、数据操作日志文件(可通过日志运算出元数据)
细节:HDFS不合适存储小文件的缘由,每一个文件都会产生元信息,当小文件多了以后元信息也就多了,对namenode会造成压力。
3种存储机制的解释
内存元数据就是当前namenode正在使用的元数据,是存储在内存中的。磁盘元数据镜像文件是内存元数据的镜像,保存在namenode工作目录中,它是1个准元数据,作用是在namenode宕机时能够快速较准确的恢复元数据。称为fsimage。数据操作日志文件是用来记录元数据操作的,在每次改动元数据时都会追加日志记录,如果有完全的日志就能够还原完全的元数据。主要作用是用来完善fsimage,减少fsimage和内存元数据的差距。称为editslog。
checkpoint机制分析
由于namenode本身的任务就非常重要,为了不再给namenode压力,日志合并到fsimage就引入了另外一个角色secondarynamenode。secondarynamenode负责定期把editslog合并到fsimage,“定期”是namenode向secondarynamenode发送RPC要求的,是按时间或日志记录条数为“间隔”的,这样即不会浪费合并操作又不会造成fsimage和内存元数据有很大的差距。由于元数据的改变频率是不固定的。
每隔1段时间,会由secondary namenode将namenode上积累的所有edits和1个最新的fsimage下载到本地,并加载到内存进行merge(这个进程称为checkpoint)。
checkpoint步骤:
1. namenode向secondarynamenode发送RPC要求,要求合并editslog到fsimage。
2. secondarynamenode收到要求后从namenode上读取(通过http服务)editslog(多个,转动日志文件)和fsimage文件。
3. secondarynamenode会根据拿到的editslog合并到fsimage。构成最新的fsimage文件。(中间有很多步骤,把文件加载到内存,还原成元数据结构,合并,再生成文件,新生成的文件名为fsimage.checkpoint)。
4. secondarynamenode通过http服务把fsimage.checkpoint文件上传到namenode,并且通过RPC调用把文件改名为fsimage。
namenode和secondary namenode的工作目录存储结构完全相同,所以,当namenode故障退出需要重新恢复时,可以从secondary namenode的工作目录中将fsimage拷贝到namenode的工作目录,以恢复namenode的元数据。
关于checkpoint操作的配置:
dfs.namenode.checkpoint.check.period=60 #检查触发条件是不是满足的频率,60秒
dfs.namenode.checkpoint.dir=file://${hadoop.tmp.dir}/dfs/namesecondary
#以上两个参数做checkpoint操作时,secondary namenode的本地工作目录
dfs.namenode.checkpoint.edits.dir=${dfs.namenode.checkpoint.dir}
dfs.namenode.checkpoint.max-retries=3 #最大重试次数
dfs.namenode.checkpoint.period=3600 #两次checkpoint之间的时间间隔3600秒
dfs.namenode.checkpoint.txns=1000000 #两次checkpoint之间最大的操作记录
editslog和fsimage文件存储在$dfs.namenode.name.dir/current目录下,这个目录可以在hdfs-site.xml中配置的。目录结果以下:
包括edits日志文件(转动的多个文件),有1个是edits_inprogress_*是当前正在写的日志。fsimage文件和md5校检文件。seen_txid是记录当前转动序号,代表seen_txid之前的日志都已合并完成。
$dfs.namenode.name.dir/current/seen_txid非常重要,是寄存transactionId的文件,format以后是0,它代表的是namenode里面的edits_*文件的尾数,namenode重启的时候,会依照seen_txid的数字恢复。所以当你的hdfs产生异常重启的时候,1定要比对seen_txid内的数字是否是你edits最后的尾数,不然会产生重启namenode时metaData的资料有缺少,致使误删Datanode上过剩Block的信息。
安全模式:Namenode启动后会进入1个称为安全模式的特殊状态。处于安全模式的Namenode是不会进行数据块的复制的。Namenode从所有的 Datanode接收心跳信号和块状态报告。块状态报告包括了某个Datanode所有的数据块列表。每一个数据块都有1个指定的最小副本数。当Namenode检测确认某个数据块的副本数目到达这个最小值,那末该数据块就会被认为是副本安全(safely replicated)的;在1定百分比(这个参数可配置)的数据块被Namenode检测确认是安全以后(加上1个额外的30秒等待时间),Namenode将退出安全模式状态。接下来它会肯定还有哪些数据块的副本没有到达指定数目,并将这些数据块复制到其他Datanode上。