针对不同的业务场景,对可靠性的要求也不一样,为了满足各种业务需求,平衡性能与可靠性,Apache Storm提供了三种可靠性级别。
至多一次
这种最为简单,关闭ack机制,不跟踪每一个tuple的处理情况,如果处理失败了就直接忽略。这种策略下,因为不需要监控tuple的执行,Storm能达到最高的性能,所以如果对可靠性没有太高的要求,可以选用这种方式。而且一般来说,即便不启用ack机制,整个系统的运行正确率也很高。
有两种方式来关闭Storm的ACK机制
- spout的emit调用中不指定msgid
- 设置Acker数目为0 Config.TOPOLOGY_ACKERS=0
至少一次
有的场景下,我们要求任务一定要被执行,但是执行了多次不会造成影响,那么就可以采用这个。
这个级别下,Storm会保证每条发出的tuple至少被处理一次。
具体的实现方式就是,在spout的emit调用中指定msgid,然后在下游的每一个bolt中emit时anchor这个tuple msgid,这样每个处理流程就会被绑定在一起,只有当每一道处理流程都正确执行了,整个tuple才算执行成功。此外,还需要重写spout的fail和ack方法,对tuple重新emit,因为Storm没有提供自动重发的机制,所以需要用户自己在spout中记录发出的tuple。
恰好一次
在一些十分严格的场景下,如银行转账等,要求任务必须被恰好执行一次。
单纯依靠Apache Storm的ack机制并不能实现这种要求,一种常见的误区是认为启用了ack机制,然后spout重发,就能够做到了。但是这种考虑忽略了很多点,因为一个任务并不是原子性的,它中间包含了多个tuple,只有这些tuple都被恰好执行一次才能说整个任务被恰好执行了一次,就像转账,第一次减少了A账户的钱后失败了,然后又转了一次,这肯定是不符合要求的。
为了做到这种严格意义上的恰好一次,Storm提供了高级的接口Trident,看过文档,大概就是tuple被组织成batch顺序执行,仅当前一个batch全部完成后一个batch才会执行,分为两种
- Transactional spouts
fail时spout发出与原来一样的tuple,如果无法生成一样的tuple,topology will be halt - opaque transactional spouts
fail时允许发出不一样的tuple,即允许某一个tuple延迟处理
以前做的笔记,大意就是中间bolt记录下自己处理过的tuple,然后再次接受到相同msgid的时候本流程跳过,然后为了提高性能,采取了微批量的模式。