消息队列面试重点-1

1. 什么是消息队列(Message Queue)?

答题技巧与拓展:**

  • 问为什么使用MQ?首先说MQ概念,然后说MQ优点,最后优点的使用场景,并举例。

概念:

应用程序之间的通信方法,是一种中间件。简单理解:把要传输的数据放在队列中,双方通过队列传递数据。

优点:

异步、解耦、削峰(应用场景都是优点)。

缺点:

系统可用性降低(MQ挂掉,系统崩溃)、系统复杂度提高(消息重复消费、消息丢失、消息传递的顺序性)、数据一致性问题(AB两系统数据保存成功, C系统保存失败)。

应用场景:

  • 异步处理:不影响主流程的操作,使用MQ异步处理。举例:用户注册后,通过MQ异步发送注册邮件或注册短信。
  • 应用解耦:通过MQ进行传递数据,可以隔离系统上下游环境变化带来的不稳定因素。举例:用户下单后,订单系统需要通知库存系统。
  • 流量削锋:通过MQ接收所有数据,避免流量过大,导致应用挂掉。举例:秒杀活动。
  • 日志处理:解决大量日志传输的问题。举例:大数据中使用Kafka接收数据。
  • 消息通讯:MQ一般都内置了高效的通信机制,因此可以用在的消息通讯。举例:点对点消息队列、聊天室等。

常见MQ:

  • ActiveMQ:万级;基于主从的高可用架构;有较低的概率丢失数据;JMS规范;
  • RabbitMQ:万级;基于主从的高可用架构;AMQP规范(特点:消费者跨平台、交换机组件等);erlang语言开发、性能好、社区活跃等。
  • Kafka:十万级;基于分布式的高可用架构;经过参数优化配置,可以做到0丢失;主要定位是在日志处理。
  • RocketMQ:十万级;基于分布式的高可用架构;经过参数优化配置,可以做到0丢失;Java实现。

2. 你们公司生产环境用的是什么消息中间件?

首先说明公司选用的是什么消息中间件,然后说不同MQ的选型分析。

选型分析:

  • ActiveMQ:是老牌的消息中间件,现在国内好多传统公司在运用,功能全面。但是它无法支付互联网的高并发、高负载,在互联网公司使用较少。
  • RabbitMQ:稳定、社区活跃,版本迭代快;基于AMQP规范,支持跨平台。但是基于erlang语言开发的,分析源码比较困难。
  • RocketMQ:阿里开源的,经过阿里的生产环境的超高并发、 高吞吐的考验,性能卓越,同时还支持分布式事务等特殊场景,Java语音开发的。
  • Kafka:提供的MQ功能明显较少一些。 但是它的优势在于超高吞吐量的实时日志采集、实时数据同步、实时数据计算。一般在大数据领域使用。

总结:

  • 中小型公司:技术实力较为一般,技术挑战不是特别高,用RabbitMQ;
  • 大型公司:基础架构研发实力较强,用RocketMQ。
  • 大数据领域:实时计算、日志采集等场景,用Kafka是业内标准的,绝对没问题。

3. MQ与RPC的区别:

  • 相同:
    • 解耦、子系统之间的交互(特别是异构子系统)。
  • 不同:
    • RPC侧重功能调用,并且关注结果,多半是同步的;
    • MQ考虑系统性能,不要求时效,支持订阅发布式数据传输。

4. MQ有哪些常见问题?

  • 消息的顺序问题
  • 消息的重复问题
  • 消息的丢失问题
  • 消息的一致性问题

5. 消息顺序问题:

概念:

消息有序,是指可以按照消息的发送顺序来消费。

举例:

假如生产者产生了 2 条消息:M1、M2,假定M1发送到S1,M2发送到 S2,如果要保证M1先于M2被消费,怎么做?

解决方案:

  • 方案1:保证生产者 - MQServer - 消费者是一对一的关系:
    • 缺陷:并行度就会成为消息系统的瓶颈(吞吐量不够)
    • 更多的异常处理,比如:只要消费端出现问题,就会导致整个处理流程阻塞,我 们不得不花费更多的精力来解决阻塞的问题。
  • 方案2:通过合理的设计或者将问题分解来规避:
    • 解决1:不关注乱序。
    • 解决2:队列无序并不意味着消息无序,从业务层面来保证消息的顺序(添加序号等),而不仅仅是依赖于消息系统,是一种更合理的方式。

6. 消息不被重复消费(消息消费时的幂等性)?

造成消息重复的重要原因:

网络的不确定性。 因为网络因素是不可控的,解决消息重复问题,就变成了:如果消费端收到两条一样的消息,应该怎样处理,即幂等性问题?

幂等性概念:

对资源(消息)的进行操作,无论操作一次还是多次,其资源本身不发生变化。

幂等性操作场景:

  • 强校验场景:
    • 场景举例:与金钱相关的关键消息,必须强校验。
    • 校验方法:基于数据库的唯一键等。
  • 弱校验场景:
    • 场景举例:可以有小概率出现重复消费的非关键消息。
    • 校验方法:基于Redis的Set数据类型等。

解决方法:

  • 通过主键来检查数据,如果有主键就更新,无数据就插入;(神州租车的做法)
  • 消费一条消息就往数据库里插入一条数据(JMSMessageID),每次都去数据库判断是否有相同的数据,有证明已经消费过;(碧有信的做法)
  • 写Redis时,使用Set数据类型 ,天然的幂等性;
  • 消费者发送消息带上全局唯一的id,消费者拿到消息后,根据这个id去Redis里查询,没有消费过就处理,并且写入这个 id 到Redis,反之,则不处理。

7. 消息丢失了怎么办?

丢失的情况:

生产者丢失、MQ Server(Broker)丢失、消费者丢失。

生产者丢失:

  • 丢失原因:生产者向MQ写数据的时候,可能数据半路就丢失了,可能是网络问题。
  • 解决:使用事务机制(遇到异常后,回滚消息)或confirm机制(写入成功后,MQServer给生产者回复一个ACK消息)。

MQ Server(Broker)丢失:

  • 丢失原因:MQ Server自己数据丢失,可能是服务器宕机了。
  • 解决:持久化消息;使用MQ集群,降低MQ挂机的可能性,防止数据丢失。

消费者丢失:

  • 丢失原因:消费者在消费时,刚消费到,还没有处理,消费者进程挂了,需要重启,此时MQ认为你已经消费过了。
  • 解决:使用ACK机制的手动应答。

8. 消息传递的一致性:

前提:

保证消息正常传递(生产者发送消息前,处理完所有业务;消息持久化,防止消息丢失;选择合适的消息确认机制)

方法1:消息事件表 + 分布式锁 + 幂等性消费 + 定时补偿 ,保证消息一致性 ***

处理流程:Event事件表(DB中)确定消息是否被消费。Redis分布式锁保证幂等性。

  • 问题1:生产者如何知道消费者没有消费一条消息?
    • 创建一个event表,用来维护消息的消费状态(核心字段:JMS队列名称、业务ID、完成状态等)。
  • 问题2:生产者重新发送的频率(即定时任务频率)?
    • 根据业务的实时性要求、消费者的能力和可以堆积的信息进行判断。
  • 问题3:消费者处理重复的消息?
    • 利用event表,使用Redis分布式事务锁(使用Redission框架,或使用String类型的并设置失效时间的简单方式实现不可重入的锁),实现幂等性消费。

方法2:消费者主动查询,推拉结合:

消费者启动一个定时任务,查询生产者需要它消费的数据,但是这样会影响消费者的消费能力。

使用场景:通知业务,适用这种推拉结合的方式。

处理流程:提供了一个http接口供用户查询(该http接口不一定在生产者),即用户可以接受推送消息,也可以主动去查询。

9. 如何解决消息积压的问题?

思路1:临时紧急扩容

      1. 先修复Consumer出现的问题,确保其恢复消费速度。
      1. 创建一个新的Topic,建立大小是原先10倍的Queue数量。(RocketMQ的概念)
      1. 将现有Cnosumer都停掉,写一个临时的分发数据的Consumer程序,将消息写入到临时的Queue中。
      1. 临时启动一批新机器部署Consumer,来消费积压数据,等消费完积压数据之后,再恢复原部署的架构。

思路2:积压数据直接丢弃,在业务低估时,批量重导

Tips:消息设置TTL,在大量数据积压时,可能过期进入死信队列。

10. 如何设计一个MQ,如何设计一个分布式的MQ:

MQ主要涉及三个角色,Producer、Consumer、Broker(MQ服务器),其中Broker是我们设计的重点,Broker需要考虑:遵循的规范和模式(例如,通信协议)、消息的存储、消息的传输、支持事务、支持延迟等:

    • 通信协议的选择:JMS(例如ActiveMQ)、AMQP(例如RabbitMQ)、自行设计等。
    • 消息存储(持久化)的选择:内存、KV分布式(Redis)、关系数据库、文件系统等。
    • 消费的关系处理:点对点、发布与订阅、广播与集群等。

分布式MQ在普通MQ的基础上,还需要考虑:数据一致性、集群可用性、集群容错性等分布式下需要关注的点:

    • 分布式理论:CAP理论 -> BASE理论 -> 消息队列一般遵循AP,保证可用性和容错性,牺牲一致性。实现最终一致性。
    • 引入注册中心:用于Producer、Consumer、Broker的注册与发现。使用ZK(CP)、Netty自己封装(AP)等。
    • 保证可用性:集群管理,选主(选举算法:ZAB)、主备、副本集等。
    • 支持动态扩缩容:数据分片存储等
    • 支持分布式事务、使用分布式锁等。
相关推荐
学历真的很重要2 小时前
LangChain V1.0 Short-term Memory 详细指南
后端·python·语言模型·面试·langchain·agent·ai编程
还是鼠鼠2 小时前
Redisson实现的分布式锁能解决主从一致性的问题吗?
java·数据库·redis·分布式·缓存·面试·redisson
Jing_Rainbow3 小时前
【LeetCode Hot100 刷题日记(19/100)】54. 螺旋矩阵 —— 数组、矩阵、模拟、双指针、层序遍历🌀
算法·面试·程序员
美团测试工程师3 小时前
最常见的软件测试面试题及答案
软件测试·面试·职场和发展
小时前端5 小时前
性能优化:从“用户想走”到“愿意留下”的1.8秒
前端·面试
芯片智造8 小时前
光刻工艺工程师职场就业相关面试问题汇总
经验分享·面试·芯片·半导体
闲人编程11 小时前
Django微服务架构:单体应用拆分解耦实践
微服务·架构·消息队列·django·api·通信·codecapsule
阿杰真不会敲代码13 小时前
Filter与Interceptor深度解析:分清这两个“拦截器”,面试不再掉坑
java·spring boot·面试
WYiQIU20 小时前
11月面了7.8家前端岗,兄弟们12月我先躺为敬...
前端·vue.js·react.js·面试·前端框架·飞书