Files
autumn-recruitment/04.MQ/rabbitmq/消息持久化与可靠性投递_test.md
T

8.6 KiB
Raw Blame History

tags, create time
tags create time
test/review
mq
rabbitmq
publisher-confirm
message-persistence
rabbitmq-transaction
return-callback
2026-08-09 12:00

消息持久化与可靠性投递_测试题

概述

本测试覆盖 RabbitMQ 消息从生产者到消费者的完整链路中保证可靠性的三大支柱:Exchange/Queue 持久化、消息 persistent 标记和 Publisher Confirm 机制。共 10 道题:6 道选择题、3 道填空题、1 道简答题。


一、选择题(6道,由浅入深)

难度阶梯: Q1-Q2 基础概念 → Q3-Q4 核心原理 → Q5-Q6 深入应用/边界场景

Q1(基础)— 考察定义层面

RabbitMQ 消息持久化的三个环节依次是:

A. 发送端加密 → 网络传输加密 → 存储端加密 B. Exchange durable 声明 → Queue durable 声明 → 消息 DeliveryMode=2 C. 消息签名 → Exchange 验证 → Queue 存储 D. 生产者确认 → Broker fsync → 消费者 ACK

Q2(基础)— 考察行为判断

仅设置 Queue durable=true 但消息的 DeliveryMode=1(transient),服务器重启后这些消息会怎样?

A. 消息会保留在磁盘中因为队列本身是持久的 B. 消息会被丢弃因为瞬态消息不会写入磁盘 C. 消息会被转移到另一个临时队列 D. 消息会以压缩格式保存在内存中

Q3(进阶)— 考察核心原理

Publisher Confirm 批量确认模式相比单条确认模式的主要优势是什么?

A. 能保证"恰好一次"语义而单条不能 B. 吞吐量接近未开启 Confirm 的水平,性能差距数倍甚至十倍以上 C. 不需要建立 Channel 连接即可工作 D. 支持事务回滚语义

Q4(进阶)— 考察对比辨析

关于 RabbitMQ 的 Confirm vs Transaction 两种可靠投递方式,以下哪项对比是错误的?

A. Confirm 采用异步批量确认,Transaction 采用同步提交 B. Transaction 的资源开销更高,需要维护完整的事务日志和回滚状态 C. Confirm 能保证恰好一次语义,Transaction 只能做到最多一次 D. 生产环境中几乎不推荐使用 Transaction 模式

Q5(深入)— 考察场景推理

一个订单支付推送系统使用 RabbitMQ 将支付结果通知给物流、库存等多个下游系统。在生产者配置中,如果 exchange 存在但没有绑定的队列能匹配该 routing key,且消息设置了 mandatory=false,会发生什么?

A. ReturnCallback 被触发,消息退回给生产者 B. 消息被 Broker 静默丢弃,没有任何通知 C. ConfirmCallback 收到 nack 通知 D. 消息自动路由到死信队列

Q6(深入)— 考察源码级别细节

在 Go 中使用 amqp.go 库实现 Confirm + Return 回调时,以下代码片段的作用是什么?

confirms := ch.NotifyPublish(nil)
for conf := range confirms {
    if conf.Ack {
        log.Printf("消息 delivery-tag=%d 已确认", conf.DeliveryTag)
    } else {
        log.Printf("消息 delivery-tag=%d 未被确认", conf.DeliveryTag)
    }
}

A. 注册 ReturnCallback 处理路由失败的消息 B. 注册 ConfirmCallback 通道,逐条接收 Broker 对每条消息的处理结果 C. 向所有生产者广播消息 D. 监控 Broker 的健康状态


二、填空题(3道)

F1 — 填空

RabbitMQ 消息的 DeliveryMode 为 ______ 时表示持久化消息,只有设置为这个值的消息在抵达 Queue 后才会刷盘到磁盘。

提示: 取值为 1 或 2。

F2 — 填空

只有同时开启 mandatory=true,ReturnCallback 才会在消息因无法路由而被退回时被触发。ConfirmCallback 告诉生产者消息是否被 Broker 安全接收(路由完成),而 ReturnCallback 处理强制性消息无法路由的情况——它区分了"Exchange 不存在"和"Exchange 存在但无绑定队列"这两种情况。

提示: 思考 mandatory 参数在这个回调中的作用。

F3 — 填空

如果需要"恰好一次"语义,正确做法是:______ 作为投递保障加上业务层幂等键(如 orderId 唯一索引)兜底。

提示: 不是 Transaction,而是另一种更轻量的机制。


三、简答题(1道)

S1

你正在为一个金融转账系统设计基于 RabbitMQ 的消息通知服务。转账成功后需要将交易记录通过 MQ 通知风控系统和审计系统。该系统有以下要求:

  • 绝对不能丢失任何一条交易通知
  • 下游系统具备幂等处理能力(可以安全重复消费)
  • 高吞吐需求(峰值 QPS 5000+)

请设计一个完整的可靠性投递方案,回答以下问题:

  1. Exchange、Queue 和消息的持久化如何配置?
  2. 选择 Confirm 还是 Transaction?为什么?
  3. Nack 的消息如何处理?
  4. 如何配合业务幂等性设计确保"恰好一次"的效果?

答题框架提示:

  1. 三阶段持久化的具体配置
  2. Confirm 模式的选择理由及批量策略
  3. nack 的重试和补偿机制
  4. 业务层幂等键的设计思路

参考答案与解析

选择题答案

题号 正确答案 解析
Q1 B 三个环节:Exchange 声明 durable=true、Queue 声明 durable=true、消息 DeliveryMode=2。三者缺一不可,任何一个环节未持久化都导致丢消息风险。A 讲的是加密而非持久化;C/D 涉及其他机制。
Q2 B 常见误解:仅设置 Queue durable 并不能保证消息不丢。如果消息 DeliveryMode=1(transient),即使队列本身是持久的,这些瞬态消息在服务器重启时也会被丢弃。持久化是队列元数据和消息内容两回事。
Q3 B 批量 Confirm 一次发送多条消息一次性收到确认回调,吞吐量接近未开启 Confirm 的水平。单条确认串行等待 ack/nack 吞吐量极低。实际性能差距可达数倍甚至十倍以上。
Q4 C 反了!无论是 Confirm 还是 Transaction 都不够保证恰好一次。Confirm 最多一次(需重试才能至少一次),Transaction 配合回滚可做到更接近恰好一次但仍需业务幂等兜底。这是面试高频考点。
Q5 B mandatory=false 时,如果 Exchange 存在但没有匹配的 Queue,消息被 Broker 静默丢弃,不会触发任何回调。只有 mandatory=true 时才会触发 ReturnCallback 退回消息。A 错误——mandatory=false 不会触发 Return。
Q6 B NotifyPublish 注册一个 Confirmation 通道,每个发出的消息对应一个 Confirmation 对象,其 Ack 字段为 true 表示 Broker 已成功处理(路由完成),false 则说明未被确认(如 Exchange 不存在)。这是 Confirm 的核心结构。

填空题答案

题号 答案 解析
F1 2 DeliveryMode=2 表示 persistent(持久化),DeliveryMode=1 表示 transient(瞬态)。持久化消息在抵达 Queue 后会刷盘而非仅仅留在内存 buffer 中。但这会带来明显的性能代价(大约 10 倍吞吐下降)。
F2 mandatory 只有同时开启 mandatory=true,ReturnCallback 才会在路由失败时被触发。mandatory 控制的是"消息是否允许被丢弃"——true 表示不允许丢弃,必须退回或报错;false 表示允许 Broker 静默丢弃无法路由的消息。
F3 Confirm 面试回答要点:如果需要"恰好一次"语义不要指望 RabbitMQ 本身保证——无论 Confirm 还是 Transaction 都不够。正确做法是 Confirm 作为投递保障 + 业务层幂等键(如 orderId 唯一索引)兜底。这才是工业级方案的思路。

简答题参考答案

S1:参考答案要点:

  1. Exchange 和 Queue 均声明 durable=true 防止服务重启丢数据;消息设置 DeliveryMode=2(persistent)确保磁盘持久化。
  2. 选择 Publisher Confirm 而非 Transaction。原因:Confirm 异步批量确认吞吐量大(峰值 QPS 5000+ 完全够用),资源占用低,主流客户端支持成熟。Transaction 同步阻塞吞吐不够且资源开销大。
  3. Nack 的消息放入本地重试表(数据库),定时任务扫描并重试。超过最大重试次数后进入死信队列人工介入。
  4. 业务幂等设计:每条交易通知携带唯一的 orderId + 目标系统标识作为幂等键。下游系统在数据库中建立联合唯一索引(order_id, target_system)。重复收到的消息因违反唯一约束而被拒绝,不会产生副作用。

评分标准:答出任意 2 个要点即可得满分;完全正确需覆盖三阶段持久化、Confirm 选择理由、nack 处理策略和业务幂等设计四个维度。

关联笔记