本节书摘来自华章出版社《Flume日志收集与MapReduce模式》一书中的第1章,第1.3节,作者 [美] 史蒂夫·霍夫曼(Steve Hoffman)斯里纳特·佩雷拉(Srinath Perera),更多章节内容可以访问云栖社区“华章计算机”公众号查看
1.3 HDFS与流式数据/日志的问题
HDFS并不是真正的文件系统,至少从传统的认识来说不是这样,对于通常的文件系统来说,很多我们认为理所当然的东西并不适合于HDFS,比如挂载。这使得将流式数据装载进Hadoop中变得有些复杂。
在通常的Portable Operating System Interface(POSIX)风格的文件系统中,如果打开文件并写入数据,那么在文件关闭前它会一直存在于磁盘上。也就是说,如果另一个程序打开了相同的文件并开始读取,那么它会读取到写入器写到磁盘上的数据。此外,如果该写入进程中断,那么写到磁盘上的任何部分都是可用的(有可能不完整,但确实是存在的)。
在HDFS中,文件只作为目录项存在,在文件关闭前,其长度一直显示为0。这意味着如果在一段时间内将数据写到文件中但却没有将其关闭,那么一旦客户端出现网络中断,你就什么都得不到了,只有一个空白文件而已。你会得出这样一个结论,即最好编写小文件,这样就能尽快将其关闭了。
问题在于Hadoop并不喜欢过多的小文件。由于HDFS元数据保存在NameNode的内存中,因此创建的文件越多,所需的RAM就越多。从MapReduce的角度来看,小文件会导致效率低下。通常情况下,每个Mapper都会被分配单个文件块作为输入(除非使用了某些压缩编码)。如果有过多的小文件,那么与待处理的数据相比,启动工作进程的代价就过高了。这种碎片还会导致更多的Mapper任务,使得总的Job运行时间增加。
在决定写入到HDFS的周期时需要考虑这些因素。如果计划保留数据较短的时间,那么可以使用较小的文件。然而,如果计划保留数据较长的时间,那么可以使用较大的文件或是做一些周期性的清理工作,将小文件压缩为少量的大文件,使得它们更加适合于MapReduce。毕竟,你只是写入一次数据,但却要在这些数据上运行MapReduce任务成百上千次。