中间件 - 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();
    }
}
相关推荐
NAGNIP14 小时前
万字长文!回归模型最全讲解!
算法·面试
qq_3181215914 小时前
互联网大厂Java面试故事:从Spring Boot到微服务架构的技术挑战与解答
java·spring boot·redis·spring cloud·微服务·面试·内容社区
且去填词16 小时前
Go 语言的“反叛”——为什么少即是多?
开发语言·后端·面试·go
青莲84318 小时前
RecyclerView 完全指南
android·前端·面试
青莲84318 小时前
Android WebView 混合开发完整指南
android·前端·面试
37手游后端团队1 天前
gorm回读机制溯源
后端·面试·github
C雨后彩虹1 天前
竖直四子棋
java·数据结构·算法·华为·面试
CC码码1 天前
不修改DOM的高亮黑科技,你可能还不知道
前端·javascript·面试
你好龙卷风!!!1 天前
rabbitMQ入门 (mac)
macos·rabbitmq·ruby
indexsunny1 天前
互联网大厂Java面试实战:微服务、Spring Boot与Kafka在电商场景中的应用
java·spring boot·微服务·面试·kafka·电商