消息中间件常见问题汇总

上一篇 <<<消息中间件的核心思想
下一篇 >>>基于Netty简单手写消息中间件思路


1.为什么消息中间能够解决流量削峰问题

流量削峰是解决我们的高并发问题。当有大量的请求进入到服务器的时候,会导致服务器的压力很大,甚至会崩掉。可以使用限流的方式,但这样会增加代码量。
Mq有以下优点,可以解决生产者和消费者的问题。
A、Mq可以减少主流程的业务,减少客户端的等待时间。
B、mq有阈值设置,可以防止无限量的涌入。达到阈值后拒绝接收(不确定)
C、Mq不会立马给消费者,消费不了就会进入队列,先进先出
D、消费者可以配置多个,这样就解决了队列的等待。

2.如何保证消息不重复消费(如何保证消息的幂等性问题)

消息重试:---出现异常或长时间未响应,队列就会重试
a、消费者在规定的时间内或者抛出了异常的情况下,导致结果没有响应给消息队列
b、消息队列在没收到结果的情况下就会重试,进而导致重复消费的问题
解决方案:
a、生产者在消息头中设置全局唯一的业务ID,比如消息ID或订单号之类的
b、消费者根据全局唯一的业务ID,判断是否处理过该逻辑,如果处理过就告诉MQ消费成功,不再继续重试。
是否会出现重试的请求和第一次请求产生并发冲突?
答:重试一般的情况下都是有间隔的,一起执行相同代码的概率极低,基本上是可以不用考虑的。

3.如果MQ服务器出现消息堆积的情况下如何处理?

产生原因:
a、生产者向消费者投递和消费的速率不匹配导致。
b、消费者挂了,导致队列阻塞。
解决办法:
核心---提高系统吞吐量才是关键
a、增加broker分区缓存不同的消息/增加MQ的队列数
b、消费者应该使用集群,提高消费的速率
c、生产者投递消息到MQ服务器如果满的情况下,直接换入死信队列,由死信消费者消费。
d、执行客户端回调监听的方法将消息存放到数据库记录,后期实现补偿
Tips:
死信队列所有的队列都是有的,属于备胎,也有消费者消费的
如果MQ的内存、硬盘都满了,那死信队列也是没用的,备胎都没了。

4.消息队列中数据有问题,导致客户端报错如何解决

a、消费者代码异常(解析报文出现问题等),则将该消息存放到数据库或死信队列中,等后期代码修复后在解决,MQ不需要对我们消费者实现重试
b、消费者代码链接数据库、redis或接口调不通的情况下,可以抛出异常,让MQ自动重试。

5.如果MQ服务器满了如何处理?

记录生产者投递的消息日志,后期采用定时job自动化补偿。
日志方式可以是磁盘、数据库、nosql等

6.mq突然产生了消息堆积?mq会崩溃吗?

不会,因为mq大都有阈值设置,超过了就拒绝接收。

7.mq消费者如果不在的情况下,生产者投递消息会丢失吗?

不会,mq队列会自动保存。

8.mq有多个消费者消费,会重复消费吗?

不会,如果存在多个的话,会存在轮询消费,无论是点对点还是工作队列,还是其他各种类型。

9.MQ如何保证消息的顺序问题?

1、如果我们的生产者往MQ投递消息行为不一样,可能会产生消息顺序的问题,如果我们投递的消息到同一个队列中行为是一样的情况下,没有必要在意消息顺序的问题。
2、我们的MQ存放消息默认的情况下本身就有一定的顺序,遵循先进先出的原则(单个MQ情况下)
3、如果我们有多个消费者订阅同一个队列的情况下,可能会产生消费者顺序被打乱
4、如果我们的Broker是集群的情况下,因为不同的消息可能会存放多个不同的Broker中,单个消费者在获取消息的时候顺序可能会被打乱。

解决消息顺序的核心思路:
保证我们的消息存放到同一个Broker中,对应只有一个消费者实现消费;
备注:kafka对我们的消息设置相同给到key,key可以根据业务来定。
但是我们的单个消费者消费消息吞吐非常低,可以采用消费者批量获取我们的消息,然后采用内存队列实现存放。(也会根据消息的key计算,相同的key存放到同一个内存队列中),
每个内存队列只会对应的一个线程实现处理。


推荐阅读:
<<<消息中间件的核心思想
<<<基于Netty简单手写消息中间件思路
<<<消息队列常用名词与中间件对比
<< << << << << << << << << << << << << << << << << << << << << << << << << << << << << << << << <<

你可能感兴趣的:(消息中间件常见问题汇总)