rocketMQ如何不丢消息

一、如何判断是不是丢消息了?

不怕丢消息,怕的是丢消息了,却不自知。 name如何探查消息是否丢失呢?

1.分布式链路追踪系统

如果公司的基础技术建设比较完善,完全可以靠分布式链路追踪系统,来分析消息的全链路。
常见有:Cat、Zipkin、Pinpoint、SkyWalking
SkyWalking简介

2.发送有序性消息验证

在 Producer 端,我们给每个发出的消息附加一个连续递增的序号,然后在 Consumer 端来检查这个序号的
连续性。

如果没有消息丢失,Consumer 收到消息的序号必然是连续递增的,或者说收到的消息,
其中的序号必然是上一条消息的序号 +1。如果检测到序号不连续,那就是丢消息了。还可
以通过缺失的序号来确定丢失的是哪条消息,方便进一步排查原因。

  • 使用拦截器机制,不侵入业务代码
    大多数消息队列的客户端都支持拦截器机制,你可以利用这个拦截器机制,在 Producer 发
    送消息之前的拦截器中将序号注入到消息中,在 Consumer 收到消息的拦截器中检测序号
    的连续性,这样实现的好处是消息检测的代码不会侵入到你的业务代码中,待你的系统稳定
    后,也方便将这部分检测的逻辑关闭或者删除。

不保证在 Topic 上的严格顺序的,只能保证分区上的消息是有序的,所以我们在发消息的时候必须要指定分区,并且,在每个分区单独检测消息序号的连续性。

如果你的系统中 Producer 是多实例的,由于并不好协调多个 Producer 之间的发送顺序,
所以也需要每个 Producer 分别生成各自的消息序号,并且需要附加上 Producer 的标识,
在 Consumer 端按照每个 Producer 分别来检测序号的连续性。
Consumer 实例的数量最好和分区数量一致,做到 Consumer 和分区一一对应,这样会比
较方便地在 Consumer 内检测消息序号的连续性。

二、消息发送途径,逐步分析

生产阶段: 在这个阶段,从消息在 Producer 创建出来,经过网络传输发送到 Broker
端。
存储阶段: 在这个阶段,消息在 Broker 端存储,如果是集群,消息会在这个阶段被复制
到其他的副本上。
消费阶段: 在这个阶段,Consumer 从 Broker 上拉取消息,经过网络传输发送到
Consumer 上。

1.消息生产端

  • 在编写发送消息代码时,需要注意,正确处理返回值或者捕获异常,就可以保证这个阶段
    的消息不会丢失。
  • 消息队列的客户端会把消息发送到 Broker,Broker 收到消息后,会给客
    户端返回一个确认响应,表明消息已经收到了。客户端收到响应后,完成了一次正常消息的
    发送。
  • 只要 Producer 收到了 Broker 的确认响应,就可以保证消息在生产阶段不会丢失。有些消
    息队列在长时间没收到发送确认响应后,会自动重试,如果重试再失败,就会以返回值或者
    异常的方式告知用户。
  • 同步发送时,只要注意捕获异常即可。
  • 异步发送时,则需要在回调方法里进行检查。这个地方是需要特别注意的,很多丢消息的原
    因就是,我们使用了异步发送,却没有在回调中检查发送结果。

2.消息存储

  • 如果对消息的可靠性要求非常高,可以通过配置 Broker 参数来避免因为宕机丢消息。

(1)刷盘方式 flushDiskType 配置为 SYNC_FLUSH 同步刷盘

在收到消息后,将消息写入磁盘后再给
Producer 返回确认响应,这样即使发生宕机,由于消息已经被写入磁盘,就不会丢失消
息,恢复后还可以继续消费。

(2)broker为集群模式,配置消息复制

如果是 Broker 是由多个节点组成的集群,需要将 Broker 集群配置成:至少将消息发送到
2 个以上的节点,再给客户端回复发送确认响应。这样当某个 Broker 宕机时,其他的
Broker 可以替代宕机的 Broker,也不会发生消息丢失。

3.消息消费端

不要在收到消息后就立即发送消费确认,而是应该在执行完所有消费业务逻辑之后,再发送消费确认。

客户端从 Broker 拉取消息后,执行用户的消费业务逻辑,成功后,才会给 Broker 发送消费确认响应。如果
Broker 没有收到消费确认响应,下次拉消息的时候还会返回同一条消息,确保消息不会在
网络传输过程中丢失,也不会因为客户端在执行消费逻辑中出错导致丢失。

尾声

未完待续

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容