合并hadoop

时间:2016-08-23 14:23:01

标签: hadoop mapreduce hive hdfs hadoop2

我在HDFS中有一个目录(Final Dir),其中一些文件(例如:10 mb)每分钟加载一次。 一段时间后,我想将所有小文件组合成一个大文件(例如:100 mb)。但是用户不断将文件推送到Final Dir。这是一个持续的过程。

所以我第一次需要将前10个文件合并到一个大文件(例如:large.txt)并将文件保存到Finaldir。

现在我的问题是我将如何获得除前10个文件之外的下10个文件?

可以请一些人帮助我

2 个答案:

答案 0 :(得分:7)

这是另一个替代方案,这仍然是@Andrew在他的评论中指出的遗留方法,但还有额外的步骤,使您的输入文件夹作为缓冲区接收小文件,及时将它们推送到tmp目录,合并它们并将结果推回输入。

第1步:创建一个tmp目录

hadoop fs -mkdir tmp

步骤2:在一个时间点将所有小文件移动到tmp目录

hadoop fs -mv input/*.txt tmp

第3步 - 在hadoop-streaming jar

的帮助下合并小文件
hadoop jar $HADOOP_HOME/share/hadoop/tools/lib/hadoop-streaming-2.6.0.jar \
                   -Dmapred.reduce.tasks=1 \
                   -input "/user/abc/input" \
                   -output "/user/abc/output" \
                   -mapper cat \
                   -reducer cat

步骤4-将输出移动到输入文件夹

hadoop fs -mv output/part-00000 input/large_file.txt

第5步 - 删除输出

 hadoop fs -rm -R output/

步骤6 - 从tmp

中删除所有文件
hadoop fs -rm tmp/*.txt

从步骤2到步骤6创建一个shell脚本,并安排它定期运行以定期合并较小的文件(可能根据您的需要每分钟)

安排合并小文件的cron作业的步骤

步骤1:借助上述步骤(2到6)创建一个shell脚本 /home/abc/mergejob.sh

重要提示:您需要在脚本中指定hadoop的绝对路径,以便cron理解

#!/bin/bash
/home/abc/hadoop-2.6.0/bin/hadoop fs -mv input/*.txt tmp
wait
/home/abc/hadoop-2.6.0/bin/hadoop jar /home/abc/hadoop-2.6.0/share/hadoop/tools/lib/hadoop-streaming-2.6.0.jar \
                   -Dmapred.reduce.tasks=1 \
                   -input "/user/abc/input" \
                   -output "/user/abc/output" \
                   -mapper cat \
                   -reducer cat
wait
/home/abc/hadoop-2.6.0/bin/hadoop fs -mv output/part-00000 input/large_file.txt
wait
/home/abc/hadoop-2.6.0/bin/hadoop fs -rm -R output/
wait
/home/abc/hadoop-2.6.0/bin/hadoop fs -rm tmp/*.txt

第2步:使用cron计划脚本使用cron表达式每分钟运行

a)通过选择编辑器来编辑crontab

>crontab -e

b)在结尾添加以下行并退出编辑器

* * * * * /bin/bash /home/abc/mergejob.sh > /dev/null 2>&1

合并作业将安排在每分钟运行一次。

希望这有用。

答案 1 :(得分:2)

@Andrew为您提供了一个解决方案,该解决方案是 6年前适用于批量导向的世界。
但是在2016年,您有一个微批量数据流,并且需要一个非阻塞解决方案。

我将如何做到这一点:

  • 创建一个包含3个分区的EXTERNAL表,映射到3个目录 例如new_datareorghistory
  • 将新文件提供给new_data
  • 实施作业以运行批量压缩,并定期运行

现在批量压缩逻辑:

  1. 确保在压缩运行时不会执行SELECT查询,否则会返回重复项
  2. 选择所有适合压缩的文件(定义您自己的文件) 标准)移动它们从new_data目录到reorg
  3. 将所有这些reorg文件的内容合并history dir 中的新文件中(随时可以随意GZip,Hive会识别.gz扩展名
  4. 删除 reorg
  5. 中的文件

    所以它基本上是旧的2010年故事,除了你的现有数据流可以继续将新文件转储到new_data,同时压缩安全地在不同的目录中运行。如果压缩作业崩溃,您可以安全地调查/清理/恢复压缩,而不会影响数据流。


    顺便说一句,我不是基于" Hadoop Streaming"的2010解决方案的忠实粉丝。工作 - 一方面,"流媒体"现在有一个非常不同的含义;另一方面," Hadoop流媒体"在过去是有用的,但现在已经不再适用了;在抓握手[*]上,您可以使用Hive查询(例如

    )完成此操作
    INSERT INTO TABLE blahblah PARTITION (stage='history')
    SELECT a, b, c, d
    FROM blahblah
    WHERE stage='reorg'
    ;
    

    在该查询之前有几个SET some.property = somevalue,您可以定义将在结果文件上应用的压缩编解码器,您想要多少个文件(或者更确切地说,您想要多大的文件)文件是 - Hive将相应地运行合并)等。

    查看hive.merge.mapfiles下的https://cwiki.apache.org/confluence/display/Hive/Configuration+Propertieshive.merge.mapredfiles(如果您使用TEZ,则为hive.merge.tezfiles)和hive.merge.smallfiles.avgsize,然后hive.exec.compress.output和{{ 1}} - 加上mapreduce.output.fileoutputformat.compress.codec以减少Map容器​​的数量,因为输入文件非常小。


    [*] 这里非常旧的SF引用: - )