一、RocketMQ的消息丢失问题
1.1、概述
生产环境中为了保证服务的高可用,一般情况下都是采用集群的方式,RocketMQ也不例外,另外现在企业级的开发基本都是分布式+微服务的模式,这就存在着跨网络传输数据的问题,而网络传输不可避免的会出现消息丢失的情况(网络传输不靠谱),这也是RocketMQ消息丢失的主要原因,当然还有其他场景导致消息丢失,具体情况请看下面的分享!
1.2、架构图
1.3、消息丢失的原因
从上边的架构图不难看出,RocketMQ中消息丢失主要发生在以下场景,即:
(一)生产者跨网络传输数据到Broker时发生数据丢失;
(二)Broker集群内部存在master节点向slave节点同步数据时发生数据丢失;
(三)消费者跨网络从Broker消费消息时发生数据丢失;
(四)另外,MQ存盘时也是先写入操作系统的缓存PageCache中,然后再由操作系统异步的将消息写入磁盘,在操作系统将PageCache中的消息写入到磁盘的过程中有个时间差,如果此时恰巧服务宕机,PageCache中的数据还没有来得及写入磁盘中,也会产生消息丢失。
1.4、如何解决消息丢失问题
(一)生产者端不丢失消息解决方案
采用同步方式进行发送,生产者端发送完消息给Broker后,它需要等待Broker的响应,如果Broker返回的状态不是SEND_OK,那么Producer可以进行重试,原理图如下:
对于重要的数据可以采用同步方式,可以做到零丢失数据,但与此同时会影响一部分性能。
(二)存储端不丢失消息解决方案
如果要保证存储端的消息不丢失,确保消息能够持久化到磁盘,可以从刷盘机制进行考虑。刷盘机制分为同步刷盘和异步刷盘,对于异步刷盘来说,只要消息写入PageCache缓存,就返回一个成功的ack响应,这样提高了MQ的性能,但是这时候如果机器恰巧断电了,就会导致刷盘失败,丢失消息。对于同步刷盘来说,生产者消息发过来时,只有消息持久化到磁盘,Broker才会返回一个成功的ack响应,进而保证消息不丢失,但与此同时会影响一部分性能,原理图如下:
同步复制:
另外Broker一般是集群部署的,有master节点和slave从节点,消息到达Broker端,只有主节点和从节点都写入成功,才反馈成功的ack给生产者,这就是同步复制,它保证了消息不丢失,但与此同时会影响一部分性能,原理图如下:
异步复制:
只要主节点写入master成功,就返回成功的ack,速度快是显著的特点,但是存在slave写入失败导致消息丢失的问题,原理图如下:
(三)消费者端不丢失消息解决方案
Consumer先将消息pull到本地,消费完成后再向Broker返回ack,通常消费消息的ack机制一般分为两种思路,分别如下:
a、先提交后消费:可以解决重复消费的问题,但是可能存在消息还没来得及消费然后服务器宕机的情况,导致消息丢失;
b、先消费后提交:需要Consumer通过幂等性的逻辑操作,避免消息被重复消费;