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)
└── MicroservicesMQTT为极低带宽+不稳定网络设计。最初为IOT、传感器网络设计。适用于设别算力弱。网络延迟高的场景。
MQTT协议甚至不强制要求持久化。直接进行实时转发。MQTT的设计重点通常不是吞吐,而是轻量级通信。如EMQX默认所有数据都存储在内存中。通过规则引擎(Rule Engine)和数据桥接(Data Bridge),可以将消息、客户端上下线事件等数据持久化到外部数据库(如 MySQL、PostgreSQL、Redis、MongoDB 等)。这种方式通常用于业务数据归档或与外部系统集成。
总的来说MQTT是无状态的。MQTT的顺序消费还要结合Qos来保证。无论是Qos1还是2都不保证严格顺序。这个顺序更像是TCP的顺序,业务层要自己控制执行顺序(毕竟ack是自动回复的,而不是业务层实现的)。