如何确保消息不丢失

1、确保消息的关键点不丢失?

  关键在于两点:消息的持久化,业务系统的幂等性!

 

2、如何检测消息是否丢失?

  1、我们可以利用消息队列的有序性来验证消息是否丢失,在producer端,每发送消息时附带连续的递增序号,在consumer端消费消息时验证消息的序号即可。

    (大部分消息队列支持拦截器机制,可在producer端发消息之前将序号加入消息中,在consumer端在收到消息后的拦截器中对序号进行验证,这样减少了对代码的侵入性)

  2、在分布式系统中,producer和consumer都是集群,producer多实例,需要给每个消息加上对应producer和序号来做唯一性,consumer端验证每个producer的消息连续性即可。

 

3、如何避免消息丢失?

  首先我们看消息从生产到消费的三个阶段:

  

 

  1、生产阶段

  producer生产消息投递到borker,Broker 收到消息后,会给客户端返回一个确认响应,表明消息已经收到了。客户端收到响应后,完成了一次正常消息的发送。

只要broker收到消息后,方能确认消息的不丢失。如果消息队列长时间没有收到确认相应,会进行重试,失败后会以返回值或异常的形式告知用户。

  所以在代码时要注意对异常的捕捉。同步调用注意在发送消息时捕获异常,异步调用注意在回调函数中进行判断。

 

  2、存储阶段

  1)为了保证broker的高可用,会采用集群部署,broker收到消息后,会同步到其它broker,以确保一旦有broker宕机后,避免消息的丢失。

  2)对于单节点的broker,需要配置 Broker 参数,在收到消息后,将消息写入磁盘后再给 Producer 返回确认响应,这样即使发生宕机,由于消息已经被写入磁盘,就不会丢失消息,恢复后还可以继续消费。例如,在 RocketMQ 中,需要将刷盘方式 flushDiskType 配置为 SYNC_FLUSH 同步刷盘。

 

  3、消费阶段

  消费阶段和生产阶段类似的确认方式,consumer接受消息后执行业务逻辑,向broker发送确认消息,则确定一次消费的完成。如果 Broker 没有收到消费确认响应,下次拉消息的时候还会返回同一条消息,确保消息不会在网络传输过程中丢失,也不会因为客户端在执行消费逻辑中出错导致丢失。

  需要注意的点:

      1、consumer一定要在执行完本地业务逻辑后再向broker发送确认消息,以防止本地业务逻辑执行失败

      2、consumer端的业务逻辑一定要保证其幂等性,防止消息重复发送带来业务问题

 

posted @ 2020-02-06 16:33  以梦为码  阅读(466)  评论(0编辑  收藏  举报