我想将Map器输出的一部分写入一个文件夹,比如hdfs中的文件夹a。输出的另一部分,我希望它由减速机处理。这可能吗?我知道有多种输出。是否可以使用多个输出?谢谢!
lh80um4z1#
您可以直接从Map器实现将输出写入hdfs—只需使用上下文的配置创建一个文件系统对象,然后创建一个文件,写入其中并记住关闭它:
public void cleanup(Context context) { FileSystem fs = FileSystem.get(context.getConfiguration()); PrintStream ps = new PrintStream(fs.create( new Path("/path/to/output", "map-output"))); ps.println("test"); ps.close(); }
需要考虑的其他事项-每个文件都需要在hdfs中唯一命名,因此可以用Map器id号作为文件名的后缀,但是您还需要考虑推测性执行(因为Map器任务示例可能在两个位置运行-两个位置都试图在hdfs中写入同一个文件)。当输出提交者在tmp hdfs目录中创建带有任务id和尝试编号的文件时,通常会将其抽象出来,只会在提交该任务尝试时将其移动到正确的位置和文件名。在运行map-side(将数据写入本地文件系统)时,如果不关闭推测性执行或在hdfs中创建多个文件(每次尝试一个),就无法解决此问题。因此,更“完整”的解决方案如下所示:
FileSystem fs = FileSystem.get(context.getConfiguration()); PrintStream ps = new PrintStream(fs.create(new Path( "/path/to/output", String.format("map-output-%05d-%d", context.getTaskAttemptID().getTaskID().getId(), context.getTaskAttemptID().getId())))); ps.println("test"); ps.close();
multipleoutputs可以帮助您减少side,但我不认为map side可以工作,因为没有输出提交程序,工作目录也不在hdfs中。当然,如果这只是一个Map器的工作,那么多次输出就可以了。因此,另一种方法是运行一个只Map的作业,然后在第二个作业中使用所需的输出部分(使用身份Map器)-这取决于您移动的数据量。
68bkxrlz2#
是的,可以使用multipleoutputs,根据docs,在map阶段通过multipleoutputs传递的任何输出都会被reducer忽略,所以这正是您想要的。我在github上写了一个小例子,希望你会发现它很有用。
2条答案
按热度按时间lh80um4z1#
您可以直接从Map器实现将输出写入hdfs—只需使用上下文的配置创建一个文件系统对象,然后创建一个文件,写入其中并记住关闭它:
需要考虑的其他事项-每个文件都需要在hdfs中唯一命名,因此可以用Map器id号作为文件名的后缀,但是您还需要考虑推测性执行(因为Map器任务示例可能在两个位置运行-两个位置都试图在hdfs中写入同一个文件)。
当输出提交者在tmp hdfs目录中创建带有任务id和尝试编号的文件时,通常会将其抽象出来,只会在提交该任务尝试时将其移动到正确的位置和文件名。在运行map-side(将数据写入本地文件系统)时,如果不关闭推测性执行或在hdfs中创建多个文件(每次尝试一个),就无法解决此问题。
因此,更“完整”的解决方案如下所示:
multipleoutputs可以帮助您减少side,但我不认为map side可以工作,因为没有输出提交程序,工作目录也不在hdfs中。
当然,如果这只是一个Map器的工作,那么多次输出就可以了。因此,另一种方法是运行一个只Map的作业,然后在第二个作业中使用所需的输出部分(使用身份Map器)-这取决于您移动的数据量。
68bkxrlz2#
是的,可以使用multipleoutputs,根据docs,在map阶段通过multipleoutputs传递的任何输出都会被reducer忽略,所以这正是您想要的。我在github上写了一个小例子,希望你会发现它很有用。