RabbitMQ基础
一、RabbitMQ 基础认知
1、RabbitMQ 是什么?
RabbitMQ 是一款基于 Erlang 语言开发、开源、轻量级、高可靠的业务型消息中间件。主打消息可靠性高、延迟极低、支持事务、支持死信、可视化管理、集群高可用。
2、使用场景 🔴
-
服务解耦:微服务之间异步通信,减少接口强依赖。
-
流量削峰:瞬时高并发流量存入队列,消费者匀速消费。
-
异步处理:非核心业务异步化,提高接口响应速度。
-
延时任务:订单超时、自动取消、超时提醒。
-
事件分发:广播消息、多服务同步数据。
3、核心五大基础组件
-
生产者 Producer:发送消息的应用程序,负责生成消息、推送至交换机。
-
交换机 Exchange:路由组件,不存储消息、只做转发。
-
绑定 Binding:交换机与队列之间的关联关系,绑定路由规则。
-
队列 Queue:唯一持久化存储消息的容器,等待消费者消费。
-
消费者 Consumer:监听队列,获取并执行业务逻辑。
4、消息完整流转流程 🔴
-
生产者与MQ建立TCP连接,创建信道Channel;
-
生产者携带 routingKey 发送消息到指定交换机;
-
交换机根据自身类型 + routingKey 匹配绑定关系;
-
消息路由分发至对应队列;
-
消息持久化落盘,等待消费者拉取;
-
消费者监听队列,获取消息执行业务;
-
消费成功手动ACK,MQ删除消息。
二、交换机详解 🟠
1、四大交换机类型
(1)Direct 直连交换机(精准匹配)
-
规则:routingKey 与 bindingKey 完全一致才转发。
-
特点:一对一、单播、精准投递。
-
场景:单服务点对点通知、订单状态通知。
(2)Topic 主题交换机(模糊匹配)
-
规则:支持通配符模糊匹配。
-
*****:匹配单个单词。
-
#:匹配零个或多个单词。
-
场景:多服务订阅、日志分类、业务事件分发。
(3)Fanout 广播交换机(无视key)
-
规则:忽略 routingKey,全部绑定队列全部接收。
-
特点:发布订阅、广播群发。
-
场景:系统公告、缓存刷新、多服务同步。
(4)Headers 请求头交换机(极少用)
-
根据消息header属性匹配。
-
性能差、配置繁琐,生产几乎不用。
2、特殊交换机 🟠
(1)死信交换机 DLX
专门接收过期、拒绝、溢出消息的交换机,搭配死信队列使用。
(2)延迟交换机(插件安装)
原生RabbitMQ不支持精准延时,需安装 delay-exchange 插件,基于时间戳精准延时投递。
三、RabbitMQ 可靠机制 🔴
1、消息丢失三大阶段
-
生产者发送阶段:网络抖动、MQ未接收成功。
-
交换机路由阶段:没有匹配队列,消息丢弃。
-
消费者消费阶段:业务异常,消息被误删。
2、生产端可靠性(防止发送丢失)
2.1 Confirm 发送确认模式(主流)
-
原理:生产者发送消息后,MQ返回ACK确认;
-
ack=true:消息持久化成功;
-
ack=false:发送失败,本地重试补偿。
-
优点:异步确认、性能高、生产必开。
2.2 Return 退回机制(路由失败)
-
作用:消息无法匹配队列时,不丢弃、退回生产者。
-
场景:路由key错误、无绑定队列。
2.3 事务机制(不推荐)
-
txCommit、txRollback,同步阻塞。
-
吞吐量极低,互联网行业禁止使用。
3、服务端可靠性(防止宕机丢失)
3.1 队列持久化
durable=true:队列元数据持久化,重启队列不消失。
3.2 消息持久化
deliveryMode=2:消息写入磁盘,断电不丢失。
注意:只持久化消息、不持久化交换机。
4、消费端可靠性(防止消费丢失)
4.1 自动ACK(不推荐)
MQ推送消息成功直接删除,业务报错也丢失消息。
4.2 手动ACK(生产强制)
-
basicAck:消费成功,MQ删除消息。
-
basicNack:消费失败,重回队列或丢弃。
-
basicReject:拒绝单条消息,不可批量。
四、死信队列 DLX 🟠
1、消息进入死信三种条件
-
消息过期:设置TTL,超时未消费。
-
消费拒绝:nack并且requeue=false。
-
队列溢出:队列达到最大长度,尾部消息丢弃进入死信。
2、死信架构搭建流程
-
创建普通业务队列,绑定死信交换机;
-
普通队列设置TTL、最大长度;
-
异常消息自动转入死信交换机;
-
死信交换机路由至死信队列;
-
消费者监听死信队列,人工补偿排查。
3、延时队列实现方案 🟠
方案一:死信实现延时(简单、低精度)
-
缺点:队列头部消息未过期,后面消息阻塞,时间不准。
-
适用:低精度、短延时任务。
方案二:Delay插件延时(生产推荐)
-
基于时间戳排序,精准延时。
-
不会阻塞、精度高。
-
适用:订单超时、精准定时任务。
五、重复消费 & 幂等性 🔴
1、为什么会重复消费?
-
消费者业务执行成功,ACK网络超时未送达MQ;
-
服务宕机、重试机制触发;
-
集群切换、消息重分发。
2、四大幂等解决方案 🔴
(1)数据库唯一索引(最简单、最稳)
消息唯一ID作为唯一索引,重复插入直接报错,不会重复业务。
(2)Redis 判断幂等(高性能)
消费前判断key是否存在,存在则直接跳过;消费成功写入Redis。
(3)业务状态机判断
数据库增加状态字段,已处理状态直接跳过。
(4)全局唯一流水号
上游生成唯一编号,下游不可重复消费。
六、消息堆积问题 🔴
1、堆积产生原因
-
消费者消费速度慢,生产者发送过快;
-
消费者代码报错、无限重试卡死队列;
-
消费者服务宕机断开;
-
prefetch一次性拉取过多消息。
2、堆积解决方案(生产实操)
-
扩容消费者:增加消费者实例,水平扩容提高并发。
-
异常消息隔离:异常消息转入死信,防止卡死队列。
-
批量消费:单次消费多条,减少IO次数。
-
限流prefetch:限制单次拉取消息数量,防止OOM。
-
临时拆分队列:超大堆积临时拆分队列分流。
七、集群模式详解 🔴
1、普通集群(静态集群)
-
特点:队列只存在一台节点,其他节点仅同步元数据。
-
缺点:主节点宕机,队列不可访问,数据丢失。
-
适用:测试环境。
2、镜像集群(旧生产)
-
特点:队列数据同步复制到所有节点。
-
优点:任意节点宕机不丢失数据。
-
缺点:同步开销大、吞吐量低、性能差。
3、仲裁队列(新版生产推荐)
-
RabbitMQ3.8+全新模式。
-
原理:过半节点保存数据,类似zk选举机制。
-
优点:性能优于镜像、高可用、低开销。
-
生产强制推荐:3主架构仲裁队列。
八、进阶 🔴
1、Channel 为什么轻于 Connection?
-
Connection:TCP物理连接,开销极大、数量有限。
-
Channel:虚拟信道,共享一条TCP连接。
-
生产规范:一个服务少量Connection,大量Channel。
2、消息为什么不建议发大消息?
-
大消息占用网卡带宽,阻塞其他消息投递;
-
持久化慢、内存占用高;
-
序列化慢、消费卡顿。
3、如何避免无限重试死循环?
-
设置重试次数上限;
-
失败达到阈值转入死信;
-
异常捕获,不要抛出原生异常。
4、RabbitMQ 内存溢出怎么解决?
-
设置内存水位,超过水位禁止生产者写入;
-
磁盘水位告警,防止磁盘爆满;
-
限制prefetch数量,防止消费者堆积内存。
九、三大消息中间件硬核对比 🔴
| 中间件 | 开发语言 | 吞吐量 | 可靠性 | 时效性 | 适用场景 |
|---|---|---|---|---|---|
| RabbitMQ | Erlang | 中等 | 极高 | 毫秒级 | 订单、支付、金融、业务异步 |
| RocketMQ | Java | 较高 | 极高 | 毫秒级 | 电商、事务消息、阿里生态 |
| Kafka | Scala | 极高 | 高 | 微秒级 | 大数据、日志、流处理、高吞吐 |
十、生产强制规范 🔴
-
必须开启 Confirm + Return 保证发送可靠;
-
队列、消息全部开启持久化;
-
消费端必须手动ACK,禁止自动ACK;
-
异常消息禁止无限重试,兜底转入死信队列;
-
业务必须做幂等,防止重复消费造成数据错乱;
-
限制prefetch数量,避免一次性拉取过多消息;
-
禁止发送超大消息,复杂数据压缩后传输;
-
线上采用仲裁队列,保证高可用、低损耗。
十一、 总结 🔴
RabbitMQ是Erlang开发、高可靠业务型消息中间件,核心包含生产者、交换机、队列、消费者;
交换机分为直连、主题、广播三类常用类型;
为保证消息零丢失,生产端开启Confirm确认和Return退回机制,服务端队列与消息双重持久化,消费端采用手动ACK;
通过死信队列处理异常消息、实现延时任务;
为防止网络抖动造成重复消费,业务层实现幂等;
集群推荐仲裁队列保障高可用;
相比Kafka,吞吐量适中、可靠性更强,适合订单、支付等核心业务异步解耦,是中小型微服务项目首选MQ。