MQTT Quality of Service 描述一条消息在客户端与 Broker 之间如何投递。它不是整个系统的“质量评分”,数字更高也不代表一定更适合。
正确的选择始于业务问题:如果消息丢失、重复、延迟或被处理两次,会发生什么?
QoS 作用于每一跳
发布侧与订阅侧的 QoS 独立协商。
发布者可以用 QoS 1 发送,而订阅者只请求 QoS 0。Broker 会按该订阅可用的较低等级投递。同样,QoS 2 也无法让数据库事务或物理执行器天然只执行一次,它只约束当前 MQTT 网络链路。
应分别分析完整路径:
设备 → Broker → 消费者 → 数据库或执行器
每个箭头和每个处理步骤都有不同的失败方式。
QoS 0:至多一次
QoS 0 发送 PUBLISH 后不等待确认。消息可能到达一次,也可能丢失。
它适合:
- 高频数据;
- 可由下一条新值替代;
- 偶尔丢失成本很低;
- 更看重低延迟和低开销。
例如每秒一次的温度、实时光标位置或高频调试指标。
QoS 0 并不等于“完全不可靠”。健康的 TCP 连接在保持连接时本身有顺序和可靠性。QoS 0 只是不会在连接中断后由 MQTT 继续恢复未完成的投递。
QoS 1:至少一次
QoS 1 要求接收 PUBACK。发布者未收到确认时可能重新发送,因此消费者必须允许重复消息。
QoS 1 很适合作为以下场景的默认起点:
- 告警;
- 状态变化;
- 带幂等键的任务与指令;
- 不希望出现缺口的测量;
- 可以安全去重的事件。
载荷应支持幂等:
{
"eventId": "01JZ8M7V2BR5H0R9BC2T2N2K0A",
"deviceId": "pump-042",
"type": "pressure.threshold.exceeded",
"occurredAt": "2026-07-27T10:42:18Z",
"value": 9.8,
"unit": "bar"
}
消费者在执行副作用前记录 eventId。同一事件再次到达时,可以正常确认但不重复执行。
QoS 2:协议层恰好一次
QoS 2 使用四步交换:PUBLISH、PUBREC、PUBREL 和 PUBCOMP。握手结束前,两端都要保存状态。
只有在以下条件成立时才值得承担这项成本:
- 应用层很难安全处理重复;
- Broker 和相关客户端都正确支持 QoS 2;
- 已测量新增的延迟、带宽、内存和重连状态;
- 确实需要 MQTT 当前链路的“恰好一次”。
QoS 2 仍无法让非事务副作用天然只执行一次。如果消费者启动电机后、保存完成状态前崩溃,MQTT 握手无法判断物理动作是否发生。业务幂等仍不可缺少。
MQTT QoS 对比:0、1 与 2
MQTT QoS 0 与 1 的主要取舍是恢复能力和开销。QoS 0 发送后不等待 MQTT 确认;QoS 1 会持续重试直到收到确认,因此消费者必须允许重复。消息丢失的影响大于重复到达时,应选择 QoS 1。
MQTT QoS 1 与 2 并不是“可靠”和“更可靠”的简单区别。QoS 1 使用两步报文交换并依赖应用幂等;QoS 2 使用四步协议握手,避免当前 MQTT 链路上的重复投递。QoS 2 仍无法让下游副作用恰好执行一次,因此多数生产系统使用 QoS 1 加事件 ID 或操作 ID,反而更简单也更完整。
下面的表格只能作为起点,最终选择还需在真实网络、消息速率、客户端库和 Broker 配置下验证。
| 消息 | 建议起点 | 原因 |
|---|---|---|
| 每秒传感器采样 | QoS 0 | 下一条值可以替代丢失采样 |
| 设备在线状态 | QoS 1 + 保留消息 | 状态重要,重复无害 |
| 告警事件 | QoS 1 | 需要到达,可按事件 ID 去重 |
| 配置更新 | QoS 1 + 版本号 | 只应用更新的版本 |
| 远程指令 | QoS 1 + 操作 ID + 过期时间 | 避免过期与重复执行 |
| 财务或安全关键动作 | 不应仅按表决定 | 必须设计端到端事务与安全模型 |
QoS 与离线会话
根据 Broker 与会话设置,持久会话的订阅者离线时,QoS 1 或 2 消息可以排队。这很有用,但也可能在设备恢复后投递已经过时的工作。
指令消息应增加:
- 消息过期时间;
- 指令或操作 ID;
- 目标设备身份;
- 创建时间;
- Schema 版本;
- 确认主题或结果事件。
同时限制 Broker 队列。无限离线队列不是可靠性,而是没有边界的积压。
只应排队那些断线后仍有业务价值的消息。新的状态快照通常可以替代旧遥测,过期指令则应直接丢弃。需要同时测量单个客户端和整个设备群的重连积压,避免正常恢复过程压垮 Broker 或下游消费者。
测试失败,而不只是成功
有效的 QoS 测试应在关键时刻中断网络:
- 正常连接时发布;
- 确认返回前断线;
- 使用同一会话重连;
- 观察消息是否重试;
- 确认消费者正确处理重复;
- 确认过期指令不会执行。
还要测试大量客户端同时重连。单台设备很小的 QoS 状态,放大到设备群后可能非常可观。
推荐默认策略
高频、可替代的遥测从 QoS 0 开始;重要事件与指令从 QoS 1 开始。在考虑 QoS 2 前,先把消费者幂等做好。
要了解完整协议模型,请阅读 MQTT 协议概览。使用主题设计指南明确权限与消息含义,并在生产设备启用持久会话前检查 MQTT 安全指南。MQTT 教程提供了可直接执行的发布与订阅命令。
