消息的可靠传递

本文介绍了如何利用消息队列的有序性检查消息丢失,包括在producer端附加递增序号和在consumer端检测序号连续性。在分布式环境下,需注意消息在topic和分区上的顺序,以及多producer情况下的序号管理和标识。同时,讨论了生产、存储和消费三个阶段的消息可靠性,强调了请求确认机制、配置broker参数以及消费确认的重要性。对于消费阶段,还提到了消息重投和死信队列的处理策略。
摘要由CSDN通过智能技术生成

检查是否丢失消息的方法

我们可以利用消息队列的有序性来检验是否丢失消息:在producer端,我们给每个消息附加一个连续的递增序号,然后在consumer端来检查这个序号的连续性。
如果消息没有丢失,consumer收到消息的序号必然是连续递增的,否则,我们可以通过确实的序号来确定丢失的是哪条消息,方便进一步排查
大多数消息队列的客户端序号注入到消息中,在consumer收到消息的拦截器检测序号的连续性,这样不会入侵代码,也方便这部分检测的逻辑关闭或者删除。

在分布式环境下需要注意以下这几个问题:

首先,像kafka和RocketMQ这样的消息队列,他是不保证在topic上的严格顺序的,只能保证分区上地消息是有序的,索引我们在发送消息的时候必须指定分区,并且每个分区单独检测消息序号的连续性。
如果系统中producer是多例的,由于并不好协调多个producer之间的发送顺序,索引也需要每个producer分别生成各自的消息序号,并且需要附加三个producer的标识,在consumer端按照每个producer分别来检查序号的连续性。

一条消息从生成到消费完的过程,可以分为三个阶段
在这里插入图片描述
如上图所示
生产阶段:消息从producer创建出来,经过网络传输发送到broker
存储阶段:消息在broker存储,如果是集群,消息会在这个阶段被复制到其他副本上
消费阶段:consumer从broker上拉取消息,经过网络传输发送到consumer上。

生产阶段

消息队列通过请求确认机制来确保消息的可靠传递
当你的代码调用发送消息方法是,消息队列的客户端会吧消息发送到broker,broker接收到消息后,给客户端返回一个确认响应,表明消息已经收到了,客户端收到响应以后,完成一次正常的消息发送;
只要producer收到broker的确认响应,就可以确保消息在生产阶段不会丢失,有些对了(如RocketMQ)在长时间没有接收到确认响应后,会自动重试,如果重试失败,就会以返回值或者异常的方式告知用户;
在编写发送消息代码时,需要注意,正确处理返回值或者捕获异常,就可以确保这个阶段的消息不会丢失
以kafka为例:
发送同步消息时,只需要注意捕获异常就可以了
在发送异步消息时,需要在回调方法中检查。

存储阶段

正常情况下,只要broker在正常运行,就不会出现消息丢失的问题,但如果broker出现了故障,比如进程死掉,或者服务器宕机,还是有可能会丢失消息的
如果对消息的可靠性要求非常高,可以通过配置broker参数来避免因为宕机丢失消息
对单个节点的broker,需要配置broker参数,在收到消息后,将消息写入磁盘后再给producer返回确认响应,这样即使宕机,由于消息已经被写入磁盘,就不会丢失,恢复后还可以继续消费
如果broker是由多个阶段组成的集群,需要将broker集群配置成至少将消息发送到两个节点以上再给客户端回复发送确认消息,这样当某个节点broker宕机时,其他节点可以代替宕机的broker,也不会发生消息丢失。

消费阶段

消费阶段采用和生产阶段类似的确认机制来保证消息点的可靠传递,客户端从broker拉取消息后,执行用户的消费业务逻辑,成功后,才会给broker发送消费确认响应
如果broker没有收到消费确认响应,下次拉取消息的时候还会返回同一条消息(重投),确保消息不会再网络传输中丢失,也不会因为客户端再执行消费逻辑中出错导致丢失。
编写代码时需要注意的是,不要在收到消息以后就立即发送消息确认,而是应该在执行完所有业务逻辑以后发送消费确认。

假如某条消息因为某种原因,一直ack失败,一般再重投一定次数以后把消息投放到死信队列中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值