消息队列问题总结

消息队列问题总结

1.为什么要用消息队列

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

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

解耦:

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

使用消息队列解耦合,系统的耦合性就会提高了。比如物流系统发生故障,需要几分钟才能来修复,在这段时间内,物流系统要处理的数据被缓存到消息队列中,用户的下单操作正常完成。当物流系统回复后,补充处理存在消息队列中的订单信息即可,终端系统感知不到物理系统的故障。

异步:

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

在这里插入图片描述

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

在这里插入图片描述

异步特定的使用条件:对用户返回的数据不需要依赖B\C\D处理的结果

流量削峰:

场景:秒杀

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

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

在这里插入图片描述

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

在这里插入图片描述

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

优点:解耦、异步、削峰

缺点:系统可用性降低、系统复杂度提高、一致性问题

系统的可用性降低:

系统引入的外部依赖越多,系统稳定性越差。—旦MQ宕机,就会对业务造成影响。

  • 如何保证MQ的高可用?

系统的复杂度提高

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

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

一致性问题

A系统处理完业务,通过MQ给B、C、D三个系统发消息数据,如果B系统、C系统处理成功,D系统处理失败。如何保证消息数据处理的一致性?

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

集群?

项目中引入了MQ导致系统的可用性降低,面试官想知道的是面试者针对可用性降低问题的思考和解决思路。
问答此问题时,面试者只需针对自己使用过的一两个MQ产品的高可用方案回答即可。

RabbitMQ高可用——普通集群

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

特点:

  • 没有真正的高可用(具有实际数据的节点挂了,RabbitMQ还是相当于挂了)
  • 有数据拉取的开销和单实例的瓶颈问题

在这里插入图片描述

RabbitMQ高可用——镜像集群

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

在这里插入图片描述

5.如何保证消息不丢失

1.考察面试者是否清楚消息丢失的原因?

  • 消息生产者没有成功发送到MQ Broker
  • 消息发送给MQ Broker后,Broker宕机导致内存中的消息数据丢失
  • 消费者获取到消息,但是还没来得及处理就宕机了,但此时MQ中消息已经被删除,消费者重启后不能再消费之前的消息。

在这里插入图片描述

2.如何保证消息不丢失?

  • 消息发送者发送给MQ Broker后,MQ Broker给生产者确认收到
  • MQ收到消息后进行消息持久化(还没持久化就宕机了,消息就丢失了,很少遇到,可以用集群同步)
  • 消费者收到消息处理完毕后手动进行ack确认
  • MQ收到消费者ack确认后删除持久化的消息

在这里插入图片描述

6.如何保证消息队列不被重复消费?(如何保证消息的幂等性?)

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

1.面试者对重复消息产生原因的思考

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

  • 发送时消息重复

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

  • 消费时消息重复

消费消息的场景下,消息已投递到消费者并完成业务处理,当消费方给MQ服务端反馈应答的时候网络闪断。为了保证消息至少被消费一次,MQ服务端将在网络恢复后再次尝试投递之前已被消费方处理过的消息,此时消费者就会收到两条内容相同的消息。

2.面试者对保证消息幂等性的方案

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

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

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

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

例如:一笔订单产生了3条消息,分别是订单创建、订单付款、订单完成。

消费时,要按照顺序依次消费才有意义。

与此同时多笔订单之间又是可以并行消费的。

  • 全局顺序消费

生产者:MQ:消费者=1:1:1

可以保证全局顺序性 但是吞吐量下降,容错性降低

  • 局部顺序消费

生产者根据消息发送到一个Queue中

多个消费者同时获取Queue中的消息进行消费

MQ使用分段锁保证单个Queue中的有序消费

在这里插入图片描述

8.分布式事务

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

本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
在这里插入图片描述

消息发送方:

1.处理业务逻辑

2.保存消息到本地数据库

3.发送消息给MQ

4.监听MQ消息方通知消息,更改消息状态为已处理

5.定时任务将长期未处理消息重新发送到MQ

消息消费方:

1.监听MQ中间件消息

2.判断消息是否重复,重复就丢弃

3.消息未重复,执行本地业务

4.业务处理完毕,写消息记录到本地数据库

5.发送通知消息到MQ

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值