如何确保消息不会丢失

Monday, August 5, 2019

检测消息丢失的方法

利用消息队列的有序性来验证是否有消息丢失

原理很简单,在Producer端,我们给每个发送的消息附加一个连续递增的序号,然后在Consumer端检查连续性即可。

我们可以在消息队列的客户端中,利用拦截器机制来加入上述操作,这样不会侵入到业务代码中。

有几个问题需要注意

  • 比如Kafka和RocketMQ,它是不保证Topic的严格顺序的,只能保证分区(队列)上的消息是有序的,所以发送消息的时候必须指定分区,在每个分区单独检测有序性
  • 如果Producer是多实例的,并不好协调多个Producer之间的发送顺序,所以要在每个Producer分别生成各自的消息序号,附加Producer标识
  • Consumer实例的数量最好和分区数量一致,做到一一对应,这样方便在Consumer内检测消息序号的连续性

确保消息可靠传递

我们需要了解,整个消息从生产到消费,到底有哪些环节会导致丢消息,该如何应对

file

  • 生产阶段:从Producer生成出来,发送到Broker
  • 存储阶段:消息在Broker存储,如果是集群,会被复制到其他副本上
  • 消费阶段,Consumer从Broker拉取消息

生产阶段

通常使用确认请求机制,来确保消息传递成功,在编写发送消息代码时,需要注意,正确处理返回值或者捕获异常,就可以保证这个阶段消息不会丢失。

存储阶段

正常情况下,只要Broker在正常运行,就不会丢失消息,但是如果Broker出现故障,还是可能会丢失消息的。

如果对消息的可靠性要求非常高,则可以通过配置Broker参数来避免因为宕机丢消息。比如配置Broker,在收到消息后,将消息写入磁盘后再给Producer响应。如果时集群Broker,则可以将Broker集群配置成,至少将消息发送到两个以上的节点,再给客户端发送确认响应。

消费阶段

与生产阶段类似,也是才用确认请求机制来保证消息的可靠传递,但是我们可以注意的一点是: 不要收到消息后立刻发送消费确认,而是应该在执行完所有消费业务逻辑之后,再发送消费确认。

消息队列

Linux 常用操作详解

利用事务消息实现分布式事务