learning_notes

学习笔记

View project on GitHub

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 如何保证消息不丢失?

  1. 生产者端
    • 开启 消息持久化delivery_mode=2)。
    • 使用 Publisher Confirms 机制,确保消息成功投递到交换机。
  2. RabbitMQ 服务器
    • 队列持久化(durable=true),避免 RabbitMQ 宕机导致数据丢失。
    • 开启 高可用模式(镜像队列)。
    • 开启 磁盘持久化,确保消息写入磁盘。
  3. 消费者端
    • ACK 确认机制manual_ack=true),确保消息被成功处理后才从队列删除。
    • 处理失败时,拒绝并重新入队basic.rejectbasic.nack)。

RabbitMQ 如何保证消息顺序?

  • 单一队列消费:单一消费者顺序消费,确保 FIFO(适用于低并发)。
  • 严格保证多消费者顺序
    • 将消息 按 key 进行分片,使用多个队列,每个队列一个消费者。
    • 在业务层 排序合并 处理结果。

RabbitMQ 的镜像队列(HA 队列)是什么?

  • RabbitMQ 镜像队列:在多个节点上复制队列,保证高可用。
  • 如何启用?
    • 配置 policy
      rabbitmqctl set_policy ha-all "^queue_name" '{"ha-mode":"all"}'
      
  • 优缺点
    • 优点:避免单点故障,RabbitMQ 宕机不会丢失数据。
    • 缺点:同步数据增加网络和存储开销。

如何优化 RabbitMQ 的性能?

  1. 生产者优化
    • 批量发布batch.publish),减少网络 I/O 开销。
    • 消息压缩(gzip/snappy),减少数据传输量。
  2. 队列优化
    • 多个队列并行,避免单个队列成为性能瓶颈。
    • 合理使用 TTL(消息过期时间),防止积压。
  3. 消费者优化
    • 并发消费,使用多个 Channel 处理消息。
    • 预取消息(Prefetch Count),减少消费者等待时间:
      channel.basic_qos(prefetch_count=10)
      

RabbitMQ 如何处理消息堆积?

  1. 短期优化
    • 增加消费者数量,提高消费速度。
    • 降低生产速率,避免消息继续堆积。
  2. 长期优化
    • 拆分队列,使用多个队列并行处理不同的消息类型。
    • 限流,RabbitMQ 提供 prefetch 机制,防止消费者超载:
      channel.basic_qos(prefetch_count=100)
      
    • 增加 RabbitMQ 节点,进行集群扩展。

死信队列(Dead Letter Queue,DLQ)

死信队列(DLQ)是一个特殊的队列,用于存储无法正常消费的消息。消息进入死信队列通常由以下原因导致:

  1. 消息过期:消息在队列中存活时间超过 TTL(Time-To-Live)后自动进入死信队列。
  2. 队列满:消息无法被消费且队列已满,无法再接收新消息。
  3. 消费者拒绝消息:消费者处理消息失败,且未进行 ack 确认。
  4. 队列未绑定:消息发送到的队列无消费者。

死信队列用于后续的故障排查、重试处理或人工干预,防止消息丢失。

RabbitMQ 的消息投递模式有哪些?

RabbitMQ 提供了 4 种常见的消息投递模式:

  1. Direct(直连交换机)
    • 只有 Routing Key 完全匹配的队列才能收到消息。
  2. Fanout(广播模式)
    • 消息发送到交换机后,所有绑定的队列都能收到消息(不需要 Routing Key)。
  3. Topic(主题模式)
    • Routing Key 支持通配符(* 表示一个单词,# 表示多个单词)。
  4. Headers(头部交换机)
    • 根据消息头部属性(Headers)匹配队列,而不是 Routing Key。

模式

详细的图

  1. 点对点模式
    1. 直接点对点
    2. task—work
  2. 发布订阅模式
    1. direct
    2. fanout
    3. topic

扩容

  • 默认不支持自动扩容,手动加节点扩容。
  • 可使用Kubernetes,底层通过负载均衡和节点池管理实现扩容。
  • 采用 多个队列,不同队列存放不同的消息类型。