RabbitMQ 和 Kafka 的消息可靠性对比

RabbitMQ和Kafka都提供持久的消息保证。两者都提供至少一次和至多一次的保证,另外,Kafka在某些限定情况下可以提供精确的一次(exactly-once)保证。

让我们首先理解一下上述术语的含义:

至多一次投递:消息绝对不会被重复投递,但是消息可能丢失

至少一次投递:消息绝对不会被丢失,但是有可能重复被消费

精确的一次投递:消息系统的圣杯。所有的消息精确的被投递一次。

“投递”貌似不是准确的语言描述,“处理”才是。无论怎么描述,我们关心的是,消费者能否处理消息,以及处理的次数。但是使用“处理”会使问题变得复杂。比如说,消息必须投递两次才能被处理一次。再比如,如果消费者在处理的过程中宕机,消息必须被第二次投递(给另一个消费者)。

其次,使用“处理”来表达会使得部分失败(partial failure)变得头疼。处理消息一般包括多个步骤。处理的开始到结束包括应用的逻辑以及应用与消息系统的通信。应用逻辑的部分失败由应用来处理。如果应用处理的逻辑是事务的,结果是all or nothing, 那么应用逻辑可以避免部分失败。但是实际上,多个步骤往往涉及不同的系统,使得事务性变得不可能。如果我们考虑到通信,应用,缓存,数据库,我们无法达到精确的一次处理(exactly-once processing).

所以,精确地一次只出现在如下情况中:消息的处理只包括消息系统本身,并且消息系统本身的处理是事务的。在该限定场景下,我们可以处理消息,写消息,发送消息被处理的ACK, 一切都在事务中。而这正是Kafka流能提供的。

但是,如果消息处理是幂等(idempotent)的,我们就可以绕过基于事务的精确一次保证。如果消息处理是幂等的,我们可以安全的处理重复的消息。当然,并不是所有的消息处理都是幂等的。

 

责任链

本质上讲,生产者不能知道消息是否被消费。他们能知道的是,消息系统是否接收了消息,是否把消息安全的存储起来以便投递。这里存在一条责任链,开始于生产者,移动到消息系统,最后到达消费者。每个环节都要正确执行,环节间的交接也要正确执行。这意味着,作为一个应用开发者,你要正确的写程序,防止丢失消息,或者滥用消息。

消息顺序

这篇文章主要关注RabbitMQ和Kafka如何提供至少一次和至多一次的投递。但是,也包括消息的顺序。简单来讲,两者都支持FIFO顺序。RabbitMQ在队列这个层次,Kafka在话题的分区层次。

RabbitMQ

投递保证依赖于:

消息的持久性——一旦存储下来,就不会丢失

消息的ACK——RabbitMQ与生产者、消费者之间的信号

队列镜像

队列可以在节点间被镜像(复制)。对于每个队列,存在一个主队列,在单独一个节点上。假设我们有3个节点,10 个队列,每个队列2个镜像。那么10个主队列和20个镜像将分布在3个节点间。主队列如何分布是可以被配置的。当一个节点宕机后,

在宕机的节点上的每一个主队列,在另一个节点上的镜像队列会被提升为主队列

在其他节点上的镜像队列会被创建出来,以代替

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值