今天咱们来聊聊使用消息队列时经常遇到且让人头疼的消息丢失问题。对于大部分业务系统来说,这可比消息重复的问题严重多了。丢消息意味着数据丢失,这是完全无法接受的。

就拿消费者来说,买了东西,如果因为消息重复给送了 100 万的积分,那可能会很开心。但要是消息丢了,没给奖励,那肯定要出大问题,消费者可能会不断投诉,甚至对整个平台产生怀疑。

其实说到消息丢失,现在主流的消息队列,像 RabbitMQ、Kafka、RocketMQ 等等,都提供了比较完善的消息可靠性保障机制,完全可以做到在消息传递过程中,即使发生网络中断或者硬件故障,也能确保消息可靠传递不丢消息。

虽然不同的消息队列提供的 API 不一样,相关配置项也不同,但实现原理基本一致,都是通过三个阶段来保障。

首先是在消息的生产阶段,消息队列通过常用的请求确认机制来保障消息的可靠传递。当代码调用发消息的方法时,消息队列会把消息发送到 Broker(这是消息存储的地方),Broker 收到消息之后会返回一个确认响应,表明消息已经收到。有些消息队列在长时间没收到确认响应之后,会自动重试做消息补偿,以确保消息能够正常发送到 Broker 中。

其次是在存储阶段,一般消息不会丢,除非出现硬件故障,比如进程挂掉。解决方法很简单,做一些持久化存储,消息队列本身也会提供相应的配置,不用手工写代码处理。就算存储的 Broker 挂掉了,重启之后消息也不会丢,照样可以继续处理。

最后是在消息的消费阶段,跟生产阶段差不多,也是通过 ack 确认机制来确保消息的可靠传递。从 Broker 拉取消息之后发送到消费端处理,处理完成之后给个回调,告知 Broker 已经消费完成。如果 Broker 没有收到消息确认的响应,也会进行消息补偿,再次发送同一条消息,确保消息不会在网络传输过程中丢失。

总结下来,保障消息不丢失的策略也就三条:生产阶段和消费阶段的 ack 确认机制,以及在存储阶段的持久化存储配置。

好了,今天关于消息队列如何解决消息丢失问题的内容就到这里啦,如果您对本期内容有任何疑问,欢迎在评论区给我留言,谢谢大家!