中间件 - RabbitMQ

前言

14题。

你的项目中哪里用到了RabbitMQ?

微服务间异步通信

之前做过一个项目,它有网页端和配套的app端,有一个新闻类的页面,用于展示一些行业相关新闻。这个项目的服务间通信使用了两种技术:

  1. 通过Feign实现服务的同步调用(需要返回数据);
  2. 通过MQ实现服务的异步通信(不需要返回数据)。

当网页端或app端上线一篇新闻,或下线一篇新闻的时候,就通过MQ异步通信给另一端令其也上线或下线该新闻。

流量削峰

比如你现在去开发哔哩哔哩,每一个视频都会有点赞功能,全站有几千万的视频,每个视频都可能有不知道多少人去点赞,这就是一个高并发操作。

但是点赞又没有那么重要,不需要太强的实时性,此时就可以把点赞或点踩操作扔进mq里,让消费者慢慢消费,从而降低流量。

为什么会选择使用RabbitMQ?

RabbitMQ的优点是:耦合极低,通过异步让响应更快,并发量高还可以做流量削峰。

但是也有缺点:架构复杂,不好管理,需要依赖于Broker

RabbitMQ的持久化

RabbitMQ的持久化分为三个部分:交换机 的持久化、队列 的持久化和消息的持久化。

  1. 交换机 的持久化,将durable的参数设置为true

交换机的持久化是我们在声明交换机的时候,将durable的参数设置为true实现的。也就是将交换机的内部属性在服务器的内部保存,当MQ服务器发生重启之后,不需要去重新建立交换机,交换机会根据服务器中保存的交换机的属性来自动创建。

  1. 队列 的持久化,设置durable属性为true

队列的持久化也是我们在声明队列的时候设置durable的参数来实现的。队列的持久化能保证队列的元数据不会因异常情况而丢失,但是并不能保证内部所存储的消息不会丢失,要确保消息不会丢失,还需要设置消息为持久化。

  1. 消息的持久化

实现消息持久化,需要把消息的投递模式设置为2,也就是MessageDeliveryMode.PERSISTENT

使用RabbitMQ如何保证消息不丢失?

消息丢失是无法找回的,所以只能避免:

  1. 生产者 :开启确认机制,出现错误就会开启Spring的重试机制,重试次数到达限制后(3-5次)将消息放入到Mysql,用xxl-job定时任务读取数据库中的数据,再次发送,发送成功移除该消息;

  2. MQ本身:做持久化,参考上一条,

  3. 消费者 :默认开启自动确认机制,用MQ自带的重试机制,到达重试次数后把消息存到一个error队列中,人工处理手动删除消息(项目中用的是这个)。

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

  1. 给每条消息设置一个唯一的标识 id,然后消费者检查该id是否存在(token+redis);

  2. 幂等方案:分布式锁、数据库锁(悲观锁、乐观锁),性能低不推荐。

如何解决消息堆积在MQ的问题?

增加使用效率,到达一定效率就不容易堆积了。

  1. 添加消费者;

  2. 扩大容积;

  3. 使用惰性队列,直接把数据放到磁盘。

RabbitMQ如何保证消费的顺序性?

MQ中,消息是有序的,但是多个消费者无法保证有序,因此一个队列只设置一个消费者消费就可以保证顺序。

RabbitMQ如何实现延迟队列?

延迟队列,即消息进入队列后不会立即被消费,只有到达指定时间后,才会被消费。RabbitMQ本身没有提供延迟队列功能,有两种实现方式。

  1. TTL+死信交换机

将消息发送到TTLTime-To-Live,生存时间)队列,消息的TTL值就是延迟时间。当消息在队列中的存活时间超过TTL值时,自动变成死信(如果配置了死信交换机和队列),随后这些死信就可以被发送到死信队列,从而实现了延迟队列的效果。只需要监听这个死信队列,消费这个死信队列的消息就可以了。

  1. 引入延迟消息插件

RabbitMQ如何设置消息过期?

存在以下两种方式:

  1. 消息所在队列设置了超时时间;

  2. 消息本身设置了超时时间。

什么是死信交换机?

死信交换机用来处理无法被正确路由、消费的消息,死信指的是消息被消费者拒绝或返回nack/消息超时未消费/队列满了。如果队列绑定了死信交换机,死信就会投递过去交由人工处理,进一步提高消息队列的可靠性。

RabbitMQ的集群有哪些?

RabbitMQ天然支持集群模式,它的集群有两种模式:

  • 普通集群:是一种分布式集群,将队列分散到集群的各个节点,从而提高整个集群的并发能力;

  • 镜像集群:是一种主从集群,普通集群的基础上,添加了主从备份功能,提高集群的数据可用性。

RabbitMQ的工作模式?

RabbitMQ共有六种工作模式,分别是:

  1. 简单模式 :一个⽣产者P,⼀个消费者C,消息只能被消费⼀次,也称为点对点(Point-to-Point)模式。
  2. ⼯作队列模式 :一个生产者(P), 多个消费者(C), 消息队列会将消息平均分配给消费者。
  3. 发布/订阅模式 :使用fanout类型交换机,将消息交给所有绑定到交换机的队列(发布/订阅模式)。交换机将消息复制多份,并且发送多个消费者,并且每个消费者收到相同的信息。
  4. 路由模式 在发布订阅模式的基础上增加了路由key。发布订阅模式是⽆条件的将所有消息分发给所有消费者,路由模式是Exchange(交换机)根据RoutingKey的规则,将数据筛选后发给对应的消费者队列。⽐如系统打印⽇志, ⽇志等级分为errorwarninginfodebug,就可以通过这种模式,把不同的⽇志发送到不同的队列,最终输出到不同的⽂件。
  5. 通配符模式 :路由模式的升级版, 在routingKey的基础上,增加了通配符的功能,使之更加灵活。
  6. RPC通信模式 :在RPC通信的过程中,没有⽣产者和消费者,类似于RPC远程调⽤, ⼤概就是通过两个队列实现了⼀个可回调的过程。

RabbitMQ的交换机都有哪些类型?

RabbitMQ支持四种类型的交换机:fanoutdirecttopicheaders。每种交换机类型有不同的路由策略:

  • fanout‌:广播消息给所有绑定的队列。
  • direct‌ :根据RoutingKey将消息路由到特定队列。
  • topic‌ :使用通配符匹配RoutingKey
  • headers‌ :根据消息的headers属性进行路由,但性能较差且不常用‌。

RabbitMq的message(消息)大小和数量边界值?

RabbitMQ默认情况下,单个消息最大为128MB,如果超出,mq会拒绝接收消息并抛出异常。对于总消息大小和消息数量,没有特别限制。

rabbitmq.conf 文件中,可通过下述配置修改:

conf 复制代码
# 设置单个消息的最大大小为 256 MiB
vm_memory_high_watermark.absolute = 268435456

在声明队列时,可以通过 x-max-lengthx-max-length-bytes 参数分别设置队列中消息的数量上限和总大小上限。

java 复制代码
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {

    // 定义队列名称
    public static final String MY_QUEUE = "my_queue";

    @Bean
    public Queue myQueue() {
        return QueueBuilder.durable(MY_QUEUE)
                .withArgument("x-max-length", 10000) // 消息数量上限
                .withArgument("x-max-length-bytes", 104857600) // 消息总大小上限(100 MiB)
                .withArgument("x-message-ttl", 60000) // 消息过期时间(60 秒)
                .build();
    }
}
相关推荐
_一条咸鱼_6 小时前
大厂Android面试秘籍:Activity 窗口管理模块(四)
android·面试·android jetpack
黑客老李7 小时前
面试经验分享 | 成都渗透测试工程师二面面经分享
经验分享·面试·职场和发展
狂炫一碗大米饭7 小时前
快刷每日面经😋
前端·面试
Yharim10 小时前
AllData数据中台源码分析
java·面试
就是我10 小时前
3种必须知道的JavaScript异步编程模型
前端·javascript·面试
_一条咸鱼_10 小时前
Android大厂面试秘籍:不同Android系统版本特性分析
android·面试·android jetpack
Yharim13 小时前
如何编造一个项目经验?
面试
_一条咸鱼_13 小时前
Android大厂面试秘籍: Activity Intent 解析与处理模块(三)
android·面试·android jetpack
9号达人13 小时前
Java 11 新特性详解与实践
java·后端·面试