RocKetMQ入门(三)--引入MQ的常见问题与解决思路

我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!

本来想要写RocketMQ核心基础使用的,涉及的概念和代码比较多;

因为这段时间都是找房子找工作的事前,实在抽不出时间了;

跳过了第二篇先发第三篇了;

本篇主要是讲引入MQ后会出现的问题和解决思路;其实和这个里每一个问题都可以拿出来细说的

鉴于时间问题,我在此先大概描述问题和解决思路;

上篇文章: RocKetMQ入门(一)--小白也能看懂 - 掘金 (juejin.cn)

一、引入MQ会有哪些问题?

引入mq后让我们子系统间耦合性降低了,异步处理机制减少了系统的响应时间,同时能够有效的应对请求峰值问题,提升系统的稳定性。

但是,引入mq同时也会带来一些问题。

1.1 重复消息问题

重复消费问题可以说是mq中普遍存在的问题,不管你用哪种mq都无法避免。

有哪些场景会出现重复的消息呢?

  • 消息生产者产生了重复的消息
  • 消息消费者确认失败
  • 消息消费者确认时超时了
  • 业务系统主动发起重试

image-20210906151111420.png

如果重复消息不做正确的处理,会对业务造成很大的影响,产生重复的数据,或者导致数据异常,比如会员系统多开通了一个月的会员。

1.2 数据一致性问题

很多时候,如果mq的消费者业务处理异常的话,就会出现数据一致性问题。比如:一个完整的业务流程是,下单成功之后,送100个积分。下单写库了,但是消息消费者在送积分的时候失败了,就会造成数据不一致的情况,即该业务流程的部分数据写库了,另外一部分没有写库。

情况一:

image-20210906153552879.png

情况二:

image-20210906153820006.png

如果下单和送积分在同一个事务中,要么同时成功,要么同时失败,是不会出现数据一致性问题的。

但由于跨系统调用,为了性能考虑,一般不会使用强一致性的方案,而改成达成最终一致性即可。

1.3 消息顺序问题

有些业务数据是有状态的,比如订单有:下单、支付、完成、退货等状态,如果订单数据作为消息体,就会涉及顺序问题了。如果消费者收到同一个订单的两条消息,第一条消息的状态是下单,第二条消息的状态是支付,这是没问题的。但如果第一条消息的状态是支付,第二条消息的状态是下单就会有问题了,没有下单就先支付了? image-20210906100937347.png 如果消费者使用多线程消费消息,也无法保证顺序。

1.4 消息堆积

如果消息消费者读取消息的速度,能够跟上消息生产者的节奏,那么整套mq机制就能发挥最大作用。但是很多时候,由于某些批处理,或者其他原因,导致消息消费的速度小于生产的速度。这样会直接导致消息堆积问题,从而影响业务功能。

image-20210906154330752.png

这里以下单开通会员为例,如果消息出现堆积,会导致用户下单之后,很久之后才能变成会员,这种情况肯定会引起大量用户投诉。

二、如何解决这些问题?

2.1 重复消息问题

不管是由于生产者产生的重复消息,还是由于消费者导致的重复消息,我们都可以在消费者中解决这个问题,这就要求消费者在做业务处理时,要做幂等设计。

在这里我们讲解使用消费消息表来解决mq的这类问题。消费消息表中,使用messageId唯一索引,在处理业务逻辑之前,先根据messageId查询一下该消息有没有处理过,如果已经处理过了则直接返回成功,如果没有处理过,则继续做业务处理。

image-20210906155051688.png

2.2 数据一致性问题

情况一:

image-20210906153552879.png

针对情况一,属于消息消费者在消费消息的时候出现异常,导致数据不一致的情况.

消息消费失败之后,消息是会进行自动重试,我们只要保证接口的幂等性就可以了.消费者这段它照1S,5S,10S,30S,1M,2M····2H进行重试,最大重试次数为16次,RocketMQ 会在达到最大重试次数之后,将该消息投递至死信队列(死信队列topic名为: %DLQ%+consumerGroup),然后我们需要关注死信队列,并对该死信消息业务做人工的补偿操作。

image-20220225174706443.png

情况二:

image-20210906153820006.png

针对情况二,在订单系统中往MQ发送消息了,但是自己本地事务异常了,导致订单没创建,但是消息发送到MQ中了,最终积分是增加了,最终导致数据不一致的情况.

这种情况,我们可以使用RocketMQ的事务消息来解决这个问题.

image-20210906161924511.png

2.3 顺序消息

RocketMQ默认是支持顺序消息的,但是需要我们在生产者和消费者做一些设置才能实现顺序消息的功能.

RocketMQ为了增加发送和消费的并发能力,针对每一个Topic都有4个写队列和4个读队列.

ff1dd8ef93360037fb2d0aefe9e9cae5.png

2.4 消息堆积

如果消费者消费消息的速度小于生产者生产消息的速度,将会出现消息堆积问题。

首先我们需要定位消息的积压的问题,如果之前消费情况正常,由于消费者消费的内部的异常,导致消息积压了.当我们解决了消费异常之后,消费者速度应该是大于等于生产者速度的,但是由于积压太多消息,导致新的消息无法及时消费,此时我们需要判断消息的重要程度,如果消息不怎么重要,我们可以把之前的消息都删除掉。如果比较重要不能删除,我们需要增加消费者集群来加大消费的速度.

有可能出现以下几种情况:

1.的确消费者的速度很慢

  • 增加消费者的集群数量

2.消费者内部逻辑出现问题,导致消费速度比平时的速度要慢

  • 定位消费者的内部的问题,问题解决了,变回正常速度

    此时恢复正常速度,目前队列的中消息是都重要,不重要

3.业务高峰,导致生产这个速度比平时要快

  • 采取限流
  • 增加消费者的集群数量

Supongo que te gusta

Origin juejin.im/post/7068588239585542152
Recomendado
Clasificación