如何避免消息丢失

128 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情

前言

上篇文章说明了如何检测消息丢失,现在继续说明,如何保证消息的不丢失。

消息发送到消息消费的阶段

首先消息整个生命周期过程是:生产者(Producer)产生消息,发送至消息队列(Broker),消费者(Consumer)从消息队列拉取消息消费。

graph TD
生产者  --> 消息队列 --> 消费者

清楚这个流程后,就能很清楚的知道需要在每个阶段都分别保证消息的可靠传递。

如果避免消息丢失

生产者->消息队列

消息从生产者端创建,通过传输消息到消息队列,消息队列收到消息后,会发送ACK给生产者端,表示已经成功收到消息,这样一次完整的消息从生产者发送到消息队列就算结束。

这个阶段要保证消息的可靠传输,需要从消息的确认机制入手。只要保证生产者成功收到了ACK,则代表成功,如果未收到ACK,或者消息队列返回失败或者异常,则触发重试机制,消息会重新发送,如果再次失败,则需将错误结果返回应用端处理。

如果是同步发送消息,代码需要做异常捕获,在catch块中处理消息发送失败的逻辑; 如果是异步发送消息,代码需要在方法回调处做消息发送失败的处理逻辑。

消息队列

消息队列端需要配置参数为接收到消息并成功写入磁盘后再返回生产者端ACK消息,这样可以避免在接收消息后,未写入磁盘就发生宕机,导致消息丢失。

对于集群部署环境的消息队列,则需配置当消息发送至2个或2个以上节点时,再返回ACK信息,这样可以保证一个节点宕机之后,其他节点已保存消息数据,可以替代服务。

消息队列—>消费者

这个阶段需要令消费者成功消费消息后(保存数据库或者业务逻辑处理完成后),再发送ACK至消息队列。如果中间发生异常导致消息消费失败,则在下次拉取消息时,还会重新拉取失败的消息再次消费。

总结

主要需要在以下三个阶段去避免消息丢失: 生产者阶段:需要异常捕获消息发送的错误,发生错误时重试消息发送。 消息队列阶段:配置消息成功写入磁盘后,或者消息成功发送至2个或2个以上节点时,再返回ACK。 消费者阶段:在处理完业务逻辑后再发送消费确认。