现在我正在学习风暴的保证消息处理,并对此部分的一些概念感到困惑。
为了保证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的新手,所以也许这些问题很天真。希望有人能帮助我弄明白。谢谢!
答案 0 :(得分:0)
关于消息ID是通用的:在内部它可能是64位值,但是这个64位值是根据Spout中msgID
中提供的emit()
对象计算的。因此,您可以将任何对象作为消息ID(两个对象散列到相同值的概率接近于零)。
关于使用str
:我认为在这个示例中,str
包含一行(而不是一个单词),并且文档不太可能包含两次完全相同的行(如果没有空可能很多的行。)
关于计数器作为消息ID:你绝对正确的观察 - 如果多个spout并行运行,这将导致消息ID冲突并且会破坏容错。
如果你想"修复"计数器方法,每个计数器应该以不同方式初始化(最好,来自1...#SpoutTasks
)。您可以使用taskID(这是唯一的,可以通过TopologyContext
中提供的Spout.open()
访问)。基本上,您获得所有并行喷口任务的所有taskID,对它们进行排序,并为每个喷口任务分配其订购号。此外,您需要增加"平行喷口的数量"而不是1
。