MQ消息中间件常见题及解决办法

常见MQ

在这里插入图片描述
在这里插入图片描述

RocketMQ

RocketMQ又四部分组成

  • NameServer 同步Broker服务信息,给消费者和生产者提供可用Broker的服务信息。
  • Broker 消息存储业务核心
  • Producer 消息生产者
  • Consumer 消息消费者

先启动NameServer作为注册中心,然后再启动Broker服务。

2、RocketMQ测试可用

RocketMQ的安装包中,提供了一个tools.sh工具可以用来在命令行快速验证RocketMQ服务。进入RocketMQ的安装目录:
① 首先需要配置一个环境变量NAMESRV_ADDR指向我们启动的NameServer服务。

export NAMESRV_ADDR='localhost:9876'

② 然后执行工具脚本,启动消息生产者发送消息:默认会发1000条消息

bin/tools.sh org.apache.rocketmg.example.quickstart.Producer

③ 然后执行工具脚本,然后启动消息消费者接收消息

bin/tools.sh org.apache.rocketmg.example.quickstart.Consumer

成功了表单机服务就搭建好了

MQ常见问题

1、幂等性问题

通常。客户端调用服务端接口是通过http协议来调取的,不安全且整个调用过程是一个同步过程。服务端处理业务逻辑比较耗时没有及时响应的情况下,于服务端而言产生了请求堆积,可能会造成 服务雪崩。于客户端会造成阻塞等待、超时断开 自动重试,这样服务器端接口就在一段时间内接收到了n个相同的请求,产生了 幂等性问题

如何防止幂等性问题,通用做法:

  • 如表单重复提交、add表数据,可以用全局id做唯一约束
  • 如重复update表数据,可以用版本号防止重复修改,每次修改都基于版本号

在这里插入图片描述

  1. 幂等性:
    所谓的幂等性,是分布式环境下的一个常见问题,一般是指我们在进行多次操作时,所得到的结果是一样的,即多次运算结果是一致的(同一个业务逻辑重复执行多次最终只算一次)。
    也就是说,用户对于同一操作,无论是发起一次请求还是多次请求,最终的执行结果是一致的,不会因为多次点击而产生副作用。
  2. 常见幂等性操作:
    • select查询天然幂等;
    • delete删除也是幂等,删除同一个数据多次其效果一样;
    • update直接更新某个值时,幂等;
    • update更新累加操作的的结果,非幂等;
    • insert操作会每次都新增一条,非幂等;
  3. 什么情况下会产生重复提交(非幂等性):
    • 连续点击提交两次按钮;
    • 点击刷新按钮;
    • 使用浏览器后退按钮重复之前的操作,导致重复提交表单;
    • 使用浏览器历史记录重复提交表单;
    • 浏览器重复地HTTP请求等。

2、如何保证消息不丢失

在这里插入图片描述
引入MQ消息中间件最直接的目的是:做系统解耦合流量控制,追其根源还是为了解决互联网系统的高可用和高性能问题
在这里插入图片描述
引入MQ虽然实现了系统解耦合流量控制,也会带来其他问题
在这里插入图片描述
其中保证数据传输的一致性就是保证消息不丢失的关键

消息从生产到消费不同环节发生消息丢失对应的原因不同,解决方案也不同,所以要分开来说
在这里插入图片描述
在这里插入图片描述
上面三个环节的解决方案看似完美,但在分布式系统中,常常出现各种故障,且不可避免,所以还是需要一种机制,来检查消息是否丢失

总体方案思路:
在消息生产端,给每个发出的消息都指定一个全局唯一D或者附加一个连续递增的版本号,然后在消费端做对应的版本校验

具体实现思路1:
可以利用拦截器机制,在生产端发送消息之前,通过拦截器将消息版本号注入消息中,然后在消费端收到消息后,再通过拦截器检测版本号的连续性或消费状态,这样实现的好处是消息检测的代码不会侵入到业务代码中,可以通过单独的任务来定位丢失的消息,做进一步的排查
在这里插入图片描述
不同的唯一ID生成方案也会有不同的问题存在,没有完美的方案。
在这里插入图片描述

3、消息积压问题

如果出现积压,那一定是性能问题,想要解决消息从生产到消费上的性能问题就首先要知道哪些环节可能出现消息积压,然后在考虑如何解决。

因为消息在生产并发送到Broker之后才会出现积压问题,所以问题不在生产端,而又因为在绝大部分消息队列单节点性能都能达到几万/s的处理能力,所以问题大概率也不在存储端上。所以性能问题绝大多数出现在消费端。

应急处理方案:
如果是线上突发问题,就要临时扩容,增加消费端的数量(水平扩容),与此同时,还可以降级一些非核心的业务,通过扩容和降级抗住流量。

扩容的同时要增加分区,防止扩容失效。

逻辑优化方案:
排查解决异常问题,比如通过查看监控,日志等手段分析是否消费端的业务逻辑代码出现了问题,进而优化消费端的业务处理逻辑,提升消费能力。

4、事务消息设计分析

如下场景:用户操作下单,我们首先需要生成一条订单信息,然后库存系统需要针对订单中的商品进行库存扣减的操作。这两步操作必须保证数据的一致性,否则会出现库存超扣等情况。

第一种情况如图所示,在本地事务提交前发送事务消息。若在创建订单信息时发生了异常,而此时事务消息已经成功发送,库存系统消费事务消息就会导致订单并没有创建成功,而库存却被扣减。
在这里插入图片描述
进而有了第二种情况,如图所示,在本地事务提交完成后再发送事务消息。若在发送事务消息的过程发生了异常,如网络波动等等,将会出现订单已创建完成,而库存系统永远也监听不到消息,导致库存无法正常扣减。
在这里插入图片描述综合第一和第二种情况,汇总成第三种方案如图所示。在本地事务执行前,先向MQ发送前置的Prepared消息,在本地事务执行完毕后,再发送确认的消息,告知MQ当前事务消息需提交/回滚。如果事务正常则提交消息,那么这条消息将会被消息消费方监听到;如果事务回滚,MQ会丢弃这条消息,消息消费方无法监听到这条消息。以上情况对应 事务消息生产者的设计思路 图中的 1、2、3、4步骤。
在这里插入图片描述
继续分析,如果上图的第二步中,发送确认消息的过程中,出现异常,没有发送成功怎么办?RocketMQ会定期(默认60s)扫描Prepared消息,如果迟迟没有收到确认消息,将会执行事务回查的逻辑,主动去消息生产方确认事务状态。对应 事务消息生产者的设计思路 图中的 5、6、7步骤。综上,是事务消息中生产者的设计思路,保证本地事务和事务消息一致性。
在这里插入图片描述
如上图中,在事务消息者中,如果步骤4返回了消费失败或者超时未响应的情况,怎么办?RocketMQ对待事务消息的处理和普通消息一样。如果消费失败或超时,将会把这条消息加入到重试队列中,不断是重复执行步骤3、4,如果重复的次数达到阈值,那么可能需要人工介入处理。

如果消费方本地事务执行成功,仅仅是在确认消息时失败呢? 那么这里又会出现另一个问题 重复消费? 这里就需要具体的业务模块去处理消息的幂等性。如接住Redis来处理。如在本地事务执行前先去查询redis中当前消息是否已经消费,执行成功后再向redis写入一条成功消费的记录,这样就能保证消费不会被重复消费了。

参考资料:

  1. 哔哩哔哩 余胜军 BAT大厂消息中间件MQ,常见面试题及答案,你能搞懂有哪些?
    https://www.bilibili.com/video/BV1zK4y1e7kS?share_source=copy_web
  2. 如何解决幂等性问题? - Java马剑威的回答 - 知乎
    https://www.zhihu.com/question/534651475/answer/2542377973
  3. 哔哩哔哩 so贝塔 MQ:如何回答消息队列的丢失、重复与积压问题
    https://www.bilibili.com/video/BV1F8411g7LF?share_source=copy_web
  4. 哔哩哔哩 图灵教育-诸葛 这可能是B站讲的最好的RocketMQ实战教程全套完整版(2023年最新版)
    https://www.bilibili.com/video/BV1DY41127Be?p=2&share_source=copy_web
    5.CSDN Rooibos gron RocketMQ事务消息
    https://blog.csdn.net/qq_42877546/article/details/125404307
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用MQ消息中间件的优势在于它可以让发送和接收消息的应用程序解耦,异步地进行消息传递。MQ消息中间件还可以提供可靠的消息传输,支持各种消息模式,提供灵活的消息路由,支持可靠的消息重试,可以提供高吞吐率的消息处理等优势。 ### 回答2: 使用消息中间件MQ)的主要原因是为了解决分布式系统中的异步通信和解耦的问题,提高系统的可靠性、可扩展性和性能。以下是MQ的几个重要优势: 1. 异步通信:MQ提供了异步通信的机制,可以让发送方和接收方在时间上解耦。发送方把消息发送到MQ后,可以立即继续自己的工作,而不需要等待接收方的响应。这对于处理高并发请求和处理耗时任务非常有帮助。 2. 解耦:MQ能够将发送方和接收方解耦,发送方只需要关注把消息发送到MQ中,而不需要知道实际的接收方是谁。同样,接收方只需要从MQ中获取消息,而不需要知道消息的发送方是谁。这样可以提高系统的灵活性和可维护性。 3. 可靠性:MQ提供消息持久化的机制,确保即使在发送方和接收方的故障或者断电情况下,消息仍然能够被保存下来,并在故障恢复后重新传递。同时,MQ还提供了事务和回滚的机制,保证消息的可靠性传递。 4. 可扩展性:MQ具有高度的可扩展性,可以根据实际需求添加更多的消息生产者和消费者。同时,MQ还支持多种消息传递模式,如发布/订阅、点对点等,可以根据不同的业务场景选择合适的模式。 5. 削峰填谷:通过将消息缓存到MQ中,可以平滑处理系统的高峰请求和突发流量,避免系统的负载过高。同时,MQ还支持消息的优先级和延时发送,可以更好地满足不同类型的消息需求。 总之,使用MQ消息中间件可以提供异步通信、解耦、可靠性、可扩展性和削峰填谷等优势,帮助构建高性能、高可靠性的分布式系统。 ### 回答3: MQ消息中间件(Message Queue)是一种用于处理消息的软件架构,它被广泛应用于分布式系统和异步通信中。使用MQ消息中间件的主要原因有以下几点: 1. 解耦:使用消息中间件能够将系统中不同模块之间的通信解耦,即发送方和接收方之间不直接依赖于彼此的存在。发送方只需要将消息发送到队列中,而不需要关心具体的接收方是谁。这种解耦能够提高系统的可扩展性和可维护性。 2. 异步通信:消息中间件支持异步通信模式,即发送方发送消息后就可以继续处理其他任务,不需要等待接收方返回响应。这种方式可以提高系统的性能和吞吐量,同时也能降低系统之间的耦合度。 3. 缓冲与削峰:消息中间件能够缓冲消息,当接收方无法立即处理消息时,消息会暂时存储在队列中,等待接收方空闲时再进行处理。这种缓冲能够平衡系统中不同模块之间的处理速度差异,并且能够应对突发性的请求,避免系统过载。 4. 可靠性与持久化:消息中间件支持消息的持久化存储,保证消息不会因为系统故障或中断而丢失。即使在消息发送后出现问题,通过重新发送机制,消息仍然能够被接收方正确处理,保证消息的可靠性。 5. 可拓展性:消息中间件能够支持高并发和高可用的应用场景,通过多个消息队列实例的部署,能够实现水平扩展和负载均衡,提高系统的可拓展性。 综上所述,使用消息中间件的优势包括解耦、异步通信、缓冲与削峰、可靠性与持久化以及可拓展性。这些优势能够提高系统的性能、可用性和可维护性,使得分布式系统更加稳定和灵活。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值