【消息队列】RabbitMQ 常见问题

🎗️ 主页:小夜时雨
🎗️专栏:消息队列
🎗️如何活着,是我找寻的方向

优雅

1. 如何解决 RabbitMQ 消息的重复消费问题?

这个涉及到幂等性问题, 什么是幂等性?
在程序开发中,指的是同一个业务,执行一次和执行多次得到的结果是一样的。比如:

  • 根据 id 删除数据
  • 查询数据

根据 id 删除数据删除一次和多次结果都是把这个数据给删掉,查询就是幂等的,查询期间没有其他操作,查询一次和多次的结果也是一样的。

但数据的更新往往不是幂等的,如果重复执行就可能是不一样的结果。比如:

  • 取消订单,恢复库存的业务。如果多次执行恢复操作,就会出现库存重复增加的情况
  • 退款业务,重复退款肯定是不行的

实际场景中,可能由于意外会出现一些业务被重复执行的情况,比如:

  • 页面卡顿时频繁刷新导致表单重复提交
  • MQ 消息的重复投递

保证消息处理的幂等性,有两种方式:

  1. 唯一消息 id
  2. 业务状态判断

唯一消息ID

这个思路和实现都是比较简单的,也是比较通用:

  1. 每条消息都会生成一个唯一 id, 与消息绑定在一起发送到交换机和队列
  2. 消费者收到消息之后,根据唯一id进行判断,数据库中是否存在记录
  3. 不存在记录,则说明是第一次处理消息,那就处理消息,成功后将消息ID存到数据库中
  4. 存在记录,则说明收到的是相同的消息已经处理过了,那就放弃处理消息

这种方式也有缺点:

  • 消费者收到消息之后,需要多做一步判断,并把消息id保存到数据库中,有一个读写和判断的业务操作。

实现方式:
SpringAMQP的MessageConverter自带了MessageID的功能,我们只要开启这个功能即可。
以Jackson的消息转换器为例:

@Bean
public MessageConverter messageConverter(){
    // 1.定义消息转换器
    Jackson2JsonMessageConverter jjmc = new Jackson2JsonMessageConverter();
    // 2.配置自动创建消息id,用于识别不同消息,也可以在业务中基于ID判断是否是重复消息
    jjmc.setCreateMessageIds(true);
    return jjmc;
}

根据业务判断

  • 这个要根据不同的业务逻辑来进行判断,有点类似于乐观锁的实现思路。
    消费者处理之前,先去查一下这条消息处理之后的状态是否被修改了。
  • 例如订单业务,业务逻辑是把订单状态从未支付修改为已支付。
    因此我们就可以在执行业务时判断订单状态是否是未支付,如果不是未支付则证明订单已经被处理过,无需重复处理。

2. 如何保证RabbitMQ消息的顺序性

要求消费消息有一定的顺序性,消费者消费的顺序和消息在队列中的顺序是一样的
顺序错乱的情况:

  • 生产者发送三个消息到MQ中, 这个消息在队列中肯定是有顺序的。
  • 但是假如有多个消费者绑定这一个队列进行消费消息(图中下面那个队列),各个消费者处理消息的能力都是不同的。
  • 就有可能出现消费者2先处理了消息3,此时消费者3还在处理消息2的情况。此时消费消息就不是有顺序性的了
    在这里插入图片描述
    解决方法:
  • 让每个队列只绑定一个消费者,这样消费者取消息消费就肯定是有序的了,没有别的消费者进行抢着消费,但是这样可能会造成处理消息的速度变慢。

3. 如果有100万条消息堆积在RabbitMQ中,如何解决?

如果发生了一些堆积问题,可以利用RabbitMQ本身的一些机制来进行解决:

  • 可以在消费端利用多线程来提高消费消息的速度
  • 使用工作队列模式,设置多个消费者消费同一个队列中的消息,增加更多消费者,提高消费速度。
  • 扩大队列容积,提高堆积上限。
    可以使用RabbitMQ惰性队列,惰性队列的好处主要是:
    ①接收到消息后直接存入磁盘而非内存
    ②消费者要消费消息时才会从磁盘中读取并加载到内存
    ③支持数百万条的消息存储。 这个是非常重要的,使用之前的MQ持久化方式存不到百万条消息

🎗️🎗️🎗️ 好啦,有关 RabbitMQ 部分面试题的分享就到这里了,如果感觉做的还不错的话可以点个赞,关注一下,你的支持就是我继续下去的动力,我们下期再见,拜了个拜~ ☆*: .。. o(≧▽≦)o .。.:*☆

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值