MQ消息队列的消息的不重不漏问题

版权声明:本文为CSDN博主「证心」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xuelang1478/article/details/90175695

一个完美的消息队列,应该做到消息的“不重不漏”,这里面包含了4重语义:

  • 消息不会重复存储;
  • 消息不会重复消费;
  • 消息不会丢失存储;
  • 消息不会丢失消费。

重复存储

发送者发送一个消息之后,服务器返回超时了。那请问,这条消息是存储成功了,还是没有呢?

所以生产者必须持有一个消息表,记录消息的发送状态,对于超时未确认的消息要再查询确认,否则无法保证不重复发送重复存储。

一般重复发送问题是不去解决的,都是在消息端做判重表来解决重复问题。

重复消费

一种是生产者就是重复发的消息,所以消息重了。

另一种是消息者消息完消息还没向MQ确认挂了,再重启还是有这个消息。

一般消费者需要根据业务ID做判重表,消息过的就不再消费。

丢失存储

如果MQ支持ACK,那生产者在收到MQ的确认后一般认为存储成功。

但也有极少情况会丢失消息,最极端情况:

操作系统本身是有page cache的。即使我们用无缓冲的io,消息也不会立即落到磁盘上,而是在操作系统的page cache里面。操作系统会控制page cache里面的内容,什么时候写回到磁盘。在应用层,对应的就是fsync函数。我们可以指定每条消息都调用一次fsync存盘,但这会较低性能,也增大了磁盘IO。

一般是不会一条消息做一次磁盘IO的,这样性能太差,所以想完全不丢失消息生产者可以持有消息表,最后和消费者对账。

对账是因为生产者收到消息确认,但消息丢失了,需要和消费者对账才能找出丢失的消息。

丢失消费

消息被消费,但还没被确认消费者就挂了,所以消息还是在MQ中。

需要判重表解决,在消费者重启后消息被判重过滤掉。

posted @ 2019-12-06 19:23  逐梦客!  阅读(551)  评论(0)    收藏  举报