消息队列——RabbitMQ(基础)

一、知识结构图

我是按照黑马的笔记大概整理了一个结构图,用于总体回顾和学习一下,https://b11et3un53m.feishu.cn/wiki/OQH4weMbcimUSLkIzD6cCpN0nvc这是黑马的笔记地址,有需要的同学可以看一下
在这里插入图片描述

二、消息队列的类型

以下是当前常见的消息队列类型及其对比分析,涵盖核心类型、代表实现、关键特性及适用场景:

1.主流消息队列实现对比

维度RabbitMQKafkaRocketMQPulsarActiveMQ
消息模型P2P、发布订阅(基于Exchange)发布订阅(分区Topic)发布订阅(Topic+Tag)发布订阅(支持多租户Topic)P2P、发布订阅(JMS标准)
底层协议AMQP、MQTT、STOMP自定义二进制协议自定义协议(支持HTTP/2扩展)Pulsar协议(支持HTTP/2、MQTT)JMS、AMQP、MQTT、OpenWire
吞吐量中低(万级TPS)极高(百万级TPS,依赖分区数)高(十万级TPS,顺序写入优化)高(分层存储架构,支持多租户隔离)低(单节点瓶颈,适合小规模)
延迟低(毫秒级,适合实时场景)低(毫秒级,批量处理时稍高)低(毫秒级,优化网络和存储)低(基于BookKeeper的高速存储)中低(单节点下延迟可控)
持久化磁盘持久化(支持内存队列)磁盘顺序写入(日志分段存储,支持长期保留)磁盘顺序写入(CommitLog机制)分层存储(内存+BookKeeper持久化)磁盘/内存持久化(JMS标准实现)
集群能力分布式集群(Erlang节点,支持镜像队列)分布式分区集群(ZooKeeper/Kafka Raft)分布式集群(主从/DLedger Raft)分布式集群(分层架构,无中心节点)简单集群(主从/静态集群,扩展性有限)
生态系统丰富(插件生态,支持多语言客户端)成熟(Kafka Connect、Streams生态)完善(阿里生态,支持Spring Cloud)新兴(与Kafka生态兼容,Function支持)传统(JMS生态,兼容性强但更新慢)
典型场景企业级解耦、微服务通信、实时通知日志收集、实时流处理、大数据管道电商订单处理、分布式事务、顺序消息多租户云原生场景、边缘计算、流处理遗留系统集成、小规模企业应用
优势轻量级、协议支持全、社区活跃高吞吐量、可扩展性、消息回溯事务消息、顺序消息、高可用性云原生架构、分层存储、跨地域复制兼容性强、易于部署(早期市场主流)
劣势高并发下内存开销大、集群管理较复杂消息顺序仅保证分区内、运维成本较高生态依赖阿里、客户端语言支持较少生态成熟度低于Kafka、学习曲线较陡性能瓶颈明显、社区活跃度下降

2.选型建议

  • 中小规模业务/低延迟场景:选RabbitMQ(协议灵活)或RocketMQ(轻量高效)。
  • 高吞吐量/流处理场景:选Kafka(大数据生态适配)或Pulsar(云原生架构)。
  • 复杂业务逻辑/事务需求:选RocketMQ(事务消息、顺序消息)。
  • 遗留系统集成/简单解耦:选ActiveMQ(兼容性强,但需注意性能瓶颈)。

根据实际需求(如吞吐量、延迟、可靠性、生态适配)选择合适的类型和实现,分布式消息队列已成为主流,尤其在微服务、实时数据处理和云原生架构中优势显著。

三、收发消息

1.交换机(Exchanges)

1.1Fanout交换机

①流程

Fanout,英文翻译是扇出,在MQ中叫广播更合适。
在广播模式下,消息发送流程是这样的:
在这里插入图片描述

②总结交换机的作用
  • 接收publisher发送的消息
  • 将消息按照规则路由到与之绑定的队列
  • 不能缓存消息,路由失败,消息丢失
  • FanoutExchange的会将消息路由到每个绑定的队列

1.2Direct交换机

①流程

在Direct模型下:

  • 队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key)
  • 消息的发送方在 向 Exchange发送消息时,也必须指定消息的 RoutingKey。
  • Exchange不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routingkey与消息的 Routing key完全一致,才会接收到消息

在这里插入图片描述

②总结(描述下Direct交换机与Fanout交换机的差异?)
  • Fanout交换机将消息路由给每一个与之绑定的队列
  • Direct交换机根据RoutingKey判断路由给哪个队列
  • 如果多个队列具有相同的RoutingKey,则与Fanout功能类似

1.3Topic交换机

①流程

Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。
只不过Topic类型Exchange可以让队列在绑定BindingKey 的时候使用通配符!

BindingKey 一般都是有一个或多个单词组成,多个单词之间以.分割,例如: item.insert

通配符规则:

  • #:匹配一个或多个词
  • *:匹配不多不少恰好1个词

举例:

  • item.#:能够匹配item.spu.insert 或者 item.spu
  • item.*:只能匹配item.spu
    在这里插入图片描述
②总结(描述下Direct交换机与Topic交换机的差异?)
  • Topic交换机接收的消息RoutingKey必须是多个单词,以 . 分割
  • Topic交换机与队列绑定时的bindingKey可以指定通配符
  • #:代表0个或多个词
  • *:代表1个词

四、SpringAMQP

1.功能

  • 自动声明队列、交换机及其绑定关系
  • 基于注解的监听器模式,异步接收消息
  • 封装了RabbitTemplate工具,用于发送消息

2.需要的依赖

<!--AMQP依赖,包含RabbitMQ-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

3.声明队列和交换机

3.1基于bean声明

direct模式由于要绑定多个KEY,会非常麻烦,每一个Key都要编写一个binding

package com.itheima.consumer.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DirectConfig {

    /**
     * 声明交换机
     * @return Direct类型交换机
     */
    @Bean
    public DirectExchange directExchange(){
        return ExchangeBuilder.directExchange("hmall.direct").build();
    }

    /**
     * 第1个队列
     */
    @Bean
    public Queue directQueue1(){
        return new Queue("direct.queue1");
    }

    /**
     * 绑定队列和交换机
     */
    @Bean
    public Binding bindingQueue1WithRed(Queue directQueue1, DirectExchange directExchange){
        return BindingBuilder.bind(directQueue1).to(directExchange).with("red");
    }
    /**
     * 绑定队列和交换机
     */
    @Bean
    public Binding bindingQueue1WithBlue(Queue directQueue1, DirectExchange directExchange){
        return BindingBuilder.bind(directQueue1).to(directExchange).with("blue");
    }

    /**
     * 第2个队列
     */
    @Bean
    public Queue directQueue2(){
        return new Queue("direct.queue2");
    }

    /**
     * 绑定队列和交换机
     */
    @Bean
    public Binding bindingQueue2WithRed(Queue directQueue2, DirectExchange directExchange){
        return BindingBuilder.bind(directQueue2).to(directExchange).with("red");
    }
    /**
     * 绑定队列和交换机
     */
    @Bean
    public Binding bindingQueue2WithYellow(Queue directQueue2, DirectExchange directExchange){
        return BindingBuilder.bind(directQueue2).to(directExchange).with("yellow");
    }
}

3.2基于注解声明

基于@Bean的方式声明队列和交换机比较麻烦,Spring还提供了基于注解方式来声明。

@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "direct.queue1"),
    exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),
    key = {"red", "blue"}
))
public void listenDirectQueue1(String msg){
    System.out.println("消费者1接收到direct.queue1的消息:【" + msg + "】");
}

@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "direct.queue2"),
    exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),
    key = {"red", "yellow"}
))
public void listenDirectQueue2(String msg){
    System.out.println("消费者2接收到direct.queue2的消息:【" + msg + "】");
}

4.消息转换器

4.1默认消息转换器

Spring的消息发送代码接收的消息体是一个Object:
在这里插入图片描述

而在数据传输时,它会把你发送的消息序列化为字节发送给MQ,接收消息的时候,还会把字节反序列化为Java对象。
只不过,默认情况下Spring采用的序列化方式是JDK序列化。众所周知,JDK序列化存在下列问题:

  • 数据体积过大
  • 有安全漏洞
  • 可读性差

4.2配置JSON转换器

JDK序列化方式并不合适。我们希望消息体的体积更小、可读性更高,因此可以使用JSON方式来做序列化和反序列化。
①引入依赖(注意,如果项目中引入了spring-boot-starter-web依赖,则无需再次引入Jackson依赖。)

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.9.10</version>
</dependency>

②在配置类中添加一个bean

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

五、WorkQueues模型

Work queues,任务模型。简单来说就是让多个消费者绑定到一个队列,共同消费队列中的消息
在这里插入图片描述

Work模型的使用:

  • 多个消费者绑定到一个队列,同一条消息只会被一个消费者处理
  • 通过设置prefetch来控制消费者预取的消息数量(默认是平均分配消息给每个队列)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

让我上个超影吧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值