rabbitmq
RabbitMQ 是什么?它的核心组件有哪些?**
RabbitMQ 是一个基于 AMQP(Advanced Message Queuing Protocol) 协议的消息队列中间件,具有高可靠性、持久化存储和灵活的路由机制。
RabbitMQ 的核心组件:
- Producer(生产者): 负责发送消息到 RabbitMQ。
- Exchange(交换机): 接收生产者的消息,并根据路由规则分发到队列。
- Queue(队列): 存储消息,等待消费者消费。
- Consumer(消费者): 从队列中取出消息并处理。
- Binding(绑定): 连接队列和交换机,定义路由规则。
- Routing Key(路由键): 生产者发送消息时附带的关键字,影响消息的投递方式。
- Virtual Host(虚拟主机): 类似于命名空间,用于隔离不同的应用或租户。
使用过程:
(1)客户端连接到消息队列服务器,打开一个channel。
(2)客户端声明一个exchange,并设置相关属性(点对点使用默认exchange)。
(3)客户端声明一个queue,并设置相关属性。
(4)客户端使用routing key,在exchange和queue之间建立好绑定关系。
(5)客户端投递消息到exchange。
exchange接收到消息后,就根据消息的key和已经设置的binding,进行消息路由,将消息投递到一个或多个队列里。
RabbitMQ 与 Kafka 的区别是什么?
| 对比项 | RabbitMQ | Kafka | |————-|————-|———-| | 消息协议 | AMQP | 自定义协议 | | 数据存储 | 内存+磁盘存储 | 仅磁盘存储 | | 消息模式 | Push | Pull | | 吞吐量 | 低(万级) | 高(百万级) | | 消息顺序 | 队列级别保证顺序 | 分区级别保证顺序 | | 事务支持 | 支持事务 | 不支持事务 | | 典型应用 | 订单、任务调度 | 日志采集、大数据处理 |
RabbitMQ 如何保证消息不丢失?
- 生产者端
- 开启 消息持久化(
delivery_mode=2
)。 - 使用 Publisher Confirms 机制,确保消息成功投递到交换机。
- 开启 消息持久化(
- RabbitMQ 服务器
- 队列持久化(
durable=true
),避免 RabbitMQ 宕机导致数据丢失。 - 开启 高可用模式(镜像队列)。
- 开启 磁盘持久化,确保消息写入磁盘。
- 队列持久化(
- 消费者端
- ACK 确认机制(
manual_ack=true
),确保消息被成功处理后才从队列删除。 - 处理失败时,拒绝并重新入队(
basic.reject
或basic.nack
)。
- ACK 确认机制(
RabbitMQ 如何保证消息顺序?
- 单一队列消费:单一消费者顺序消费,确保 FIFO(适用于低并发)。
- 严格保证多消费者顺序
- 将消息 按 key 进行分片,使用多个队列,每个队列一个消费者。
- 在业务层 排序合并 处理结果。
RabbitMQ 的镜像队列(HA 队列)是什么?
- RabbitMQ 镜像队列:在多个节点上复制队列,保证高可用。
- 如何启用?
- 配置 policy:
rabbitmqctl set_policy ha-all "^queue_name" '{"ha-mode":"all"}'
- 配置 policy:
- 优缺点
- 优点:避免单点故障,RabbitMQ 宕机不会丢失数据。
- 缺点:同步数据增加网络和存储开销。
如何优化 RabbitMQ 的性能?
- 生产者优化
- 批量发布(
batch.publish
),减少网络 I/O 开销。 - 消息压缩(gzip/snappy),减少数据传输量。
- 批量发布(
- 队列优化
- 多个队列并行,避免单个队列成为性能瓶颈。
- 合理使用 TTL(消息过期时间),防止积压。
- 消费者优化
- 并发消费,使用多个 Channel 处理消息。
- 预取消息(Prefetch Count),减少消费者等待时间:
channel.basic_qos(prefetch_count=10)
RabbitMQ 如何处理消息堆积?
- 短期优化
- 增加消费者数量,提高消费速度。
- 降低生产速率,避免消息继续堆积。
- 长期优化
- 拆分队列,使用多个队列并行处理不同的消息类型。
- 限流,RabbitMQ 提供 prefetch 机制,防止消费者超载:
channel.basic_qos(prefetch_count=100)
- 增加 RabbitMQ 节点,进行集群扩展。
死信队列(Dead Letter Queue,DLQ)
死信队列(DLQ)是一个特殊的队列,用于存储无法正常消费的消息。消息进入死信队列通常由以下原因导致:
- 消息过期:消息在队列中存活时间超过 TTL(Time-To-Live)后自动进入死信队列。
- 队列满:消息无法被消费且队列已满,无法再接收新消息。
- 消费者拒绝消息:消费者处理消息失败,且未进行
ack
确认。 - 队列未绑定:消息发送到的队列无消费者。
死信队列用于后续的故障排查、重试处理或人工干预,防止消息丢失。
RabbitMQ 的消息投递模式有哪些?
RabbitMQ 提供了 4 种常见的消息投递模式:
- Direct(直连交换机)
- 只有 Routing Key 完全匹配的队列才能收到消息。
- Fanout(广播模式)
- 消息发送到交换机后,所有绑定的队列都能收到消息(不需要 Routing Key)。
- Topic(主题模式)
- Routing Key 支持通配符(
*
表示一个单词,#
表示多个单词)。
- Routing Key 支持通配符(
- Headers(头部交换机)
- 根据消息头部属性(Headers)匹配队列,而不是 Routing Key。
模式
- 点对点模式
- 直接点对点
- task—work
- 发布订阅模式
- direct
- fanout
- topic
扩容
- 默认不支持自动扩容,手动加节点扩容。
- 可使用Kubernetes,底层通过负载均衡和节点池管理实现扩容。
- 采用 多个队列,不同队列存放不同的消息类型。