面试之消息队列

目录

面试题列表

1、为什么要用消息队列?(消息队列的应用场景?)

1.1、面试官心理分析

1.2、消息队列的本质

1.3、解耦

1.4、异步

1.5、削峰/限流

1.5.1、流量削峰的经济考量

1.6、小结

2、各种消息队列产品的比较

2.1、面试官心理分析

2.2、几种MQ的对比

2.3、小结

3、消息队列的优点和缺点

3.1、面试官心理分析

3.2、系统可用性降低

3.3、系统复杂度提高

3.4、一致性问题

3.5、小结

4、如何保证消息队列的高可用?

4.1、面试官心理分析

4.2、RabbitMQ高可用-普通集群

4.3、RabbitMQ高可用-镜像集群(解决普通集群的缺点)

4.4、RocketMQ高可用-双主双从

4.5、小结

5、如何保证消息不丢失?

5.1、面试官心理分析

5.2、消息丢失的原因

5.3、确保消息不丢失方案

5.4、小结

6、如何保证消息不被重复消费?

6.1、面试官心理分析

6.2、重复消息产生的原因

6.3、消息幂等性

6.4、小结

7、如何保证消息消费的顺序性?

7.1、面试官心理分析

7.2、消息的顺序性消费

7.3、小结

8、基于MQ的分布式事务实现

8.1、分布式事务

8.2、小结


面试题列表

  1. 为什么要用消息队列?(消息队列的应用场景?)
  2. 各种消息队列产品的比较?
  3. 消息队列的优点和缺点?
  4. 如何保证消息队列的高可用?
  5. 如何保证消息不丢失?
  6. 如何保证消息不被重复消费?(如何保证消息消费的幂等性?)
  7. 如何保证消息消费的顺序性?
  8. 基于MQ的分布式事务实现

1、为什么要用消息队列?(消息队列的应用场景?)

1.1、面试官心理分析

考察面试者是否知道消息队列用来解决什么样的问题?

也就是消息队列的应用场景

1.2、消息队列的本质

  • 消息队列是一种“先进先出”的数据结构

  • 常见应用场景:解耦、异步、削峰

1.3、解耦

    系统的耦合性越高,容错性就越低。以电商应用为例,用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障或者因为升级等原因暂时不可用,都会造成下单操作异常,影响用户使用体验。

1.4、异步

    A系统接收一个请求,需要在自己本地写库,还需要在B、C、D三个系统写库,自己本地写库要3ms,B、C、D三个系统分别写库要300ms、450ms、200ms。最终请求总延时是3+300+450+200=953ms,接近1s,用户非常不好,一般互联网类的企业,对于用户直接的操作,一般要求是每个请求都必须在200ms以内完成,对用户几乎是无感知的,如果用户通过浏览器发起请求,等待个1s,这几乎是不可接受的。

    如果使用MQ,那么A系统连续发送3条消息到MQ队列中,假如耗时5ms,A系统从接受一个请求到返回响应给用户,总时长是3+5=8ms,对于用户而言,响应速度大大提升了,改善了用户的体验。

1.5、削峰/限流

    应用系统如果遇到系统请求流量的瞬间猛增,有可能会将系统压垮。有了消息队列可以将大量请求缓存起来,分散到很长一段时间处理,这样可以大大提到系统的稳定性和用户体验。

1.5.1、流量削峰的经济考量

 业务系统正常时段的QPS如果是2000,流量最高峰是10000,这里应该是应该冲着2000搭,还是10000搭服务器呢?

 答案是2000,为了应对流量高峰配置高性能的服务器搭10000显然不划算,但是在高并发场景下,如秒杀场景QPS是大于2000的,系统肯定挂掉的,这时可以使用消息队列对峰值流量削峰限流为2000,从而保证系统不蹦。

一般情况,为了保证系统的稳定性,如果系统负载超过阙值,就会阻止用户请求,这会影响用户体验,而如果使用消息队列将请求缓存起来,等待系统处理完毕后通知用户下单完毕,这样总比不能下单体验要好。

1.6、小结

  • 为什么要用消息队列
  1. 解耦
  2. 异步
  3. 削峰

2、各种消息队列产品的比较

2.1、面试官心理分析

考察面试者是否对市面上的MQ产品做过调研?

在选择MQ时是否根据不同MQ的产品特点做过对比和取舍?

2.2、几种MQ的对比

2.3、小结

  • ActiveMQ ,早起使用的较多,没经过大规模吞吐量场景的验证,社区也不是很活跃,但是现在确实大家用的不多了,不推荐。
  • RabbitMQ ,开发语言 erlang 阻止了大量的 Java。工程师去深入研究和掌控它,对公司而言,几乎处于不可控的状态,但是 RabbitMQ 是开源的,比较德定的支持,活跃度也高,如不考虑二次开发,追求性能和稳定性,推荐使用。
  • RocketMQ ,开发语言是 Java ,在阿里内部经受过高并发业务的考验,稳定性和性能均不错,考虑后期可能二次开发,推荐使用。
  • Kafka,大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,社区活跃度很高,推荐使用。大数据领域日志采集等业务推荐使用。
  • ZeroMQ,底层是C/C++开发的,但是目前支持了多种语言对它的封装,可以说是夸平台、跨语言的。另外ZeroMQ是嵌入到程序内部的(类似程序中使用第三方api),而其他MQ是独立的一个服务。

3、消息队列的优点和缺点

3.1、面试官心理分析

考察面试者在项目中引入一个新的技术后,是否全面考虑过新的技术对当前项目的影响。

3.2、系统可用性降低

系统引入的外部依赖越多,系统稳定性越差。一旦MQ宕机,就会对业务造成影响。---如何保证MQ的高可用?

3.3、系统复杂度提高

MQ的加入大大增加了系统的复杂度,以前系统间是同步的远程调用,现在是通过MQ进行异步调用。

引入问题有:

  1. 消息丢失怎么办?
  2. 重复消息怎么处理?
  3. 如何保证消息传递的顺序性?

3.4、一致性问题

A系统处理完业务,通过MQ给B、C、D三个系统发消息数据,如果B系统、C系统处理成功,D系统处理失败。

如何保证消息数据处理的一致性?

3.5、小结

  • 消息队列的优点和缺点?

优点

  • 解耦
  • 异步
  • 削峰

缺点

  • 系统可用性降低
  • 系统复杂度提高
  • 一致性问题

4、如何保证消息队列的高可用?

4.1、面试官心理分析

项目中引入了MQ导致系统的可用性降低,面试官想知道的是面试者针对可用性降低问题的思考和解决思路。

问答此问题时,面试者只需针对自己使用过的一两个MQ产品的高可用方案回答即可。

4.2、RabbitMQ高可用-普通集群

  1. 在多台机器上分别启动RabbitMQ实例。
  2. 多个实例之间可以相互通信。
  3. 创建的Queue只会放在一个RabbitMQ上,其他实例都同步元数据。
  4. 消费的时候,如果连接的没有Queue,那么当前实例会从queue所在实例拉取数据。

特点

1.没有真正做到高可用(左右节点从中间节点拉取业务数据然后在给消费者消费,当左右节点宕机不影响,当中间节点宕机了就真的宕机了,业务数据将不能获取了)。

2.有数据拉取的开销和单实例的瓶颈问题(所有数据要到中间节点拉取,这样会有性能的瓶颈)。

图中元数据是配置数据,实际数据是业务数据。

4.3、RabbitMQ高可用-镜像集群(解决普通集群的缺点)

  1. 在多台机器上分别启动 RabbitMO实例。
  2. 多个实例之间可以相互通信。
  3. 每次生产者写消息到 queue的时候,都会自动把消息同步到多个实例的 queue上。每个RabbitMQ节点上都有 Queue的消息数据和元数据。
  4. 某一个节点宕机,其他节点依然保存完整数据,不影响客户端消费。

 

4.4、RocketMQ高可用-双主双从

  1. 生产者通过Name Server发现Broker。
  2. 生产者发送队列消息到2个Broker主节点。
  3. Broker主节点分别和各自从节点同步数据。
  4. 消费者从主或者从节点订阅消息。

图中Name Server可以理解为管理者,Producer发消息前会询问Name Server发送到哪个主节点,主节点收到数据后会同步到从节点,主从节点和Name Server通过心跳机制的方式可以知道节点是否正常运行,消费者可以从主节点、从节点消费数据

4.5、小结

  • MQ的高可用如何保证?
  1. RabbitMQ::镜像集群
  2. RocketMQ:双主双从

5、如何保证消息不丢失?

5.1、面试官心理分析

  1. 考察面试者是否清楚消息丢失的原因?
  2. 如何保证消息不丢失?

5.2、消息丢失的原因

情况一:消息生产者没有成功发送到MQ Broker。

情况二:消息发送给MQ Broker后,Broker宕机导致内存中的消息数据丢失。

情况三:消费者获取到消息,但消费者还没有来得及处理宕机了,但此时MQ中消息已经删除,消费者重启后不能再消费之前的消息。

5.3、确保消息不丢失方案

  1. 消息发送者发送给 MQ Broker后, MQ Broker给生产者确认收到。
  2. MQ收到消息后进行消息持久化。
  3. 消费者收到消息处理完毕后手动进行ack确认。
  4. MQ收到消费者ack确认后删除持久化的消息。

5.4、小结

消息丢失的原因

  • 发送方、MQ、消费方都有可能导致消息丢失。

如何保证消息不丢失

  • 发送方可靠发送。
  • MQ进行消息持久化。
  • 消费方消费完毕进行ACK确认,MQ收到消费方的ACK确认再删除本地消息。

6、如何保证消息不被重复消费?

6.1、面试官心理分析

消息的重复消费和保证幂等性会经常被连着问,当出现了重复消费后,为了保证系统数据的正常性,就必须要保证幂等性。针对该问题,面试官实际想要考察的是:

  1. 面试者对重复消费产生原因的思考
  2. 面试者对保证消息幂等性的方案

6.2、重复消息产生的原因

消息重复的根本原因是网络不可达。

  • 发送时消息重复

当一条消息已被成功发送到服务端,此时出现了网络闪断,导致服务端对客户端应答失败。如果此时生产者意识到消息发送失败并尝试再次发送消息,消费者后续会收到两条内容相同的消息。

6.3、消息幂等性

  1. 消息发送者发送消息时携带一个全局唯一的消息id。
  2. 消费者获取消费后先根据id在redis/db中查询是否存在消费记录。
  3. 如果没有消费过就正常消费,消费完毕后写入redis/db。
  4. 如果消息消费过就直接舍弃。

6.4、小结

  • MQ消息的重复问题和幂等性保证?

消息重复原因

  • 网络不可达,不可避免。

幂等性

  • 消息携带全局ID,消费方接到消息时先查在处理,根据全局ID做判重操作。

7、如何保证消息消费的顺序性?

7.1、面试官心理分析

  1. 考察消费者是否理解什么是消息顺序消费?
  2. 考察消费者是否思考过确保消息顺序消费的方案?

7.2、消息的顺序性消费

消息有序指的是可以按照消息的发送顺序来消费。
例如:一笔订单产生了3条消息,分别是订单创建、订单付款、订单完成
消费时,要按照顺序依次消费才有意义。
与此同时多笔订单之间又是可以并行消费的

假设消费者顺序有张三:M1、M2、M3,李四S1、S2、S3。

  • 模式一:M1、M2按照先后顺序发送到2台Server,被2个消费者分别消费(PASS)。
  1. 不能保证消息的顺序到达MQ。
  2. 不能保证消息的顺序消费。

 

  • 模式二:M1、M2按照先后顺序发送到1台Server,被2个消费者分别消费(PASS)。
  1. 可以保证消息的顺序到达MQ。
  2. 消费方如果出现网络延迟问题,不能严格保证消息的顺序消费。

  • 模式三:生产者:MQ Server:消费者=1:1:1(全局顺序性)
  1. 可以保证消息顺序到达MQ。
  2. 可以保证消息顺序消费。

全局的顺序消费(即张三的消息没有消费完的话,李四的消息是不能消费的),不常见!

  1. 吞吐量下降。
  2. 容错性降低。

该模式在M1被消费并且应答后,再消费M2,如此保证顺序性。

  • 模式四:局部顺序消费
  1. 生产者根据消息ID将同一组消息发送到一个Queue中。
  2. 多个消费者同时获取Queue中的消息进行消费。
  3. MQ使用分段锁保证单个Queue中的有序消费。

该模式既保证了并行消费,也保证了顺序消费。

当消费者1 从Queue1 取了M1时,给Queue1加分段锁,当消费者1 ack后再解锁,让消费者2从Queue1中取M2再加锁,以此完成局部顺序性。

这里张三的消息只能到同一个消息队列,比如M1、M2、M3都在Queue1,S1、S2、S3都在Queue3.

7.3、小结

什么是消息的顺序型消费?

  • 消费方按照消息发送的顺序进行消费,分为全局顺序消息和局部顺序消息。
  • 常见的局部顺序消费

如何保证消息的顺序消费?

  • 全局顺序消息,生产者:MQ:消费者=1:1:1
  • 局部顺序消息
  1. 生产者将同一组消息发送到单个队列。
  2. 多个消费者并行对消息进行消费。
  3. Queue通过分段锁保证消息消费的顺序性。

8、基于MQ的分布式事务实现

8.1、分布式事务

  1. 用户提交订单。
  2. 库存服务操作库存DB,减库存。
  3. 订单服务操作订单DB,生成订单数据。
  4. 库存服务和订单服务要么同时成功,要么同时失败。

本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

处理流程: 

  • 消息发送方先将消息存储到本地消息表并置消息状态type=1表示未处理,然后发送消息到MQ,消息消费方监听到消息后,根据id查询本地消息表是否重复,如果未重复则继续执行并存储本地消息表,再发送成功到MQ。消息发送方监听到消费方处理成功后,将本地消息表的消息状态type置为2表示已处理。
  • 当消费方处理失败的时候,此时消费方没有正常发送消息到MQ,因为消息发送方有个定时任务,定时查询本地消息表,将type=1的数据重新发送到MQ,接着触发消费方消费。

8.2、小结

消息发送方:

  1. 处理业务逻辑。
  2. 保存消息到本地数据库。
  3. 发送消息给MQ。
  4. 监听MQ消息方通知消息,更改消息状态为已处理。
  5. 定时任务将长期未处理消息重新发送到MQ。

消息消费方:

  1. 监听MQ中间件消息。
  2. 判断消息是否重复,重复就丢弃。
  3. 消息未重复,执行本地业务。
  4. 业务处理完毕,写消息记录到本地数据库。
  5. 发送通知消息到MQ。

 

 

 

参考之https://www.bilibili.com/video/BV1tK411p71q?t=6008

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值