RabbitMQ

一、基础概念

1、什么是RabbitMQ ?

RabbitMQ 是一款开源、轻量级、可靠的消息中间件(Message Queue) ,采用 Erlang 语言开发,基于 AMQP 0-9-1 高级消息队列协议,跨平台、多语言客户端支持(Java/Python/Go/PHP 等)。

核心作用:解耦、削峰、异步、最终一致性,解决分布式系统通信问题。

2、核心术语(AMQP 模型)

  • 生产者 Producer 发送消息的应用程序,不直接发给队列,先发给交换机。
  • 消费者 Consumer 监听队列、接收并处理消息的应用。
  • 消息 Message 传输数据,包含两部分:
    • Header:属性(路由 key、持久化、优先级、过期时间等)
    • Body:业务数据(JSON / 字符串 / 二进制)
  • 虚拟主机 Virtual Host(vhost) Rabbit 的隔离命名空间,相当于小型独立 Rabbit 服务。 不同 vhost 交换机、队列互不干扰,用于多环境、多项目隔离,默认 /
  • 交换机 Exchange 接收生产者消息,根据规则路由到队列,队列不直接绑定生产者
  • 绑定 Binding 交换机 ↔ 队列之间的关联关系,绑定需要 RoutingKey
  • 队列 Queue 存储消息的容器,先进先出 FIFO;消息最终存在队列等待消费者消费。
  • Broker RabbitMQ 服务实例整体统称,包含交换机、队列、vhost 全部组件。

二、交换机 Exchange 四大类型(核心重点)

交换机决定消息分发策略,四种内置类型:

1. Direct 直连交换机(精准匹配)

  • 规则:消息 routingKey = 绑定 bindingKey,精准匹配才投递队列
  • 使用场景:点对点、单任务分发、精准定向推送
  • 示例:订单支付成功只通知订单服务,路由 key order.pay

2. Fanout 扇形交换机(广播)

  • 规则:忽略 routingKey,所有绑定该交换机的队列全部收到同一条消息
  • 使用场景:广播通知、日志同步、多服务同时更新缓存
  • 示例:商品上新,推送给搜索服务、推荐服务、库存服务

3. Topic 主题交换机(模糊匹配,最常用)

  • 规则:支持通配符模糊匹配 routingKey
    • *:匹配一个单词
    • #:匹配零个或多个单词 单词用 . 分隔,例:user.createorder.pay.success
  • 使用场景:日志分级、多维度业务消息、多订阅规则
  • 示例:
    • log.* 接收所有一级日志(log.info、log.error)
    • log.# 接收所有日志

4. Headers 头交换机(极少用)

不依赖 routingKey,通过消息 header 键值对匹配,性能差,业务几乎不用。

补充:默认交换机

Rabbit 自带匿名直连交换机,名称为空字符串。 特点:所有队列自动与它绑定,bindingKey = 队列名。 生产者直接发 routingKey=队列名,即可直达队列,适合简单场景。

三、消息可靠机制(生产 + 存储 + 消费三层保障)

1. 生产者可靠性:确保消息不丢失

(1)事务机制(不推荐,性能差)

channel.txSelect() 开启事务,发送后 txCommit;失败 txRollback。 缺点:同步阻塞,吞吐量下降几十倍,生产环境弃用。

(2)Publisher Confirms 发布确认(主流方案)

异步确认模式:

  1. 通道开启 confirmSelect()
  2. 生产者发送消息,Rabbit 处理完成后返回 ack/nack
    • ack:消息已正常存入交换机 / 队列
    • nack:消息丢失,生产者重发 支持批量确认、异步回调,性能远高于事务。

(3)Return 退回消息

消息无法路由到任何队列时触发回调(无匹配队列),生产者可捕获重发。

2. 服务端可靠性:消息持久化

两个持久化配置必须同时开启才不会丢消息:

  1. 队列持久化 :创建队列参数 durable=true
  2. 消息持久化 :发送消息时 deliveryMode=2(持久化) 重启 Rabbit 后,持久化消息不会丢失;非持久化内存消息重启清空。

注意:仅持久化会丢数据场景:磁盘满、机器宕机未刷盘,需配合镜像队列。

3. 消费者可靠性:手动 ACK 防止消息丢失

两种确认模式:

  1. 自动 ACK(autoAck=true) Rabbit 消息推送给消费者立刻标记删除;若消费者中途崩溃,消息直接丢失,业务禁止使用
  2. 手动 ACK(autoAck=false,推荐) 消费者业务处理完成后手动调用 basicAck
    • 正常消费:basicAck(deliveryTag, multiple=false) 确认删除
    • 处理失败:basicNack(deliveryTag, multiple=false, requeue=true) 重新放回队列 requeue=false:丢弃消息 / 转发死信队列

四、死信队列 DLX(Dead Letter Exchange)

1. 消息成为死信的 4 种情况

  1. 消费者 nack 且 requeue=false(拒绝不重入)
  2. 消息过期(TTL 超时未消费)
  3. 队列达到最大长度,溢出消息
  4. 消息被 basic.reject 拒绝

2. 使用流程

  1. 创建普通业务队列,绑定 DLX 死信交换机 + 死信路由 key
  2. 创建死信队列,绑定死信交换机
  3. 死信自动转发到死信队列,单独监听处理异常消息(重试、告警、记录)

3. 消息 TTL 过期

两种设置方式:

  1. 队列级别:队列所有消息统一过期时间
  2. 消息级别:单条消息单独过期时间(优先级更高) 结合死信队列可实现延迟队列(简易延迟方案)。

五、高级特性

1. 延迟消息(两种方案)

  1. TTL+DLX 死信延迟(低成本,精度差) 队列设置过期时间,到期转发死信,适合分钟级延迟,毫秒误差大。
  2. rabbitmq-delayed-message-exchange 插件(推荐) 官方延时插件,新增 x-delayed-message 交换机类型,发送时指定延迟毫秒,精准可控,生产常用。

2. 消息限流 Qos(消费者预取)

channel.basicQos(prefetchCount) 控制消费者未确认消息最大数量,避免一次性推送几万条压垮消费者。 例:Qos=10,消费者最多持有 10 条未 ack 消息,处理完一条才会推送下一条。

3. 队列模式:普通队列 / 镜像队列 / 集群队列

  1. 普通队列:仅存在当前节点,节点宕机队列消息全部丢失
  2. 镜像队列(高可用) 集群环境,队列同步复制到多个节点,主节点故障自动切换镜像节点,保证消息不丢失。
  3. 队列持久化 + 镜像队列 = 生产高可用标配

4. 消息优先级

创建队列时设置 x-max-priority=10(0~10 级),高优先级消息优先被消费,适合紧急订单、告警消息。

5. 独占队列、临时队列

临时队列:消费者断开自动删除,配合 Fanout 做临时订阅; 独占队列:仅当前消费者可监听,适用于独占任务。

6. 幂等性(必做!)

MQ 不保证消息只投递一次,存在重复消费,业务必须实现幂等: 方案:

  1. 每条消息携带唯一 msgId,消费前查数据库 / Redis 是否已处理
  2. 数据库唯一约束,重复插入直接报错跳过
  3. Redis 记录已消费消息 ID,设置过期时间

六、集群架构

1. 普通集群

多台 Rabbit 节点共享元数据(交换机、队列配置),消息只存在创建队列的节点,节点宕机消息丢失,仅做配置共享,无高可用。

2. 镜像集群(生产高可用)

队列数据同步到集群多个节点,主节点故障,镜像节点升级为主,消息不丢失。 配置策略指定哪些队列开启镜像。

3. 联邦集群 / 跨地域集群

多机房、异地 Rabbit 同步消息,解决跨区域消息互通,不依赖统一集群。

七、使用场景

  • 系统解耦 下单后不用同步调用库存、支付、短信;发消息到 MQ,各服务异步消费,互不阻塞。
  • 流量削峰填谷 秒杀大量请求打入队列,消费者匀速处理,避免数据库瞬间压垮。
  • 异步处理 短信、邮件、日志、文件导出、大数据统计,不阻塞主流程。
  • 最终一致性(分布式事务) 可靠消息事务:本地消息表 + Rabbit 可靠投递,实现跨服务数据一致。
  • 定时任务 / 延迟任务 订单 30 分钟未支付自动取消、超时退款。
  • 广播通知 配置更新、缓存刷新、多服务同步数据。

八、优缺点

优点

  1. 可靠性高:持久化、确认机制、镜像集群,消息不易丢失
  2. 灵活路由:四种交换机适配各类分发场景
  3. 轻量稳定:Erlang 高并发、低内存占用,百万级消息无压力
  4. 多语言、成熟生态,监控完善(Management 管理面板)
  5. 功能丰富:死信、延迟、限流、优先级、vhost 隔离

缺点

  1. 不适合海量超大数据流(Kafka 吞吐量更高)
  2. 分布式事务实现复杂,无原生事务
  3. 延迟插件精度有限,超大规模延迟任务成本高
  4. 集群运维有一定学习成本

九、与 Kafka 核心区别(面试高频)

特性 RabbitMQ Kafka
定位 可靠业务消息,复杂路由 高吞吐日志、数据流
吞吐量 万级 十万 / 百万级
消息模型 消费后删除 日志持久化,可重复消费
路由能力 交换机灵活路由 仅分区 + topic,路由简单
可靠性 强可靠,适合金融订单 高吞吐优先,丢失容忍度更高
使用场景 订单、支付、短信、延迟任务 日志收集、大数据流、实时计算

十、常见问题与踩坑

  1. 消息丢失三大场景
    • 生产者未开启 confirm,网络断连消息丢失
    • 队列 / 消息未持久化,服务重启清空
    • 自动 ack,消费者崩溃消息未处理完直接删除
  2. 消息堆积 消费速度 < 生产速度,解决方案:提高消费者数量、批量消费、限流生产、拆分队列
  3. 死信队列堆积 异常消息持续产生,需定时清理死信、告警通知人工处理
  4. 重复消费 网络超时导致生产者重发,必须业务幂等
  5. 脑裂问题 集群网络分区,镜像队列出现双主,配置磁盘节点、监控告警规避

十一、简单工作流程总结

  1. 生产者连接 Broker,创建交换机,发送消息携带 routingKey
  2. 交换机根据类型 + routingKey 匹配绑定关系,投递消息到对应队列
  3. 消息存入队列,持久化落地磁盘
  4. 消费者监听队列,手动 ACK 处理业务
  5. 处理失败消息转入死信队列,异常单独处理
  6. 集群镜像保证节点宕机消息不丢失

十二、Mac m1 PRO 安装 RabbitMQ 的完整步骤

1. 确认安装 Homebrew

M1 芯片 brew 安装路径为 /opt/homebrew,没有先执行安装脚本:

bash 复制代码
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

安装结束后终端会输出两行环境变量命令,复制执行,配置 zsh。

验证 brew:

bash 复制代码
brew -v

2. 一键安装 RabbitMQ(自动装 Erlang)

bash 复制代码
brew install rabbitmq

3. 配置环境变量(M1 必配,否则命令找不到)

M1 默认 shell 是 zsh,编辑配置文件:

bash 复制代码
nano ~/.zshrc

文件末尾粘贴:

bash 复制代码
# RabbitMQ M1 Pro
export PATH=$PATH:/opt/homebrew/opt/rabbitmq/sbin

保存退出:control+O 回车,control+X

刷新配置生效:

bash 复制代码
source ~/.zshrc

验证命令是否可用:

bash 复制代码
rabbitmq-server --version

4. 启动 / 停止服务

方案 A:开机自启(推荐开发用)

bash 复制代码
# 启动后台服务
brew services start rabbitmq

# 停止
brew services stop rabbitmq

# 重启
brew services restart rabbitmq

# 查看运行状态
brew services list

方案 B:临时前台运行(关闭终端即停止)

bash 复制代码
rabbitmq-server

5. 开启 Web 管理面板

bash 复制代码
rabbitmq-plugins enable rabbitmq_management

访问地址:http://localhost:15672

  • AMQP 连接端口:5672
  • 管理后台端口:15672

默认账号(仅本地localhost可用)

  • 用户名:guest
  • 密码:guest

6、创建管理员账号(禁止使用默认 guest)

guest 仅允许本地访问,外网 / 项目连接会报错,新建管理员:

bash 复制代码
# 创建用户 admin 密码 12345678
rabbitmqctl add_user admin 12345678
# 设置超级管理员权限
rabbitmqctl set_user_tags admin administrator
# 赋予全部虚拟主机权限
rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"


# 可选:删除默认guest用户
rabbitmqctl delete_user guest

网页登录账号:admin / 12345678

7. 高频常用命令

bash 复制代码
# 查看服务状态
rabbitmqctl status

# 查看所有用户
rabbitmqctl list_users

# 查看队列消息数量
rabbitmqctl list_queues name messages

# 查看交换机
rabbitmqctl list_exchanges

十三、Java SpringBoot 整合 RabbitMQ 的完整可运行代码

环境说明

  • SpringBoot 2.7.x/ 3.2.x 通用(区分简单注解)
  • RabbitMQ 本地安装 / Docker 启动均可
  • 实现:简单队列、工作队列、发布订阅、路由、主题 5 种模式完整代码

一、创建项目(两种方式)

方式 1:IDEA 新建 SpringBoot 项目

  1. File -> New -> Project -> Spring Initializr
  2. 填写坐标:
    • Group:com.mq
    • Artifact:rabbit-demo
    • Java 版本 8/17
  3. 勾选依赖:
    • Spring for RabbitMQ(spring-boot-starter-amqp)
    • Spring Web(可选,方便接口测试)

方式 2:Maven 手动引入依赖 pom.xml

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>4.1.0</version>
        <relativePath/>
    </parent>
    <groupId>com.zhbe</groupId>
    <artifactId>RabbitMQDemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>RabbitMQDemo</name>
    <description>RabbitMQDemo</description>

    <properties>
        <java.version>17</java.version>
    </properties>

    <dependencies>
        <!-- RabbitMQ核心 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <!-- 标准web,内置Tomcat + Jackson(解决JSON转换器爆红) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- lombok简化实体 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 统一测试依赖,包含web、amqp测试能力 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

二、application.yml 配置文件

删除默认的 application.properties 文件,然后创建 application.yml 文件

bash 复制代码
spring:
  rabbitmq:
    # rabbitmq 服务地址
    host: 127.0.0.1
    port: 5672
    username: admin
    password: 12345678
    virtual-host: /
    # 消息手动确认(推荐生产使用)
    listener:
      simple:
        acknowledge-mode: manual # manual手动 / auto自动
        prefetch: 1 # 每次只分发1条消息,公平分发
    # 生产者确认
    publisher-confirm-type: correlated
    publisher-returns: true

三、完整项目目录结构

包名统一:com.zhbe.rabbitmqdemo ,分层清晰,企业标准规范,所有代码对应放置位置标注清楚

bash 复制代码
rabbit-demo
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── zhbe
        │           └── rabbitmqdemo                 # 根启动包
        │               ├── RabbitDemoApplication.java  # 启动类
        │               ├── config                  # 配置层:交换机、队列、RabbitTemplate配置
        │               │   └── RabbitConfig.java
        │               ├── controller              # 测试接口控制器
        │               │   └── MqTestController.java
        │               ├── consumer                # 消费者监听类
        │               │   └── RabbitConsumer.java
        │               ├── producer                # 生产者发送工具类
        │               │   └── RabbitProducer.java
        │               └── entity                  # 消息实体对象
        │                   └── Message.java
        └── resources
            └── application.yml                     # RabbitMQ配置文件

四、通用消息实体 Message.java

java 复制代码
package com.zhbe.rabbitmqdemo.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @program: RabbitMQDemo
 * @author: 郭宝
 * @create: 2026-06-30 14:24
 * @description:
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Message {

    private Long id;
    private String content;
    private Long time;
}

四、RabbitMQ 配置类 RabbitConfig.java(交换机、队列、绑定声明)