Java 将少量值从映射器传递到减速器

Java 将少量值从映射器传递到减速器,java,hadoop,Java,Hadoop,如何将在映射器中收集的少量元数据传递给Reducer?在我的具体问题中,我只想传递两个long值,因此我不会对这些值使用MultipleOutputFormat或MultipleOutputs。 我尝试过的一些变体: (一) 映射器 context.getCounter("Countergroup", "Counter").increment(1); counter = context.getCounter("Countergroup", "Counter").getValu

如何将在映射器中收集的少量元数据传递给Reducer?在我的具体问题中,我只想传递两个long值,因此我不会对这些值使用MultipleOutputFormatMultipleOutputs

我尝试过的一些变体:

(一)

映射器

    context.getCounter("Countergroup", "Counter").increment(1);
    counter = context.getCounter("Countergroup", "Counter").getValue(); 
    context.getConfiguration().setInt("Counter", countTotal);
    counter = context.getConfiguration().getInt("Counter", 0);          
减速器

    context.getCounter("Countergroup", "Counter").increment(1);
    counter = context.getCounter("Countergroup", "Counter").getValue(); 
    context.getConfiguration().setInt("Counter", countTotal);
    counter = context.getConfiguration().getInt("Counter", 0);          
计数器不会定期更新,因此Reducer中的函数调用会导致0值



(二)

映射器

    context.getCounter("Countergroup", "Counter").increment(1);
    counter = context.getCounter("Countergroup", "Counter").getValue(); 
    context.getConfiguration().setInt("Counter", countTotal);
    counter = context.getConfiguration().getInt("Counter", 0);          
减速器

    context.getCounter("Countergroup", "Counter").increment(1);
    counter = context.getCounter("Countergroup", "Counter").getValue(); 
    context.getConfiguration().setInt("Counter", countTotal);
    counter = context.getConfiguration().getInt("Counter", 0);          
当然,在运行作业期间不能更改配置(值得一试)

关于这个问题已经有问题了,但我找不到有效的答案。此外,API也发生了变化。我正在使用Hadoop 0.20.2



类似问题:


(这看起来很有希望,但似乎不适用于0.20.2 API)

如果无法使用计数器找到问题的解决方案(在特定情况下将两个长值从mapper传递到reducer),另一种方法可以利用顺序反转模式

在这个模式中,您要做的是从map发出一个额外的键值对,其中键是某物,它成为reducer接收的第一个键(利用reducer按排序顺序接收键的事实)。例如,如果发射的关键帧是1到1000之间的数值。您的虚拟密钥可以是“0”。由于reducer按排序顺序接收密钥,因此保证在处理任何其他密钥之前先处理伪密钥


另外,在新API中还有SetUp()和CloseUp()方法(在旧API中也有类似的方法,但我不记得名称),它们只在每个节点上执行一次,在该节点上的所有map/reduce任务开始/完成之前/之后

如果您无法使用计数器找到问题的解决方案(在特定情况下,将两个长值从映射器传递到reducer),另一种方法可以利用顺序反转模式

在这个模式中,您要做的是从map发出一个额外的键值对,其中键是某物,它成为reducer接收的第一个键(利用reducer按排序顺序接收键的事实)。例如,如果发射的关键帧是1到1000之间的数值。您的虚拟密钥可以是“0”。由于reducer按排序顺序接收密钥,因此保证在处理任何其他密钥之前先处理伪密钥


另外,在新API中还有SetUp()和CloseUp()方法(在旧API中也有类似的方法,但我不记得名称),它们只在每个节点上执行一次,在该节点上的所有map/reduce任务开始/完成之前/之后

这只适用于只有一个减速器的情况。我从OP的问题中了解到的是,这个元数据需要对所有的还原程序都可用,而不仅仅是那些碰巧运气好并获得了特殊密钥的还原程序。如果可以避免数据膨胀,则可以将元数据多路传输到所有键,从而确保每次调用reduce()时都能看到元数据,还可以执行一些额外的二级排序技巧,以确保在迭代组时首先看到元数据值。是的,我同意,只有使用1个reducer时,它才能正常工作,除非数据量大到足以让程序在使用1减速机时变得太慢。否则,您可以发出多个键并编写自定义partioner。我同意发出多个键可能不是很干净,但它与发出每个键值对的元数据并进行二次排序是一种折衷,因为后一种方法会使用大量不必要的内存。释放尽可能多的键,并通过分区器确保每个还原器都有一个副本,并通过自定义比较器确保元数据键优先于所有真正的键;在我当前的解决方案中,这个小技巧很有效。对于额外的第一个记录,我需要找到数据集中肯定永远不会出现的值(至少在这里可以用代码解决),然后在我的排序结构中首先出现。额外的第一个元素可以通过在键中添加布尔值(例如isMetadata)和适当的compareTo()更容易实现只有当你只有一个减速机时,它才起作用。我从OP的问题中了解到的是,这个元数据需要对所有的还原程序都可用,而不仅仅是那些碰巧运气好并获得了特殊密钥的还原程序。如果可以避免数据膨胀,则可以将元数据多路传输到所有键,从而确保每次调用reduce()时都能看到元数据,还可以执行一些额外的二级排序技巧,以确保在迭代组时首先看到元数据值。是的,我同意,只有使用1个reducer时,它才能正常工作,除非数据量大到足以让程序在使用1减速机时变得太慢。否则,您可以发出多个键并编写自定义partioner。我同意发出多个键可能不是很干净,但它与发出每个键值对的元数据并进行二次排序是一种折衷,因为后一种方法会使用大量不必要的内存。释放尽可能多的键,并通过分区器确保每个还原器都有一个副本,并通过自定义比较器确保元数据键优先于所有真正的键;在我当前的解决方案中,这个小技巧很有效。对于额外的第一个记录,我需要找到数据集中肯定永远不会出现的值(至少在这里可以用代码解决),然后在我的排序结构中首先出现。额外的第一个元素可以通过添加bool更容易地实现