RocketMQ消息丢失解决方案:同步刷盘+手动提交
前言
之前我们一起了解了使用RocketMQ事务消息解决生产者发送消息时消息丢失的问题,但使用了事务消息后消息就一定不会丢失了吗,肯定是不能保证的。
因为虽然我们解决了生产者发送消息时候的消息丢失问题,但也只是保证Broker正确的接收到了消息,实际上接收到的消息会保存在os cache中,如果此时broker机器突然宕机,os cache中的消息数据就丢失掉了。
而且就算是os cache中的消息已经刷盘到了磁盘中,如果磁盘突然就坏了,消息是不是也就丢失了。
所以我们还要考虑Broker如何保证消息不丢失。
Broker的消息丢失解决方案
说到这里,我们就进入主题了,首先解决临时存在os cache,而未刷新到磁盘导致的消息丢失问题,那么如何解决呢?
看过之前系列文章的小伙伴都知道,Broker是有两种刷盘机制的,同步刷盘和异步刷盘,详细内容可以回顾一下这篇文章:深入研究Broker是如何持久化的。
解决的方式就是把异步刷盘改为同步刷盘,具体操作就是修改一下broker的配置文件,将其中的flushDiskType配置设置为:SYNC_FLUSH,默认它的值是ASYNC_FLUSH,即异步刷盘。
调整为同步刷盘后,只要MQ告诉我们消息发送成功了,那么就说明消息已经在磁盘中了。
接下来就要解决磁盘坏了导致的消息丢失问题了。
这个问题其实也很好解决,只要我们使用RockerMQ的高可用集群模式就可以了,也就是说如果返回消息发送成功的响应,那就代表Master Broker已经把数据同步到了Slave Broker中,保证数据有多个备份。
这样一来就算是Master Broker突然宕机 ,也可以通过Dledger技术进行主从的自动切换,使用我们备份的数据,这其中的原理我们已经讲过了,小伙伴们可以自己去复习回顾一下。Dledger是如何实现主从自动切换的
Consumer的消息丢失解决方案
到这里,我们已经确保了生产者和Broker的消息不会丢失了,那么消费者处理消息的时候会不会导致消息丢失呢?
答案是肯定的。
比如说我们的积分系统拿到了消息,还未执行该执行的操作,先返回给broker这条消息的offset,说这条消息已经处理过了。然后突然宕机了,这就导致mq认为这条消息已经处理过了,而实际并没有处理,所以这条消息就丢失掉了。
对于Kafka和RabbitMQ来讲,默认的消费模式就是上边这种自动提交的模式,所以是有可能导致消息丢失掉的。
而RocketMQ的消费者有点不一样,它本身就是需要手动返回消息处理成功的响应的。
所以其实Consumer的消息丢失解决方案也很简单,就是将自动提交改为手动提交。
消息零丢失方案的优缺点分析
如果在系统中落地一套消息零丢失的方案,无论什么场景都保证消息的可靠性,这似乎听起来不错,这也是它的优点所在,保证系统的数据都是正确的,不会有丢失的情况。
但它有什么缺点呢?
首先,引入了这套解决方案之后,系统的复杂度变高了,想想事务消息的实现方式你肯定会这么觉得。
而且比较严重的缺点是,它会导致系统的性能严重的下降,比如原来每秒可以处理好几万条的消息,结果在引入消息零丢失这套方案之后,可能每秒就只能处理几千条消息了。
其实只要随便思考一下,就可以想明白这个问题。
事务消息的复杂性导致生产消息的过程耗时更久了,同步刷盘的策略导致写入磁盘后才返回消息,自然也会增加耗时,而消费者如果异步的处理消息,直接返回成功,整个流程的速度会更快。
所以说引入这么一套消息零丢失的方案,对于性能的影响还是很大的。
总结
其实关于消息零丢失的方案无外乎就这么多,所以本篇文章内容不是很多。
既然我们刚才聊了消息零丢失方案的缺点,那么就继续讨论一下,究竟什么场景下需要引入这套方案吧。
王子给大家介绍一下自己的想法。
一般我们对于跟金钱、交易以及核心数据相关的系统和核心链路,可以采用这套方案。
比如说我们文章中举的例子:支付系统、订单系统、积分系统。
而对于其他的没那么核心的场景,丢失一些数据问题也不大,就不应该采用这套方案了,或者说可以做一些简化,比如事务消息改成失败重试几次的机制,刷盘策略改为异步刷盘。
那么小伙伴们在平时的工作中,这套方案是怎么应用到生产环境中的呢?欢迎留言讨论。
往期文章推荐:

RocketMQ消息丢失解决方案:同步刷盘+手动提交的更多相关文章
- RocketMQ消息丢失解决方案:事务消息
前言 上篇文章,王子通过一个小案例和小伙伴们一起分析了一下消息是如何丢失的,但没有提出具体的解决方案. 我们已经知道发生消息丢失的原因大体上分为三个部分: 1.生产者发送消息到MQ这一过程导致消息丢失 ...
- RocketMQ 消息丢失场景分析及如何解决
生产者产生消息发送给RocketMQ RocketMQ接收到了消息之后,必然需要存到磁盘中,否则断电或宕机之后会造成数据的丢失 消费者从RocketMQ中获取消息消费,消费成功之后,整个流程结束 1. ...
- 探秘 RocketMQ 消息持久化机制
我们知道 RocketMQ 是一款高性能.高可靠的分布式消息中间件,高性能和高可靠是很难兼得的.因为要保证高可靠,那么数据就必须持久化到磁盘上,将数据持久化到磁盘,那么可能就不能保证高性能了. Roc ...
- 【RocketMQ】消息的刷盘机制
刷盘策略 CommitLog的asyncPutMessage方法中可以看到在写入消息之后,调用了submitFlushRequest方法执行刷盘策略: public class CommitLog { ...
- RabbitMQ,RocketMQ,Kafka 事务性,消息丢失和消息重复发送的处理策略
消息队列常见问题处理 分布式事务 什么是分布式事务 常见的分布式事务解决方案 基于 MQ 实现的分布式事务 本地消息表-最终一致性 MQ事务-最终一致性 RocketMQ中如何处理事务 Kafka中如 ...
- Rocket重试机制,消息模式,刷盘方式
一.Consumer 批量消费(推模式) 可以通过 consumer.setConsumeMessageBatchMaxSize(10);//每次拉取10条 这里需要分为2种情况 Consumer端先 ...
- 面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!
最近看了 @JavaGuide 发布的一篇『面试官问我如何保证Kafka不丢失消息?我哭了!』,这篇文章承接这个主题,来聊聊如何保证 RocketMQ 不丢失消息. 0x00. 消息的发送流程 一条消 ...
- rocketmq刷盘过程
本文基于rocketmq4.0版本,结合CommitlLog的刷盘过程,对消息队列的刷盘过程源码进行分析,进而对RocketMQ的刷盘原理和过程进行了解. rocketmq 4.0版本中刷盘类型 ...
- RocketMQ中Broker的刷盘源码分析
上一篇博客的最后简单提了下CommitLog的刷盘 [RocketMQ中Broker的消息存储源码分析] (这篇博客和上一篇有很大的联系) Broker的CommitLog刷盘会启动一个线程,不停地 ...
随机推荐
- Java Web学习(十一)Java过滤器
一.引言 上一篇文章学习了java三大器的拦截器,拦截器主要是针对于action请求进行拦截处理的,那么对于requst的一些信息如果在调用前,想先进行过滤和处理,那么就要使用到第二个神器,也就是本文 ...
- gcc g++ 安装与配置 入门详解 - 精简归纳
gcc g++ 安装与配置 入门详解 - 精简归纳 JERRY_Z. ~ 2020 / 9 / 24 转载请注明出处!️ 目录 gcc g++ 安装与配置 入门详解 - 精简归纳 一.下载MinGW ...
- 利用Z.Expressions.Eval表达式求值
Z.Expression.Eval是一个开源的(OpenSource),可扩展的(Extensible),超轻量级(Super lightweight)的公式化语言解析执行工具包. 使用方法:1.从n ...
- mysql load_file()
本地mysql注入读取配置文件 遇到的问题 简单记录一下. 本地测试时,读取文件发现无论怎样都返回为NULL. >> select load_file('c:/xx/xx/xx/x.txt ...
- OSPF及实验
OSPF:Open Shortest Path First,最短路径优先1)基本概念:标准的LS型协议--共享拓扑组播更新:224.0.0.5/6触发更新,存在周期更新 30minOSPF是跨层封装 ...
- ARM架构下的Docker环境,OpenJDK官方没有8版本镜像,如何完美解决?
为什么需要ARM架构下的OpenJDK8的Docker镜像? 对现有的Java应用,之前一直运行在x86处理器环境下,编译和运行都是JDK8,如今在树莓派的Docker环境运行(或者其他ARM架构电脑 ...
- JUC并发编程--AQS
转自: https://www.jianshu.com/p/d8eeb31bee5c 前言 在java.util.concurrent.locks包中有很多Lock的实现类,常用的有Reentrant ...
- Java知识系统回顾整理01基础06数组02初始化数组
一.分配空间与赋值分步进行 分配空间与赋值分步进行 public class HelloWorld { public static void main(String[] args) { int[] a ...
- c++中sprintf和sprintf_s的区别
参考:https://blog.csdn.net/qq_37221466/article/details/81140901 sprintf_s是sprintf的安全版本,指定缓冲区长度来避免sprin ...
- 对ACE和ATL积分
下载source code - 39.66 KB 介绍 这篇文章展示了一种结合ACE和ATL的方法.它不打算作为功能演示,而是作为一个小型的"入门"解决方案,展示实现此目标的可行方 ...