[TOC] #### 1. 回顾一下 --- 上一讲我们用 PHP 连接 RabbitMQ,发了一条消息,也消费了一条消息 整个过程中,消息存在哪里 ?答:Queue(队列),Queue 是 RabbitMQ 中负责存放消息的核心组件 消息从生产者发出来,经过 Exchange 路由,最终落到 Queue 里,等着消费者来取 今天我们就来深入了解一下 Queue #### 2. 队列是什么 --- 队列这个概念,你应该不陌生,去银行办业务要取号排队,先来的人先办,后来的人后办。 这就是队列:先进先出(FIFO),RabbitMQ 的 Queue 也是一样: + 消息从队尾进去 + 消息从队头出来 + 先发的消息先被消费 默认情况下,RabbitMQ 的队列遵循先进先出(FIFO),先进入队列的消息,通常会先被消费 #### 3. 声明队列 --- 上一讲我们用 `queue_declare` 声明了一个队列: ```php $channel->queue_declare('hello_queue', false, false, false, false); ``` 这行代码做了什么? + 如果 `hello_queue` 不存在,就创建它 + 如果已经存在,检查参数是否一致,一致就没事,不一致会报错 + 特别注意:生产者和消费者声明队列时的参数必须一致,否则会报错 声明队列是幂等的:你声明多少次都没关系,只要参数一致,RabbitMQ 都只会创建一次,且不会产生任何副作用 这个设计很实用,因为生产者和消费者可能在不同的进程里,你不知道谁先启动,两边都声明一遍,就不会出问题 为什么 RabbitMQ 要设计成幂等 ? 在实际的微服务或分布式架构中,这个特性非常关键: + 支持并发启动:多个消费者实例同时启动时,幂等性保证了它们可以安全地并发执行,而不会引发冲突 + 解耦服务依赖:生产者服务和消费者服务无论谁先启动,都不用担心因为队列不存在而导致报错或消息丢失 #### 4. 队列的几个重要参数 --- 接下来我们来聊聊队列的几个重要参数,声明队列的时候,有好几个参数可以配置 durable(持久化) ```php // 第二个参数是 passive // 第三个参数是 durable,durable = true 表示队列是持久化的 $channel->queue_declare('order_queue', false, true, false, false); ``` 这里的队列持久化什么意思 ? RabbitMQ 重启之后,持久化的队列还在,非持久化的队列就没了 ```php # 没有配置持久化的队列(重启服务后 hello_queue2 队列就没了) $channel->queue_declare('hello_queue2', false, false, false, false); # 持久化队列(重启服务后 hello_queue3 队列依然存在) $channel->queue_declare('hello_queue3', false, true, false, false); ``` ```bash # 使用 docker 安装的 rabbitmq 可以运行以下命令重启服务测试 docker restart rabbitmq ``` 但注意:队列持久化 ≠ 消息持久化 队列持久化只是保证队列这个「壳子」在重启后还在,消息要持久化,需要在发消息的时候单独设置,后面会讲 exclusive(排他队列) ```php // 第四个参数是 exclusive // exclusive = true 表示这个队列是排他的,只有当前连接能用。作用:当前连接断开,队列自动删除 $channel->queue_declare('temp_queue', false, false, true, false); ``` 什么时候用 ? 临时队列,比如用于 RPC 调用的响应队列,用完就删,不需要保留,一般业务场景用不到 auto_delete(自动删除) ```php // 第五个参数是 auto_delete // auto_delete = true 表示当最后一个消费者断开连接后,队列自动删除 $channel->queue_declare('worker_queue', false, false, false, true); ``` 特别注意:是最后一个消费者断开队列自动删除,不是生产者断开。如果从来没有消费者连过这个队列,它不会自动删除。 实际开发中,最常用的配置是: ```php // 持久化队列、不排他、不自动删除 $channel->queue_declare('order_queue', false, true, false, false); ``` 这是最稳的配置:队列重启后还在,谁都能用,不会被意外删除 + `passive = false`:正常声明 + `durable = true`:持久化 + `exclusive = false`:不排他 + `auto_delete = false`:不自动删除 #### 5. 一个生产者,多个消费者 --- 一个 Queue 可以被多个消费者同时消费,RabbitMQ 会把消息分发给不同的消费者处理,这样可以提高整体处理能力 假设队列里有 6 条消息: ```plaintext 消息1 → 消费者1 消息2 → 消费者2 消息3 → 消费者1 消息4 → 消费者2 消息5 → 消费者1 消息6 → 消费者2 ``` 这种方式可以让多个消费者同时处理同一个队列里的消息,如果消息很多,可以增加消费者数量来提高处理能力 #### 5. 队列还有很多高级能力 --- Queue 不只是简单地存放消息,它还支持消息过期、优先级控制、死信处理等高级能力 这些内容后面都会单独展开讲解,现在先把 Queue 理解成「存放消息的地方」就够了 #### 6. 本文小结 --- Queue 是 RabbitMQ 存放消息的地方,核心特性: + 默认按照先进先出顺序消费消息 + 支持持久化配置 + 可以同时被多个消费者消费 + 提供丰富的高级能力扩展 记住一句话:消息最终都存在 Queue 里,消费者从 Queue 里取。下一讲,我们来聊聊 Producer 生产者。