1、MQ的应用场景及解决的问题、作用、好处?

使用MQ的前提:请求不要求立即得到执行结果

1.1系统解耦

image.png
使用MQ进行解耦,商品服务把提供的数据发送到RabbitMQ中,搜索服务、订单服务、库存服务之需要从对应的队列中拉取所以需要的数据即可,二不需要强依赖与商品服务

1.2异步处理

image.png
由串行执行变为异步执行,提高代码执行效率;

1.3故障隔离

image.png
服务即便宕机不会影响主体业务使用

1.4流量削峰

image.png
消息在队列中等待,服务器可根据性能逐步消费

1.5日志处理

image.png
Kafka 最开始就是专门为了处理日志产生的。

2、常见的MQ及性能对比?

image.png

3、不同类型的MQ在项目中使用会存在什么问题?你们是如何解决的?

MQ在项目中的问题:当要在项目中替换MQ类型时,如从rabbitMq转为RoocketMq
1、开发人员的学习成本 和项目开发的成本
2、系统和MQ之间的耦合

解决方法:
在项目中,我们使用SpringCloude Stream 来整合各类消息中间件,降低系统和中间件的耦合性

4、SpringCloude Stream的核心概念?

image.png

组成 说明
Middleware 中间件,支持 RabbitMQ、Kafka、RocketMQ等。
Binder 目标绑定器,目标指的是 Kafka 还是 RabbitMQ。绑定器就是封装了目标中间件的包。如果操作的是 Kafka 就使用 spring-cloud-stream-binder-kafka,如果操作的是 RabbitMQ 就使用 spring-cloud-stream-binder-rabbit。
@Input 注解标识输入通道,接收(消息消费者)的消息将通过该通道进入应用程序。
@Output 注解标识输出通道,发布(消息生产者)的消息将通过该通道离开应用程序。
@StreamListener 监听队列,消费者的队列的消息接收。
@EnableBinding 注解标识绑定,将信道 channel 和交换机 exchange 绑定在一起。

5、SpringCloude Stream的工作原理?

image.png
该模型图中有如下几个核心概念:

  • Source:当需要发送消息时,我们就需要通过 Source.java,它会把我们所要发送的消息进行序列化(默认转换成 JSON 格式字符串),然后将这些数据发送到 Channel 中;
  • Sink:当我们需要监听消息时就需要通过 Sink.java,它负责从消息通道中获取消息,并将消息反序列化成消息对象,然后交给具体的消息监听处理;
  • Channel:通常我们向消息中间件发送消息或者监听消息时需要指定主题(Topic)和消息队列名称,一旦我们需要变更主题的时候就需要修改消息发送或消息监听的代码。通过 Channel 对象,我们的业务代码只需要对应 Channel 就可以了,具体这个 Channel 对应的是哪个主题,可以在配置文件中来指定,这样当主题变更的时候我们就不用对代码做任何修改,从而实现了与具体消息中间件的解耦;
  • Binder:通过不同的 Binder 可以实现与不同的消息中间件整合,Binder 提供统一的消息收发接口,从而使得我们可以根据实际需要部署不同的消息中间件,或者根据实际生产中所部署的消息中间件来调整我们的配置。

6、SpringCloude Stream的快速入门?

6.1分组消息

有多个消费者的情况,消息会被重复消费,比如,下单扣减库存,采用集群部署,每个库存服务都去监听订单信息,就会导致一个订单消息被同时消费,出现库存量错误。可通过Stream分组消息解决,同一个组中的服务互相竞争,保证消息只会被一个服务消费。
image.png

6.2分区消息

分组消息能解决消息重复消费问题,但无法统计同一个用户的消息消费记录,因为消息是随机被消费的。鉴于此,Stream提供了分区消息,根据用户id进行分区,类似hash一致性。
image.png

6.3延迟队列

延迟消息:是指消息发到 Broker 后,不能立刻被 Consumer 消费,要到特定的时间点或者等待特定的时间后才能被消费。
应用场景:

  • 订单超时未支付,30分钟后取消订单
  • 添加购物车扣减库存,30分钟后删除购物车回滚库存

在 RabbitMQ 中,我们可以通过使用 rabbitmq-delayed-message-exchange 插件提供的定时消息功能。

7、添加菜品至购物车的优化方案?

问题:添加购物车后,长期不下订单,如果不做库存处理会占用库存
解决方案:

  • 改变库存扣减的时机:用户在下单的时刻完成库存的扣减
  • 给购购物车设置过期时间,到期后立刻删除购物车菜品数据并回滚菜品库存(项目采用)

具体实现流程:
image.png
3.解析消息,获取消息中的菜品id和订单编号*

  1. 加入购物车成功发送延迟消息(30分钟有效)- CartSource
  2. 消息监听延迟消息-CartSink
  3. 接收到消息后解析消息内容获取消息中菜品id和订单编号

3.1 回滚数据库菜品库存
3.2 回滚redis中的库存
3.3 删除购物车中对应的菜品

流程中存在bug:
目前是用户添加菜品至购物车,30分钟中后,不做任何判断即回滚库存;
解决方案:接收到消息后,先判断菜品id是否已下订单,下订单会直接结束方法;
未下订单则回滚