1.小文件场景
有三个文件分别为 1.TXT 1B 2.txt 2K 3.txt 10B
那么根据上次讲得切片方法,会将这三个文件切成3片,启动3个maptask进程。
mapreduce中的task都是java进程,这在申请资源, 获得资源,启动JVM虚拟机,启动任务,处理了这三个小文件,在销毁资源释放。可能程序进行了40秒,30秒都在做准备工作,效率非常低,这大大浪费了资源。
那么怎么处理呢?
将小文件合并成大文件。大小以block大小为基准。
1.在上传hdfs之前合并(效率最高)
java IO本地合并 这和 Hadoop mr 没有关系
2.在上传hdfs过程中合并
用appendToFile 命令追加合并
3.在上传hdfs之后合并(弥补措施)
(1)用Archive小文件归档合并
(2)改变TextInputFormat这个读数据的类
1.自定义inputformat组件(不推荐)
2.用combineTextInputFormat类(推荐)
2.大文件场景
有一个文件100T
直接改变block大小 在hdfs-default.xml配置文件中修改 dfs.blocksize =512g
3.文件大小略大于block大小场景(官方处理完)
有一个文件为129M
那么按照切片规则分为 split1 0-128M split2 128-129M
在mr底层源码中有bytesRemaining / splitSize > SPLIT_SLOP = 1.1。
也就是说最后一片的切片大小可以有一个10%的余量,具体数值要根据实际block的大小。 所以按照默认的话上文的切片应该为 split 0-129M
4.文件在存储时被拆成两部分(官网处理完)
因为hadoop中的文件存储是分块存储的,也是因为HDFS底层分块存储属于内部逻辑,不会考虑数据的完整性,而mr恰好是基于block来处理的。如果1个单词例如hello,被分成he在一个block里,llo在一个block里怎么办?
1.每个maptask都会读取下一个切片的第一行数据。
2.如果不是第一个maptask,都会舍弃自己的第一行不处理。