MQTT学习笔记

MQTT主题设计最佳实践 - 数字基座

简介

写给那些已经学习过消息队列的人()

或者间接连接。比如移动网络,卫星网络等。协议非常轻量header只有2字节。

MQTT只有一种通信模型

Publisher → Broker → Subscriber

例如

temperature/sensor1
temperature/sensor2

设备只关心topic,topic是层级字符串,支持通配符订阅。

temperature/+
temperature/#

不同于消息队列mqtt有统一的开源标准化协议。由OASIS 维护。

通信模式

MQTT支持多种模式

如点对点:每个消息只消费一次

Producer → Queue → Consumer

发布订阅:每个订阅者都收到消息。

流处理

MQTT的Qos从高到低依次为

Qos 0:至多依次(at most once1)

发布者发送消息后不等确认,直接发送下一条消息。代理收到消息后直接转发给订阅者,同样不等待订阅者确认。

Qos 1:至少一次(at least once)

这是中等级别,确保消息至少被送达一次,但可能重复。

发布者发送消息后,会等待代理返回一个 PUBACK(发布确认)包。如果超时未收到确认,发布者会重新发送消息,直到收到确认为止。代理收到消息后,会存储消息,并确保将其发送给订阅者(同样需要订阅者的确认)。

消息不会丢失知道重试成功。

Qos 2:恰好一次(exaclly once)

最高的级别。确保消息仅有一次被送达。这个机制通过四次握手实现(four way handshake)

PUBLISH:发布者发送消息。

PUBREC:代理收到后回复“已接收”。

PUBREL:发布者收到确认后,发送“释放”信号。

PUBCOMP:代理回复“完成”,此时双方才确认消息处理完毕。

Qos机制只是传输层的机制,只负责消息物理上从生产者到消费者,但无法感知消费者应用层代码是否执行成功。

PUBREC/PUBCOMP 由 MQTT client library 自动发送。而不是等你业务处理完成后再发。


MQTT没有类似消息队列中的DLQ(死信队列)的实现。MQTT语义是传递保证,而不是处理保证。因此broker不会感知业务是否处理成功。

QoS2保证的是“协议层 exactly-once”,不是“业务 exactly-once”。这里的ack和kafka不同的是收到消息就ack,而不是完成处理才ack。

MQTT 本身只是一个消息传输协议,是否把消息保存到磁盘、保存多久、是否清理,取决于具体的 MQTT Broker 实现和配置。不同 Broker(如 Eclipse Mosquitto、EMQX、HiveMQ)策略会不同。可以从几个机制来理解。

如果要保证消费成功可以通过应用层ack

Producer → MQTT → Consumer
                   ↓
                处理成功
                   ↓
            publish ack message

例如

topic: order/create
topic: order/create/ack

和消息队列的区别

mqtt 出现的更早,是1999年的,kafka是2011年。并且一般kafka的生产者都是内网的机器有单独的稳定的IP。而mqtt生产者可能只有NAT的IP,并且无法固定。

以EMQX距离,吞吐量能来到50w到100w。kafka在100w-1000w。由于许多应用层消费逻辑都只适配了kafka的。你甚至可以把MQTT消息桥接到kafka

IoT Device / Client
        │
        ▼
   MQTT Broker
   (EMQX / HiveMQ / Mosquitto)
        │
        │ MQTT → Kafka Bridge / Connector
        ▼
      Kafka Cluster
        │
        ├── Stream processing (Kafka Streams / Flink / Spark)
        ├── Storage (Data lake / DB)
        └── Microservices

MQTT为极低带宽+不稳定网络设计。最初为IOT、传感器网络设计。适用于设别算力弱。网络延迟高的场景。

MQTT协议甚至不强制要求持久化。直接进行实时转发。MQTT的设计重点通常不是吞吐,而是轻量级通信。如EMQX默认所有数据都存储在内存中。通过规则引擎(Rule Engine)和数据桥接(Data Bridge),可以将消息、客户端上下线事件等数据持久化到外部数据库(如 MySQL、PostgreSQL、Redis、MongoDB 等)。这种方式通常用于业务数据归档或与外部系统集成。

总的来说MQTT是无状态的。MQTT的顺序消费还要结合Qos来保证。无论是Qos1还是2都不保证严格顺序。这个顺序更像是TCP的顺序,业务层要自己控制执行顺序(毕竟ack是自动回复的,而不是业务层实现的)。

Last modification:March 11, 2026
如果觉得我的文章对你有用,请随意赞赏