😊你好,我是小航,一个正在变秃、变强的文艺倾年。
🔔本专栏《八股消消乐》旨在记录个人所背的八股文,包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法
等相关知识点,期待与你一同探索、学习、进步,一起卷起来叭!
目录
- 题目
- 答案
- Why use 消息队列?
- 秒杀场景
- 订单超时取消
- 事件驱动(Event-Driven)
题目
💬技术栈:RocketMQ、Kafka、RabbitMQ
🔍简历内容:熟悉消息队列常见应用场景,基于事件驱动实现了 SAGA 的分布式事务,保证了事务的低耦合、高扩展、高可用。
🚩面试问:你为什么用 Kafka、RabbitMQ 或 RocketMQ,又或者说你为什么使用某一个中间件?
💡建议暂停思考10s,你有答案了嘛?如果你有不同题解,欢迎评论区留言、打卡。
答案
前置准备:
- 你们公司有没有使用消息队列?主要用于解决什么场景的问题?
- 如果使用了消息队列,那么在具体的场景下不使用消息队列是否可行?和使用消息队列的方案比起来,有什么优缺点?
- 你们公司用的是什么消息队列,它有什么优缺点?
Why use 消息队列?
为什么要用消息队列?【其实就是再问在这个业务场景下,不异步、不解耦或者不削峰会有什么问题?】
答案:如果不用消息队列,性能差、扩展性差、可用性差。【同步调用的缺点】
性能差:业务方必须停下来等待结果,如果我这里需要通知三个下游,那么就需要发起三次调用,并且等它们各自的结果返回之后才能继续往下执行,或者返回响应,这样性能太差了。
扩展性差:在使用消息队列的时候,新的下游要接入,只需要自己去订阅消息就可以,完全不需要通知任何人。在公司里,可能就是你丢给下游一个文档,下游自己看看文档,知道订阅哪个 topic,消息生产速率有多高,差不多就能自己独立完成接入了
。
而同步调用的时候,上游必须知道下游的接口,然后要知道如何构造请求、如何解析响应,还要联调、测试、上线,整个过程都得和下游密切合作,因此效率特别低
,可扩展性很差。
如果在某些场景下确实不能用消息队列,那么这个扩展性问题可以通过一些技术手段来缓解。比如说上游提供一整套的对接规范,包括 API 定义、请求和响应中每个字段的含义
。这样下游就对着这个 API 定义来提供实现,上游就不需要适配每一个下游了。
可用性:在同步调用方案中,你必须要确保调用所有的下游都成功了才算是成功了
。所以你还需要额外考虑部分成功部分失败的问题。
秒杀场景
架构设计:
利用消息队列把整个秒杀过程分成轻重两个部分
:
- 进入消息队列之前:秒杀请求进来之后,会有一个轻量级的服务。这个服务就是
做一些限流、请求校验和库存扣减
的事情。这些事情差不多都是内存操作,最多操作 Redis
。当库存扣减成功之后,就会把秒杀请求丢到一个消息队列
。 - 进入消息队列之后:
订单服务会从消息队列里面将请求拿出来
,真正创建订单,并且提示用户支付
。这一部分就是重量级的操作,无法支撑大规模并发。
订单超时取消
场景:扣减了库存之后,用户没有支付
怎么办。
解决方案:如果用户下单之后一直没有支付,那么这个订单就会被取消,从而释放库存。想利用消息队列实现订单超时取消功能,需要使用 延时消息。(超时时间是 30 分钟)
延时消息:发送者在发送之后,要过一段时间,消费者才能消费的消息
。
可能引发的并发问题:在 30 分钟这一个时刻,一边用户支付,一边消费者也消费超时消息,就会有并发问题
。
解决思路:使用分布式锁、乐观锁(在你把订单更新为超时状态的时候,需要 确保原始状态还是未支付。支付那边也需要确保只有在 status 是未支付的时候才能发起支付。),也可以使用 SELECT FOR UPDATE 锁住订单,防止并发操作。
目前主流的消息队列中 RocketMQ 是支持延时消息的,它有插件支持。但是 Kafka 不支持。
事件驱动(Event-Driven)
事件驱动适合用来解决一些 复杂、步骤繁多、流程冗长 的业务问题。
场景:事件驱动结合 SAGA 分布式事务。
当某一个步骤完成之后,就会发出一个或者多个事件,驱动事务中的后续步骤。包括回滚也是这样,比如说发出一个代表某一个步骤执行失败的事件,对应的消费者就会去执行反向补偿步骤
。
不过在实时性上要比同步调用差一点
。比如说你有一个分布式事务,就是要求先更新 DB,再更新缓存
。那么在缓存更新失败的场景下,过程看起来就像图里展示的这样。
往期精彩专栏内容,欢迎订阅:
🔗【八股消消乐】20250622:Elasticsearch查询优化
🔗【八股消消乐】20250620:Elasticsearch优化—检索Labubu
🔗【八股消消乐】20250619:构建微服务架构体系—保证服务高可用
🔗【八股消消乐】20250615:构建微服务架构体系—链路超时控制
🔗【八股消消乐】20250614:构建微服务架构体系—实现制作库与线上库分离
🔗【八股消消乐】20250612:构建微服务架构体系—限流算法优化
🔗【八股消消乐】20250611:构建微服务架构体系—降级策略全总结
🔗【八股消消乐】20250610:构建微服务架构体系—熔断恢复抖动优化
🔗【八股消消乐】20250609:构建微服务架构体系—负载均衡算法如何优化
🔗【八股消消乐】20250608:构建微服务架构体系—服务注册与发现
🔗【八股消消乐】20250607:MySQL存储引擎InnoDB知识点汇总
🔗【八股消消乐】20250606:MySQL参数优化大汇总
🔗【八股消消乐】20250605:端午节产生的消费数据,如何分表分库?
🔗【八股消消乐】20250604:如何解决SQL线上死锁事故
🔗【八股消消乐】20250603:索引失效与优化方法总结
🔗【八股消消乐】20250512:慢SQL优化手段总结
🔗【八股消消乐】20250511:项目中如何排查内存持续上升问题
🔗【八股消消乐】20250510:项目中如何优化JVM内存分配?
🔗【八股消消乐】20250509:你在项目中如何优化垃圾回收机制?
🔗【八股消消乐】20250508:Java编译优化技术在项目中的应用
🔗【八股消消乐】20250507:你了解JVM内存模型吗?
🔗【八股消消乐】20250506:你是如何设置线程池大小?
🔗【八股消消乐】20250430:十分钟带背Duubo中大厂经典面试题
🔗【八股消消乐】20250429:你是如何在项目场景中选取最优并发容器?
🔗【八股消消乐】20250428:你是项目中如何优化多线程上下文切换?
🔗【八股消消乐】20250427:发送请求有遇到服务不可用吗?如何解决?
📌 [ 笔者 ] 文艺倾年
📃 [ 更新 ] 2025.6.23
❌ [ 勘误 ] /* 暂无 */
📜 [ 声明 ] 由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!