作业更新另一个作业的输出的最佳方式

时间:2015-04-01 18:21:39

标签: java hadoop mapreduce distributed-computing avro

这是我的情景。我有一份处理大量csv数据的工作,并使用Avro将其写入按日期划分的文件中。我得到了一个小文件,我希望用它来更新其中一些文件,其中包含第二个作业,我可以在需要时运行,而不是再次重新处理整个数据集。

以下是这个想法的样子:

  • Job1:处理大量csv数据,将其写入按输入日期拆分为文件的压缩Avro文件中。源数据不按日期划分,因此此作业将执行此操作。
  • Job2(在Job1运行之间根据需要运行):处理小型更新文件并使用此文件将条目添加到适当的相应Avro文件中。如果它不存在则创建一个新文件。
  • Job3(始终运行):从Job1的输出(可能还有Job 2)生成一些报告指标。

所以,我必须这样写Java作业。我的第一份工作似乎工作正常。我也不确定如何接近工作2.

这就是我的想法:

  • 使用分布式缓存传递更新文件。将此文件解析为 在Job类中生成一个日期列表,并使用它来过滤 Job1中的文件将作为此作业的输入。
  • 在映射器中,访问分布式更新文件并将其添加到我读过的我的avro对象集合中。如果该文件尚不存在,该怎么办?这有用吗?
  • 使用Reducer编写新的对象集合

这是一个如何实现这个?如果不是更好的方法是什么?合成器在这里有意义吗?我觉得答案是肯定的。

提前致谢。

3 个答案:

答案 0 :(得分:3)

您可以按照以下方法:

1)在所有csv文件上运行job1

2)在小文件上运行job2并创建新输出

3)对于更新,您需要再运行一个作业,在此作业中,在setup()方法中加载job2的输出,并将job1的输出作为map()输入。然后编写更新逻辑并生成最终输出。

4)然后运行你的job3进行处理。

据我所知,这将有效。

答案 1 :(得分:2)

只是一个疯狂的想法:为什么你需要实际更新job1输出?

  • JOB1为日期生成一个文件。为什么不添加像随机UUID这样的独特后缀?
  • JOB2流程'更新'信息。也许好几次。输出文件命名的逻辑是相同的:基于日期的名称和唯一的后缀。
  • JOB3收集JOB1和JOB2输出,按日期前缀将它们分组为所有后缀并作为输入。

如果基于日期的分组是目标,那么在这里你有很多优点,显而易见的是:

  • 如果您在此日期有JOB1的输出,那么您并不在意。
  • 如果您需要使用多个JOB2结果更新一个JOB1输出,您甚至不在乎。
  • 你没有打破HDFS方法,没有文件更新'具有“一次写入”功能的限制。直截了当的处理。
  • 您的JOB3只需要一些特定的InputFormat。看起来不那么复杂。
  • 如果您需要合并来自不同来源的数据,没问题。
  • JOB3本身可以忽略从多个来源接收数据的事实。 InputFormat应该小心。
  • 可以以相同的方式组合多个JOB1输出。

限制:

  • 这可能会产生比大型数据集和多次传递更多的小文件。
  • 您需要自定义InputFormat

至于我的好选择,如果我能正确理解你的情况,你可以/需要按日期将文件分组作为JOB3的输入。

希望这会对你有所帮助。

答案 2 :(得分:1)

对于Job2,您可以读取更新文件以过滤驱动程序代码中的输入数据分区,并将其设置在输入路径中。您可以按照当前方法读取更新文件作为分发缓存文件。如果您想要在无法读取更新文件时使作业失败,请在安装方法本身中抛出异常。

如果更新逻辑不需要在reduce端进行聚合,则将Job2设置为仅映射作业。您可能需要构建逻辑以在Job3中识别更新的输入分区,因为它将接收Job1输出和Job2输出。