Storm acker的混乱和有保证的消息处理

时间:2016-10-26 10:02:26

标签: apache-storm

现在我正在学习风暴的保证消息处理,并对此部分的一些概念感到困惑。

为了保证spout发出的消息得到完全处理,Storm使用acker来实现这一点。每次喷口发出一个元组时,acker都会分配" ack val"初始化为0以存储元组树的状态。每次这个元组的下游螺栓发出新的元组或ack一个" old"元组,元组ID将与#34; ack val"异或。 acker只需要检查" ack val"是0还是不知道元组已经完全处理。我们来看下面的代码:

public class WordReader implements IRichSpout {
    ... ...
while((str = reader.readLine()) != null){
    this.collector.emit(new Values(str), str);
    ... ...
}

上面的代码片段是来自" Storm入门"教程。在emit方法中,第二个参数" str"是messageId。我对此参数感到困惑: 1)据我了解,每次发出元组(即消息)时,无论是在spout还是在bolt中,Storm都有责任为该消息分配64位messageId。那是对的吗?或者在这里" str"这个消息只是一个人类可读的别名? 2)无论1)的答案是什么,这里" str"在两个不同的消息中将是相同的单词,因为在文本文件中应该有许多重复的单词。如果这是真的,那么Storm如何区分不同的消息?这个参数的含义是什么? 3)在一些代码中,我看到一些spout使用以下代码在Spout emit方法中设置消息Id:

public class RandomIntegerSpout extends BaseRichSpout {
    private long msgId = 0;
    collector.emit(new Values(..., ++msgId), msgId);
}

这更接近我的想法:消息ID应该在不同消息之间完全不同。但对于这段代码,另一个困惑是:私有领域会发生什么?#ms; msgId"跨越不同的执行者?因为每个执行程序都有自己的msgId初始化为0,所以不同执行程序中的消息将从0,1,2等命名。那么Storm如何区分这些消息?

我是Storm的新手,所以也许这些问题很天真。希望有人能帮助我弄明白。谢谢!

1 个答案:

答案 0 :(得分:0)

关于消息ID是通用的:在内部它可能是64位值,但是这个64位值是根据Spout中msgID中提供的emit()对象计算的。因此,您可以将任何对象作为消息ID(两个对象散列到相同值的概率接近于零)。

关于使用str:我认为在这个示例中,str包含一行(而不是一个单词),并且文档不太可能包含两次完全相同的行(如果没有空可能很多的行。)

关于计数器作为消息ID:你绝对正确的观察 - 如果多个spout并行运行,这将导致消息ID冲突并且会破坏容错。

如果你想"修复"计数器方法,每个计数器应该以不同方式初始化(​​最好,来自1...#SpoutTasks)。您可以使用taskID(这是唯一的,可以通过TopologyContext中提供的Spout.open()访问)。基本上,您获得所有并行喷口任务的所有taskID,对它们进行排序,并为每个喷口任务分配其订购号。此外,您需要增加"平行喷口的数量"而不是1