面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!

摘要:
最近看了@JavaGuide发布的一篇『面试官问我如何保证Kafka不丢失消息?我哭了!』,这篇文章承接这个主题,来聊聊如何保证RocketMQ不丢失消息。若想保证Broker端不丢消息,保证消息的可靠性,我们需要将消息保存机制修改为同步刷盘方式,即消息存储磁盘成功,才会返回响应。如果Broker未收到消费确认响应或收到其他状态,消费者下次还会再次拉取到该条消息,进行重试。

最近看了@JavaGuide发布的一篇『面试官问我如何保证Kafka不丢失消息?我哭了!』,这篇文章承接这个主题,来聊聊如何保证 RocketMQ 不丢失消息。

0x00. 消息的发送流程

一条消息从生产到被消费,将会经历三个阶段:

面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!第1张

生产阶段,Producer 新建消息,然后通过网络将消息投递给 MQ Broker存储阶段,消息将会存储在 Broker 端磁盘中消息阶段, Consumer 将会从 Broker 拉取消息以上任一阶段都可能会丢失消息,我们只要找到这三个阶段丢失消息原因,采用合理的办法避免丢失,就可以彻底解决消息丢失的问题。

0x01. 生产阶段

生产者(Producer) 通过网络发送消息给 Broker,当 Broker 收到之后,将会返回确认响应信息给 Producer。所以生产者只要接收到返回的确认响应,就代表消息在生产阶段未丢失。

RocketMQ 发送消息示例代码如下:

面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!第2张

send 方法是一个同步操作,只要这个方法不抛出任何异常,就代表消息已经发送成功。

消息发送成功仅代表消息已经到了 Broker 端,Broker 在不同配置下,可能会返回不同响应状态:

SendStatus.SEND_OKSendStatus.FLUSH_DISK_TIMEOUTSendStatus.FLUSH_SLAVE_TIMEOUTSendStatus.SLAVE_NOT_AVAILABLE引用官方状态说明:

面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!第3张

上图中不同 broker 端配置将会在下文详细解释

另外 RocketMQ 还提供异步的发送的方式,适合于链路耗时较长,对响应时间较为敏感的业务场景。

面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!第4张

异步发送消息一定要注意重写回调方法,在回调方法中检查发送结果。

不管是同步还是异步的方式,都会碰到网络问题导致发送失败的情况。针对这种情况,我们可以设置合理的重试次数,当出现网络问题,可以自动重试。设置方式如下:

面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!第5张

0x02. Broker 存储阶段

默认情况下,消息只要到了 Broker 端,将会优先保存到内存中,然后立刻返回确认响应给生产者。随后 Broker 定期批量的将一组消息从内存异步刷入磁盘。

这种方式减少 I/O 次数,可以取得更好的性能,但是如果发生机器掉电,异常宕机等情况,消息还未及时刷入磁盘,就会出现丢失消息的情况。

若想保证 Broker 端不丢消息,保证消息的可靠性,我们需要将消息保存机制修改为同步刷盘方式,即消息存储磁盘成功,才会返回响应。

修改 Broker 端配置如下:

## 默认情况为 ASYNC_FLUSH flushDiskType = SYNC_FLUSH

若 Broker 未在同步刷盘时间内(默认为 5s)完成刷盘,将会返回 SendStatus.FLUSH_DISK_TIMEOUT 状态给生产者。

集群部署

为了保证可用性,Broker 通常采用一主(master)多从(slave)部署方式。为了保证消息不丢失,消息还需要复制到 slave 节点。

默认方式下,消息写入master成功,就可以返回确认响应给生产者,接着消息将会异步复制到slave节点。

注:master 配置:flushDiskType = SYNC_FLUSH

此时若 master 突然宕机且不可恢复,那么还未复制到slave的消息将会丢失。

为了进一步提高消息的可靠性,我们可以采用同步的复制方式,master节点将会同步等待slave节点复制完成,才会返回确认响应。

异步复制与同步复制区别如下图:

面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!第6张

注: 大家不要被上图误导,broker master 只能配置一种复制方式,上图只为解释同步复制的与异步复制的概念。

Broker master 节点 同步复制配置如下:

## 默认为 ASYNC_MASTER brokerRole=SYNC_MASTER

如果slave节点未在指定时间内同步返回响应,生产者将会收到SendStatus.FLUSH_SLAVE_TIMEOUT 返回状态。

小结

结合生产阶段与存储阶段,若需要严格保证消息不丢失,broker 需要采用如下配置:

面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!第7张

同时这个过程我们还需要生产者配合,判断返回状态是否是 SendStatus.SEND_OK。若是其他状态,就需要考虑补偿重试。

虽然上述配置提高消息的高可靠性,但是会降低性能,生产实践中需要综合选择。

0x03. 消费阶段

消费者从 broker 拉取消息,然后执行相应的业务逻辑。一旦执行成功,将会返回 ConsumeConcurrentlyStatus.CONSUME_SUCCESS 状态给 Broker。

如果 Broker 未收到消费确认响应或收到其他状态,消费者下次还会再次拉取到该条消息,进行重试。这样的方式有效避免了消费者消费过程发生异常,或者消息在网络传输中丢失的情况。

消息消费的代码如下:

面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!第8张

以上消费消息过程的,我们需要注意返回消息状态。只有当业务逻辑真正执行成功,我们才能返回 ConsumeConcurrentlyStatus.CONSUME_SUCCESS。否则我们需要返回 ConsumeConcurrentlyStatus.RECONSUME_LATER,稍后再重试。

0x04. 总结

看完 RocketMQ 不丢消息处理办法,回头再看这篇 kafka,有没有发现,两者解决思路是一样的,区别就是参数配置不一样而已。

所以下一次,面试官再问你 XX 消息队列如何保证不丢消息?如果你没用过这个消息队列,也不要哭,微笑面对他,从容给他分析那几步会丢失,然后大致解决思路。

最后我们还可以说出我们的思考,虽然提高消息可靠性,但是可能导致消息重发,重复消费。所以对于消费客户端,需要注意保证幂等性。

面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!第9张

但是要注意了,这时面试官可能就会跟你的话题,让你来聊聊如何保证幂等性,一定先想好再说哦。

什么?你还不知道如何实现幂等?那就赶紧关注**@程序通事,后面文章我们就来聊聊幂等**这个话题。

面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!第10张

最后说一句(求关注)

才疏学浅,难免会有纰漏,如果你发现了错误的地方,还请你留言给我指出来,我对其加以修改。

再次感谢您的阅读,我是计算机 JAVA 编程,一位还未秃头的程序猿,下篇文章我们再见~

面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!第11张
转载于:https://baijiahao.baidu.com/s?id=1662095398693413299&wfr=spider&for=pc

免责声明:文章转载自《面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇html2canvas如何在元素隐藏的情况下生成截图Teradata Join类型下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Jenkins Generic Webhook Trigger+gitlab设置触发器

在生产环境中因为代码仓库迁移导致Jenkins设置的触发器失效,在调试的过程gitlab触发事件响应状态码为200,但是响应消息一直为{"status":"ok","data":{..."triggered":false,"url":""}}}} 。 此篇文章的描述主要针对该问题,且面向对Jenkins和Gitlab有一定经验的小伙伴。 文章标签: Je...

苹果APNs’ device token特性和过期更新

APNs全名是Apple Push Notification Service。用iPhone的应该都习惯了,每次安装完一个新应用启动后,几乎都会弹出个警告框,“XXX应用”想要给您发送推送通知。这个警告框的权限申请就是为了APNs推送,用户授权后,应用提供商就可以通过APNs给用户推送消息。APNs的工作机制简单来说可以分为两步,第一步是注册推送服务从AP...

ASP.NET中进行消息处理(MSMQ) 二

      在我上一篇文章《ASP.NET中进行消息处理(MSMQ)一》里对MSMQ做了个通俗的介绍,最后以发送普通文本消息和复杂的对象消息为例介绍了消息队列的使用。 本文在此基础上继续介绍MSMQ的相关知识点,最后还是通过一个示例程序来分析MSMQ在实际项目开发中的应用。 建议:如果你对MSMQ不够了解,在你阅读本文前请先阅读第一部分:《ASP.NET中...

Jmeter(三) 从上传图片来入门Jmeter

用Jmeter上传用户头像到人人网 先用抓包工具Fiddler把上传操作的报文抓取下来 开启Jmeter,在测试计划中创建一个线程组,取名为“图片上传” 再在线程组中创建一个HTTP请求 在请求报文中可以看到有一个<file>的参数,其实就是图片名称。 在Jmeter的文件上传中把图片路径配置上去 配置上传参数,接口URL,请求方式...

kafka集群搭建(windows环境下)

一、简介 Kafka 是一个实现了分布式的、具有分区、以及复制的日志的一个服务。它通过一套独特的设计提供了消息系统中间件的功能。它是一种发布订阅功能的消息系统。 1、名词介绍 Message 消息,就是要发送的内容,一般包装成一个消息对象。   Topic 通俗来讲的话,就是放置“消息”的地方,也就是说消息投递的一个容器。假如把消息看作是信封的话,那么 T...

转:利用JavaScript实现图片标注——SearchMapIdentityTask

功能:功能实现了现在网络流行的定位后在地图上画一个图标,点击图标后弹出消息框。 思路:根据查询条件获得一个点的地图坐标,然后转换为屏幕坐标,利用js脚本动态图片到相应位置。 效果图如下: 主要实现步骤: 1、SearchMapIdentity.cs,该类主要实现查询获取点的地图坐标,地图坐标转换为屏幕坐标的方法,点击小图标时的回发调用,代码如下 1us...