storm是怎么实现高效率的可靠性的?

           理解storm的可靠性的最好的方法是来看看tuple和tuple树的生命周期,当一个tuple被创建,不管是spout还是bolt创建的,它会被赋予一个64位的id,而acker就是利用这个id去跟踪所有的tuple 的。每一个tuple知道它的祖宗的id(从spout发出来的那个tuple的id),每当你新发射一个tuple,它的祖宗id都会传给这个新的tuple。所以当一个tuple 被ack的时候,它会发一个消息给acker,告诉它这个tuple树发生了怎么样的变化。具体来说就是:它告诉acker:我呢已经完成了,我有这些儿子tuple,你跟踪一下他它吧。下面这个图演示了C被ack了之后,这个tuple树所发生的变化。

       

        

      关于storm怎么跟踪tuple还有一些细节,前面已经提到过了,你可以自己设定你的topology里面有多少个acker。而这又给我们带来一个问题,当一个tuple需要ack的时候,它到底选择哪个acker来发送这个信息呢?

      storm使用一致性哈希来把一个spout-tuple-id对应到acker,因为每一个tuple知道它所有的祖宗tuple-id,所以它自然可以算出要通知哪个acker来ack。(这里所有的祖宗是指这个tuple所对应的所有的根tuple。这里注意因为一个 tuple 可能存在于多个tuple树,所以才有所有一说)

      storm的另一个细节是acker是怎么知道每一个spout tuple应该交给哪个task来处理。当一个spout发射一个新tuple,它会简单的发一个消息给一个合适的acker,并且告诉acker它自己的id(taskid),这样storm就有了taskid-tupleid的对应关系。当acker发现一个树完成处理了,它知道哪个task发送成功的消息。

      acker task并不是显式的跟踪tuple 树。对于那些有成千上万个节点的tuple树,把这么多的tuple信息都跟踪起来会耗费太多的内存。相反, acker用了一种不同的方式,使得对于每个spout tuple 所需要的内存量恒定的(20 bytes),这个跟踪算法是storm 如何工作的关键,并且也是它的主要突破。

       一个acker  task存储了一个spout-tuple-id到一对值的一个mapping。这个对子的第一个值是创建这个tuple的taskid,这个是用来在完成处理tuple的时候发送消息用的。第二个值是一个64位的数字称作:“ack val”,ack val是整个tuple树的状态的一个表示,不管这棵数多大。它只能简单地把这棵数上的所有创建的tupleid/ack的tupleid一起异或(XOR)。

      当一个acker task发现一个ack val变成0了,它知道这棵树已经处理完成了。因为tupleid是随机的64位数字,所以,ack val碰巧变成0(而不是因为所有创建的tuple都完成了)的几率极小。算一下就知道了,就算每秒发生10000个ack,那么需要50000000万年才可能碰到一个错误。而且就算碰到一个错误,也只有在这个tuple失败的时候才会造成数据丢失。关于Acker的详细工作流程可以看看这篇文章:Twitter Storm源代码分析之acker工作流程。

      

     既然你已经理解了storm的可靠性算法,让我们一起过一遍所有可能的失败场景,并看看storm在每种情况下是怎么避免数据丢失的。

     1.对由于应的task挂掉了,一个tuple没有被ack:storm的超时机制在超时之后会把这个tuple标记为失败,从而可以重新处理。

     2.Acker挂掉了:这种情况下由这个acker所跟踪的所有spout tuple都会超时,也就会被重新处理 

      3. Spout挂掉了: 在这种情况下给spout发送消息的消息源负责重新发送这些消息。比如Kestrel和RabbitMQ在一个客户端断开之后会把所有”处理中“的消息放回队列。就像你看到的那样, storm的可靠性机制是完全分布式的, 可伸缩的并且是高度容错的。

 调整可靠性 (Tuning Reliability)

       acker task是非常轻量级的, 所以一个topology里面不需要很多acker。你可以通过Strom UI(id: -1)来跟踪它的性能。 如果它的吞吐量看起来不正常,那么你就需要多加点acker了。

       如果可靠性对你来说不是那么重要 — 你不太在意在一些失败的情况下损失一些数据, 那么你可以通过不跟踪这些tuple树来获取更好的性能。不去跟踪消息的话会使得系统里面的消息数量减少一半, 因为对于每一个tuple都要发送一个ack消息。并且它需要更少的id来保存下游的tuple, 减少带宽占用。

        有三种方法可以去掉可靠性。第一是把Config.TOPOLOGY_ACKERS 设置成 0. 在这种情况下, storm会在spout发射一个tuple之后马上调用spout的ack方法。也就是说这个tuple树不会被跟踪。

        第二个方法是在tuple层面去掉可靠性。 你可以在发射tuple的时候不指定messageid来达到不跟粽某个特定的spout tuple的目的。

        最后一个方法是如果你对于一个tuple树里面的某一部分到底成不成功不是很关心,那么可以在发射这些tuple的时候unanchor它们。 这样这些tuple就不在tuple树里面, 也就不会被跟踪了。


     

    












         

 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值