RabbitMQ 面试高频 20 问(PHP后端版)
1. 什么是 RabbitMQ?
RabbitMQ 是一个基于 AMQP 协议的开源消息中间件,用于系统之间的异步通信。
主要作用:
- 异步处理
- 应用解耦
- 流量削峰
例如电商下单后,将发短信、发邮件、同步 ERP 等操作通过 RabbitMQ 异步执行,提高系统响应速度。
2. 为什么使用 RabbitMQ?
主要有三个原因:
异步
用户下单后立即返回结果。
不需要等待:
- 发短信
- 发邮件
- 发积分
执行完成。
解耦
订单系统不需要关心:
- 短信系统
- 邮件系统
- ERP系统
是否存在。
削峰
高并发场景:
10000请求/秒
↓
RabbitMQ
↓
100请求/秒慢慢消费
防止数据库被压垮。
3. RabbitMQ 核心组件有哪些?
核心组件:
| 组件 | 作用 |
|---|---|
| Producer | 生产者 |
| Consumer | 消费者 |
| Exchange | 交换机 |
| Queue | 队列 |
| Routing Key | 路由键 |
消息流转:
Producer
↓
Exchange
↓
Queue
↓
Consumer
4. Exchange 有哪些类型?
四种:
Direct
精准匹配
order.create
Topic
通配符匹配
order.*
order.#
Fanout
广播
发送给所有绑定队列。
Headers
根据 Header 路由。
实际项目很少使用。
5. Direct 和 Topic 的区别?
Direct:
order.create
必须完全匹配。
Topic:
支持模糊匹配:
order.*
order.#
例如:
order.create
order.pay
order.cancel
都可以匹配。
6. RabbitMQ 如何保证消息不丢失?
需要三层保证。
生产者确认
Publisher Confirm
Producer
↓
RabbitMQ
↓
ACK
队列持久化
durable = true
消息持久化
delivery_mode = 2
消费者ACK
basic_ack()
消息处理完成后确认。
7. 什么是 Publisher Confirm?
生产者发送消息后:
RabbitMQ返回ACK。
Producer
↓
MQ
↓
ACK
收到ACK:
表示RabbitMQ已接收。
未收到ACK:
重试发送。
用于保证生产者消息不丢失。
8. 什么是 Consumer ACK?
消费者处理成功后:
basic_ack()
通知RabbitMQ删除消息。
如果消费者异常退出:
ACK未发送
↓
消息重新投递
避免消息丢失。
9. 什么是消息持久化?
RabbitMQ重启后消息仍然存在。
需要:
队列持久化
durable=true
消息持久化
delivery_mode=2
两者缺一不可。
10. RabbitMQ 如何实现延迟队列?
常见方案:
TTL + Dead Letter Queue
流程:
订单创建
↓
延迟队列
(TTL=30分钟)
↓
死信队列
↓
取消订单
典型场景:
30分钟未支付自动取消订单。
11. 什么是死信队列?
无法正常消费的消息进入死信队列。
出现条件:
消息过期
TTL到期。
队列满
超过最大长度。
消费被拒绝
basic_nack()
12. 什么是 TTL?
Time To Live(消息存活时间)
例如:
x-message-ttl = 60000
表示:
60秒后过期
过期消息可转入死信队列。
13. RabbitMQ 如何实现订单超时取消?
标准流程:
创建订单
↓
发送延迟消息
(TTL=30分钟)
↓
进入死信队列
↓
检查订单状态
↓
未支付则取消
这是电商面试经典题。
14. RabbitMQ 会重复消费吗?
会。
例如:
消费成功
↓
ACK发送失败
↓
MQ认为失败
↓
重新投递
导致重复消费。
15. 如何解决重复消费?
保证幂等性。
常见方案:
Redis
SETNX(message_id)
唯一索引
UNIQUE(message_id)
业务状态判断
已处理
↓
直接返回
16. 什么是幂等性?
同一个请求执行多次。
结果保持一致。
例如:
支付成功
支付成功
支付成功
订单状态仍然:
已支付
不会重复扣款。
17. RabbitMQ 消息积压怎么办?
增加消费者
1个
↓
10个
提高prefetch
basic_qos()
优化消费逻辑
例如:
批量插入数据库
临时扩容
增加消费机器。
18. 什么是 Prefetch?
限制消费者一次拉取消息数量。
例如:
prefetch_count = 10
表示:
处理完10条
再拉下一批
防止单个消费者被压垮。
19. RabbitMQ 和 Redis 消息队列区别?
| 对比项 | RabbitMQ | Redis |
|---|---|---|
| 可靠性 | 高 | 一般 |
| ACK机制 | 支持 | 较弱 |
| 死信队列 | 支持 | 不支持 |
| 延迟队列 | 支持 | 需自己实现 |
| 吞吐量 | 较高 | 非常高 |
| 场景 | 业务消息 | 简单异步 |
面试结论:
业务场景优先RabbitMQ
极高性能场景可考虑Redis
20. RabbitMQ 在项目中的实际应用?
在电商项目中,我使用 RabbitMQ 实现订单异步处理。
用户下单后:
订单创建
↓
RabbitMQ
↓
短信通知
邮件通知
ERP同步
库存同步
积分发放
这样做有三个好处:
- 提高接口响应速度
- 降低系统耦合
- 应对高并发流量
同时为了保证消息可靠性,我使用:
- Publisher Confirm
- 消息持久化
- Consumer ACK
- Redis幂等控制
避免消息丢失和重复消费。