一、MQ会产生消息丢失的场景

1.1 生产者到MQ阶段
生产者发送消息到MQ,单纯的这种操作并不能保证MQ确实收到消息。
另外,比如生产者端是在进行远程调用的情况,那么本地事务是否操作成功,MQ并不得知。
begin:
发送消息;
本地数据库操作;
commit;
如果本地数据库操作失败回滚,但是消费者端操作成功,会导致数据不一致。
1.2 MQ主从数据同步阶段
MQ接收到消息,进行主从同步的时候失败,则会导致主从数据不一致,造成消息丢失。
1.3 MQ数据刷盘持久化阶段
MQ还未进行消息持久化宕机,造成消息丢失
1.4 MQ到消费者阶段
消费者拉取消息之后,执行失败,或者MQ消息发送失败都会导致消息丢失。
二、解决方案
2.1 生产者到MQ阶段
kafka:消息发送 + 回调 (MQ收到消息之后进行回复)
- 优点:能够保证生产者端到MQ的消息发送不丢失
- 缺点:在MQ回复期间,生产者阻塞
RocketMQ:1. 消息发送 + 回调 2. 事务消息
这里重点说一下事务消息,过程如下:
- 生产者(MQ发送方)向MQ发送一个Half消息,确认MQ当前状态
- MQ回复Half消息确认,回复消息发送是OK的
- 生产者执行本地事务
- 生产者事务执行之后,发送commit或 rollback到MQ
- 如果是commit,则MQ向消费者投递消息
- 如果是rollback,则MQ丢弃该消息
- 如果生产者方在执行事务时挂掉,或超时,MQ会不停的询问同组其他生产者来获取事务的执行状态,也就是事务回查
- 后续就是生产者检查本地事务状态,然后再进行第四步的操作
事务消息的方式,能够保证本地事务和消息投递这块是原子性的操作。那么,到消息被消费者消费这里又可以利用消费者执行成功的确认返回来保证消费者正确消费消息,保证数据一致性。
2.2 MQ主从复制阶段
主从同步
- 同步同步:生产者发送消息到MQ主节点,主节点立刻进行主从同步,等到同步完成之后,再向生产者发送确认消息。整个过程中生产者是阻塞的。
- 异步同步:生产者发送消息到MQ主节点,主节点立刻返回确认消息,然后异步进行主从同步。(但存在异步主从同步过程消息丢失的可能)
2.3 MQ消息存盘阶段
同步刷盘和异步刷盘。同上面一样的道理,异步刷盘存在消息丢失的可能。
2.4 MQ到生产者阶段
同步和异步,当然优缺也和上面说的一样。但此处还是建议同步较好。
版权声明:本文为qq_44760601原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。