关于MQ

136 阅读4分钟

先学点基础🙌🙌🙌

image.png 消息的三个过程:

  • 消息生产阶段: 从消息被生产出来,然后提交给 MQ 的过程中,只要能正常收到 MQ Broker 的 ack 确认响应,就表示发送成功,所以只要处理好返回值和异常,这个阶段是不会出现消息丢失的。
  • 消息存储阶段: 这个阶段一般会直接交给 MQ 消息中间件来保证
  • 消息消费阶段: 消费端从 Broker 上拉取消息,只要消费端在收到消息后,不是立即发送消费确认给 Broker,而是等到执行完业务逻辑后,再发送消费确认,也能保证消息的不丢失

面试必背:消息丢失😍

发送端怎么保证中间件是否保存了消息,消费者是否消费了消息

解决:进行消息检测

总体方案解决思路为:在消息生产端,给每个发出的消息都指定一个全局唯一 ID,然后在消费端做对应的版本校验。

具体落地:利用拦截器机制,在生产端发送消息之前,通过拦截器将消息版本号注入消息中。

然后在消费端收到消息后,再通过拦截器检测版本号的连续性或消费状态。

面试必背:重复消费😭

问题背景:在消息消费的过程中,如果出现失败的情况,通过补偿的机制发送方会执行重试,重试的过程就有可能产生重复的消息

幂等设计。 即相同的请求参数,请求1次,和请求100W次,得到的结果和对业务的影响是一样的。

幂等处理的核心:存储+唯一key 。在进行业务处理时,查询下是否已处理过这个唯一key的消息;如果存在就不进行后续业务处理;如果不存在就继续后续业务的处理吧

举个例子:

image.png

我们可以在数据库中建一张消息日志表

这个表有两个字段:消息 ID 和消息执行状态。

这样,我们消费消息的逻辑可以变为:在消息日志表中增加一条消息记录,然后再根据消息记录,异步操作更新用户京豆余额。

因为我们每次都会在插入之前检查是否消息已存在,所以就不会出现一条消息被执行多次的情况,这样就实现了一个幂等的操作。

基于这个思路,不仅可以使用关系型数据库来进行强校验,也可以通过 Redis 来代替数据库实现唯一约束的方案(弱校验,可能会出现幂等校验穿透的问题)。

解决“消息丢失”和“消息重复消费”的问题,有一个前提条件就是要实现一个全局唯一 ID 生成的技术方案。

好孩子必背:消息积压😊

消息积压反映的是性能问题

如果出现积压,那一定是性能问题

因为消息发送之后才会出现积压的问题,所以和消息生产端没有关系,

又因为绝大部分的消息队列单节点都能达到每秒钟几万的处理能力,相对于业务逻辑来说,性能不会出现在中间件的消息存储上面。

毫无疑问,出问题的肯定是消息消费阶段,那么从消费端入手:

如果是线上突发问题,要临时扩容,增加消费端的数量,与此同时,降级一些非核心的业务。通过扩容和降级承担流量,这是为了表明你对应急问题的处理能力。

其次,才是排查解决异常问题,如通过监控,日志等手段分析是否消费端的业务逻辑代码出现了问题,优化消费端的业务处理逻辑。

最后,如果是消费端的处理能力不足,可以通过水平扩容来提供消费端的并发处理能力