我有一个大约120gb大小的大gz文件。我想在上面运行mapreduce,但由于gz文件是不可拆分的,所以一次只能有一个Map器处理该文件。该文件在hdfs和local上都存在。可能的选择我在想:
1) 解压gz文件并将其存储在hdfs中:首先,解压文件和将解压数据放入hdfs将花费太多时间。另外,我不能在hdfs中直接解压缩文件,因为hdfs没有zcat或gunzip命令。所以我必须这么做 zcat a.gz | hdfs dfs put - /path/in/hdfs
. 此外,这将占用hdfs中的大量空间(大约是gz的4倍)
2) 将文件分成小文件(每个文件大约1gb)并对其进行处理:最好的选择,但不幸的是不起作用。我正在使用split命令将大文件拆分为小文件(也尝试了cata.gz | head-n),但是当我在它们上运行mapper时,我得到了一个错误
Error: java.io.EOFException: Unexpected end of input stream
at org.apache.hadoop.io.compress.DecompressorStream.decompress(DecompressorStream.java:145)
at org.apache.hadoop.io.compress.DecompressorStream.read(DecompressorStream.java:85)
at java.io.InputStream.read(InputStream.java:101)
at org.apache.hadoop.util.LineReader.fillBuffer(LineReader.java:180)
at org.apache.hadoop.util.LineReader.readDefaultLine(LineReader.java:216)
at org.apache.hadoop.util.LineReader.readLine(LineReader.java:174)
at org.apache.hadoop.mapreduce.lib.input.LineRecordReader.nextKeyValue(LineRecordReader.java:185)
at org.apache.hadoop.mapred.MapTask$NewTrackingRecordReader.nextKeyValue(MapTask.java:553)
at org.apache.hadoop.mapreduce.task.MapContextImpl.nextKeyValue(MapContextImpl.java:80)
at org.apache.hadoop.mapreduce.lib.map.WrappedMapper$Context.nextKeyValue(WrappedMapper.java:91)
at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:144)
at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:784)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:341)
at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:168)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:415)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1642)
at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:163)
3) 解压文件,然后再次压缩到bzip2:这也需要花费很多时间。
请给我一些其他的建议来达到这个目的,或者修改以上三种方法中的任何一种来获得成功(我更喜欢第二种方法:p)
1条答案
按热度按时间rekjcdws1#
我想你可以选择第三种。在bzip2中压缩文件的优点是可以在mapreduce作业中直接使用它。由于bzip2是可拆分的,因此不需要手动将其拆分为1gb文件(如选项2中所示)并对其进行处理,hadoop必须将其存储到指定大小的块中,并在配置的输入拆分上进行处理。因此,将文件压缩到bzip2的预处理应该可以正常工作。