您现在的位置是:亿华云 > 热点
车祸现场!线上突然宕机,一条订单消息丢失了
亿华云2025-10-05 21:27:08【热点】1人已围观
简介一、写在前面之前写过一篇文章《RabbitMQ是如何收发消息的?(通俗易懂)》,我们用一个简单易懂的电商场景给大家引入说明了一个消息中间件的使用场景。同时,我们还基于RabbitMQ的Hell
之前写过一篇文章《RabbitMQ是现场线上息丢如何收发消息的?(通俗易懂)》,我们用一个简单易懂的突然条订电商场景给大家引入说明了一个消息中间件的使用场景。
同时,宕机单消我们还基于RabbitMQ的车祸HelloWorld级别的代码,给出了订单服务和仓储服务如何基于MQ中间件收发消息的现场线上息丢示例。
二、突然条订业务场景回顾这篇文章,宕机单消我们来稍微深入探讨一些MQ中间件使用中的车祸基础技术问题。
首先回顾一下上篇文章做出来的现场线上息丢一个架构图,看看订单服务和消息服务是突然条订如何基于MQ来收发消息的。
我们稍微把这个图细化一点,宕机单消简单来说就是车祸多个订单服务实例给queue推送消息,多个仓储服务每个消费一部分消息。现场线上息丢如下图所示:
假如你线上对MQ技术的使用就到此为止了,那么基本可以跟offer说拜拜了。。。
因为如果是云服务器提供商我的话,作为一个面试官就没法继续往下问了。你这个MQ的使用以及理解的深度仅此而已的话,那基本就是刚刚对MQ技术入门的程度。
如果面试官要继续问,完全可以问下面的问题:
那你说说如果仓储服务作为消费者服务,刚收到了一个订单消息,但是在完成消息的处理之前,也就是还没对订单完成仓储调度发货,结果这个仓储服务突然就宕机了,这个时候会发生什么事情?
所以说,大家还是要对这个技术了解得稍微深入一点点,否则随便被问几个问题就完蛋了。
大伙儿先来看看下面的图,感受一下车祸现场。
RabbitMQ这个中间件默认的一个行为,就是只要仓储服务收到一个订单消息,RabbitMQ就会立马把这条订单消息给标记为删除,这个行为叫做自动ack,云服务器也就是投递完成一条消息就自动确认这个消息处理完毕了。
但是接着如果此时仓储服务收到了一个订单消息,但是还没来得及对仓库系统完成商品的调度发货,结果直接就宕机了。
此时,明显这个订单消息就丢失了啊,因为RabbitMQ那里已经没有了。。。
这会导致什么样的尴尬体验呢?就是一个用户支付了8999元,对一个iphone8下了订单,结果呢,死等活等了好几天,就是不见网站上显示他的iphone8在发货。
搞了半天,原因就是他的那个iphone8的订单在仓储服务那里,还没来得及调度发货直接就宕机了,导致这个订单消息就一直丢失了,始终没有给这个用户通知仓库系统进行发货。
这个问题,是不是源码库很尴尬?所以说,技术问题是会严重影响企业的核心业务流程的!
各位小伙伴,还记得上一讲咱们的仓储服务消费消息的代码中,有一行关键的代码:
这行代码对channel.basicConsume()方法,传入的第二个参数:true,其实就是一个关键的参数。
这个true就代表了一个核心的含义,他的意思是,RabbitMQ只要把一个消息投递到仓储服务手上,立马就标记这个消息删除了。
但是在这个默认的配置之下,要是仓储服务收到一个订单消息,结果还没来得及完成耗时几十秒的仓储调度发货的业务逻辑,结果突然宕机了,那么这个订单消息就永久性丢失了!
找了半天,原来问题的症结在这里啊!大家是不是明白了,上一篇文章最后为什么我会说,这个代码目前为止还有很多的问题。
所以这个时候,我们如果希望不要因为仓储服务的突然宕机导致一条订单消息丢失,就需要改造一下仓储服务消费消息的代码了。
首先,我们需要把那个参数从true改为false,如下代码所示:
只要修改为false之后,RabbitMQ就不会盲目的投递消息到仓储服务,立马就删除消息了,说白了就是关闭autoAck的行为,不要自作主张的认为消息处理成功了。
接着,我们需要改造一下处理订单消息的代码,如下代码所示。
这段代码,说白了,就是在对订单完成了调度发货之后,在finally代码块中手动执行了ack操作,说我自己已经完成了耗时几十秒的业务逻辑的处理,现在可以手动ack通知RabbitMQ,这个消息处理完毕了。
此时整个架构运行流程大致看起来跟下面的图那样子。
架构流程改成上面那样后,就意味着只有完成了仓储调度发货的代码业务逻辑,确保仓库系统收到通知之后,仓储服务才会在代码中手动发送ack消息给RabbitMQ。
此时,RabbitMQ收到了这个ack消息,才会标记对应的订单消息被删除了。
如果说在仓储服务收到了订单消息,但是还没来得及完成仓储调度发货的业务逻辑,那也就绝对不会执行这条订单消息的ack操作,然后RabbitMQ也就不会收到这条订单消息的ack通知。
一旦RabbitMQ发现代表消费者的某个仓储服务实例突然宕机了,而这个仓储服务收到的一些订单消息还没来得及处理,没给自己发送那些消息的ack通知。
此时,RabbitMQ会自动对这条订单消息重发推送给其他在运行中的仓储服务实例,让其他的仓储服务实例去处理这条订单消息。
这样的话,就可以保证这条订单消息不会因为某个仓储服务实例的宕机而丢失,他会确保必须由某个仓储服务实例完成这条订单消息的调度发货处理,然后才会删除那条订单消息。
四、总结 tips最后再来一张图,大家直观的感受一下:
好了,各位同学,这篇文章是不是相对稍微深入一点点,让大家了解到了一些使用MQ技术时候要考虑的一些问题?
实际上无论是RocketMQ、Kafka还是RabbitMQ,都有类似的autoAck或者是手动ack的机制。
线上生产环境中运行时,你必须要考虑到消费者服务可能宕机的问题。
如果消费者服务没处理完消息就自己宕机了,那么一定会导致部分消息的丢失,进而影响核心业务流程的运转。
因此大家在线上使用MQ时,一定要充分考虑这些潜在问题,同时结合具体的MQ提供的一些API、参数来进行合理设置,确保消息不要随意丢失。
很赞哦!(142)
相关文章
- 4.选择顶级的域名注册服务商
- 前端算法系统练习: 链表篇完结
- GCC 11编译器已初步支持AMD Zen 3
- 图像风格迁移也有框架了:使用Python编写,与PyTorch完美兼容,外行也能用
- 便宜域名使用如何?小白可以买到便宜域名吗?
- 用PyQt打造具有专业外观的GUI(上)
- 成为一名优秀的软件开发人员必须具备的技能
- 一篇文章带你了解SVG 剪切路径
- 域名资源有限,好域名更是有限,但机会随时都有,这取决于我们能否抓住机会。一般观点认为,国内域名注册太深,建议优先考虑外国注册人。外国注册人相对诚实,但价格差别很大,从几美元到几十美元不等。域名投资者应抓住机遇,尽早注册国外域名。
- 开源开发者说保护自己的代码是令人心力交瘁的浪费时间
站长推荐
投资各类域名就像到处打游击战,结果处处失败。因为这样,对任何一个中国域名市场的走势和价格都没有准确的把握,所以最好缩小范围,准确把握战场态势,埋伏。
跨域请求产生错误的原因及处理方法
编写一个简单的游戏来学习 Python
收下这款 Vue 项目模版,它将让你的开发效率在 2021 年提高 50%
众所周知,com域名拥有最大的流通市场和流通历史。最好选择com域名,特别是在购买域名时处理域名。其次可以是cn域名、net域名、org域名等主流域名,现在比较流行的王域名和顶级域名,都是值得注册和投资的。
刚来的大兄弟在这个小问题上翻车了,你确定不看一下?
C++为什么非要引入那几种类型转换?
2D动画唇动合成,根据语音自动生成动画人物口型