NameNode体系结构:fsimage,editslog
Namenode主要维护两个文件,一个是fsimage,一个是editlog
fsimage:保存了最新的元数据检查点,包含了整个HDFS文件系统的所有目录和文件的信息。对于文件来说包括了数据块描述信息、修改时间、访问时间等;对于目录来说包括修改时间、访问权限控制信息(目录所属用户,所在组)等。
editlog:主要是在NameNode已经启动情况下对HDFS进行的各种更新操作进行记录,HDFS客户端执行所有的写操作都会被记录到editlog中。
简单来想,NameNode维护了文件与数据块的映射表以及数据块与数据节点的映射表,什么意思呢?就是一个文件,它切分成了几个数据块,以及这些数据块分别存储在哪些datanode上,namenode一清二楚。fsimage就是在某一时刻,整个hdfs 的快照,就是这个时刻hdfs上所有的文件块和目录,分别的状态,位于哪些个datanode,各自的权限,各自的副本个数。然后客户端对hdfs所有的更新操作,比如说移动数据,或者删除数据,都会记录在editlog中。
为了避免editlog不断增大,secondary namenode会周期性合并fsimage和edits成新的fsimage,新的操作记录会写入新的editlog中,这个周期可以自己设置(editlog到达一定大小或者定时)。
HDFS的小文件问题
- 什么是小文件问题
一个小文件是一个明显小于HDFS块大小的文件(默认为64MB)。如果你要存储小文件,那么你可能有很多文件(否则你不会转向Hadoop),问题是HDFS无法处理大量文件。
在HDFS每个文件,目录和块被表示为在名称节点的存储器中的对象,其每一个占用150个字节,作为一个经验法则。因此,每个使用一个块的1000万个文件将使用大约3千兆字节的内存。超出此级别的扩展是当前硬件的问题。当然十亿个文件是不可行的。
此外,HDFS还没有准备好有效地访问小文件:它主要用于大型文件的流式访问。通过小文件读取通常会导致大量的搜索和从datanode到datanode的大量跳转以检索每个小文件,所有这些都是低效的数据访问模式。
- 小文件和MapReduce的问题
映射任务通常一次处理一个输入块(使用默认值FileInputFormat)。如果文件很小并且有很多文件,那么每个地图任务处理的输入都很少,而且还有更多的地图任务,每个任务都会增加额外的簿记开销。将1GB文件分成16个64MB块和10,000个左右100KB文件。10,000个文件各使用一个映射,并且作业时间可能比具有单个输入文件的等效文件慢几十或几百倍。
有一些功能可以帮助减轻簿记开销:任务JVM重用以在一个JVM中运行多个映射任务,从而避免一些JVM启动开销(请参阅mapred.job.reuse.jvm.num.tasks属性),并且MultiFileInputSplit每个映射可以运行多个拆分。
- 为什么会有小文件问题?
至少有两个情况
- 这些文件是较大逻辑文件的一部分。由于HDFS最近才支持附加,因此保存无界文件(例如日志文件)的一种非常常见的模式是将它们以块的形式写入HDFS。
- 这些文件本来就很小。想象一下大量的图像。每个图像都是一个不同的文件,没有自然的方法将它们组合成一个更大的文件。
这两种情况需要不同的解决方案 对于第一种情况,文件由记录组成,可以通过调用HDFS的sync()方法(随附附带,尽管参见此讨论)来经常连续写入大文件来避免问题。或者,可以编写一个程序来将小文件连接在一起(参见Nathan Marz 关于一个名为Consolidator的工具的帖子,它正是这样做的)。
- 如何解决小文件问题
- HAR文件
- Sequence 文件
- Hbase