一、简介
Storm 可以保证 spout 发出的每条消息都能被“完全处理” ,这也是直接区别于其他实时系统的地方,如 S4。
请注意,spout 发出的消息后续可能会触发产生成千上万条消息 ,可以形象的理解为一棵消息树, 其中 spout 发出的消息为树根, Storm会跟踪这棵消息树的处理情况, 只有当这棵消息树中的所有消息都被处理了,Storm 才会认为 spout 发出的这个消息已经被“完全处理” 。如果这棵消息树中的任何一个消息处理失败了, 或者整棵消息树在限定的时间内没有“完全处理” ,那么 spout 发出的消息就会重发。
二、理解消息被完整处理
一个消息(tuple)从 spout 发送出来, 可能会导致成百上千的消息 基于此消息被创建
以“单词统计”为例:它的消息可分裂为多个消息,这些消息构成一个树状结构,被称为“tuple tree”,如图
当下面的条件同时被满足,Storm 才会认为一个从 spout 发送出来的消息被完整处理.
-
- tuple tree 不再生长
- 树中的任何消息被标识为“已处理”
如果在指定的时间内,一个消息衍生出来的 tuple tree 未被完全 处理成功,则认为此消息未被完整处理。这个超时值可以通过任务级 参数Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS 进行配置,默认超时 值为30秒。
二、原理
考虑到尽可能减少对内存的消耗,Storm 并不会跟踪消息树中的每个消息,而是采用了一些特殊的策略,它把消息树当作一个整体来跟踪,对消息树中所有消息的唯一 id 进行异或计算,通过是否为零来判定 spout 发出的消息是否被“完全处理” ,这极大的节约了内存和简化了判定逻辑。
上面所说的,Storm 保证了每个消息至少被处理一次,但是对于有些计算场合,会严格要求每个消息只被处理一次,幸而 Storm 的0.7.0引入了事务性拓扑,解决了这个问题,后面会有详述。
三、注意
这种模式,每发送一个消息,都会同步发送一个ack/fail,对于网络的带宽会有一定的消耗,如果对于可靠性要求不高,可通过使用不同的 emit 接口关闭该模式。