在大数据环境,很多组件都是基于HDFS,例如HDFS直接放文件环境、以及HBase、Hive等上层数据库环境。如果对HDFS环境未进行优化,小文件可能会造成HDFS系统的崩溃。今天我们来看一下。
一、究竟会出什么问题
因为HDFS为了加速数据的存储速度,将文件的存放位置数据(元数据)存在了NameNode的内存,而NameNode又是单机部署,如果小文件过多,将直接导致NameNode的内存溢出,而文件无法写入。
为此在HDFS中放小文件必须进行优化,不能将小文件(类似1MB的若干小文件)直接放到HDFS中。
二、数据在DataNode中如何存储?
HDFS默认的数据存储块是64MB,现在新版本的hadoop环境(2.7.3版本后),默认的数据存储块是128MB。
一个文件如果小于128MB,则按照真实的文件大小独占一个数据存储块,存放到DataNode节点中。同时 DataNode一般默认存三份副本,以保障数据安全。同时该文件所存放的位置也写入到NameNode的内存中,如果有Secondary NameNode高可用节点,也可同时复制一份过去。NameNode的内存数据将会存放到硬盘中,如果HDFS发生重启,将产生较长时间的元数据从硬盘读到内存的过程。
如果一个文件大于128MB,则HDFS自动将其拆分为128MB大小,存放到HDFS中,并在NameNode内存中留下其数据存放的路径。不同的数据块将存放到可能不同的DataNode中。
三、如何解决小文件需要存放到HDFS的需求?
1.合并小文件,数据未落地到HDFS之前合并或者数据已经落到HDFS,用spark service服务或其它程序每天调度去合并。Apache官方也提供了官方工具。Hadoop Archive或者HAR,是一个高效地将小文件放入HDFS块中的文件存档工具,它能够将多个小文件打包成一个HAR文件,这样在减少namenode内存使用的同时,仍然允许对文件进行透明的访问。
2、多Master设计,让元数据分散存放到不同的NameNode中。
也许还有同学会提到增大NameNode的内存、甚至将元数据直接从硬盘中读取,但这些方法都是治标不治本,不适用。
四、小文件的其它危害
小文件除了可能会撑爆NameNode。另一个是hive或者spark计算的时候会影响它的速度,因为spark计算时会将数据从硬盘读到内存,零碎的文件将产生较多的寻道过程。
五、题外话:HDFS为什么将Block块设置为128M
1、如果低于128M,甚至过小。一方面会造成NameNode内存占用率高的问题,另一方面会造成数据的寻址时间较多。
2、如果于高于128M,甚至更大。会造成无法利用多DataNode的优势,数据只能从从一个DN中读取,无法实现多DN同时读取的速率优势。