- 消息发送到 mq 之前先把消息存储到 mysql 中,消息有一个存根避免消息在 mq 中丢失后没地方找这个消息了。
表设计有几个关键字段:
messageId:流水 ID,用来在消息的生产端和消费端串联使用,根据这个 id 找到消费端和生产端唯一的消息;
messageContent:消息内容;
count:发送到 broker 的次数,如果超过特定次数就不往 broker 发送;
status:消息状态,已确认、未确认、已作废,如果消费端已经确认就需要修改该状态。 - 定时扫描 mysql 中未确认的消息,扫描到后重新发送到 broker,如果 count 超过了特定次数就不发送到 broker,避免消息一直消费失败,大量的消息重复发送到 broker ,导致 broker 被垃圾消息填满。
- 消费者消费消息后,如果消费成功则需要回调生产者修改生产者端消息表的状态把状态变成已确认状态,但是这里存在一个问题,回调的时候可能出现问题,导致消息消费成功了,但是状态没改。
- 第 3 点这种情况就会存在消息又会被重新投递到 broker 导致消费者重新消费,这就是消息重复消费问题,这时候消费端必须要有幂等设计,在消费端就需要有本地消息表, 当我们消费消息的时候先查询本地消息表记录,如果能根据 messageId 查询到记录则说明之前消费过就不再消费了,如果没有记录则说明该记录还没有处理过就消费该消息。如果消费成功就往消息表中存该条消息。
- 如果消费者 ACK 失败,但是业务处理成功,那么消息还会存在在 mq 中的,这也会导致重复消费。
- 还有些异常情况,比如消息发送到 mq 成功,插入到本地表中失败,消费者消费成功后插入到本地消息表失败,这些都会存在消息丢失或者重复消费,所以万无一失的做法是生产端和消费端必须要有对账操作,双方对账查找遗漏的业务做人工补偿,人工跑批处理。
如何保证Rabbitmq消息的成功投递
最新推荐文章于 2024-07-10 15:37:29 发布