【第二章10】 MQTT 保留消息

发布时间:2026/7/31 22:19:59
【第二章10】 MQTT 保留消息 一、MQTT 保留消息简介一、基础概念对比‌普通消息‌如果消息发布时对应的主题下没有任何订阅者MQTT服务器会直接将这条消息丢弃不会做任何留存。‌保留消息‌这类消息会被保存在MQTT服务器中后续任何新的订阅者订阅和该保留消息主题匹配的主题时都会立刻收到这条消息——哪怕这条消息是在订阅者发起订阅之前就已经发布的。文档中也通过示意图演示了这个流程发布者在10:00向主题sensor/t1发布消息服务器将这条消息存入保留消息存储区当客户端在11:00订阅sensor/t1主题时服务器会立刻将这条历史保留消息推送给客户端。二、典型使用场景文档中列举了3个非常实用的落地场景‌智能家居状态同步‌智能家居设备仅在状态发生变更时才上报数据控制端上线后可以直接通过保留消息获取设备的最新状态不需要等待设备下一次状态上报。‌传感器数据即时获取‌部分传感器上报数据的间隔很长新的订阅者发起订阅后不需要等待传感器下一次上报就能立刻拿到最新的传感器数据。‌静态属性分发‌传感器的版本号、序列号这类几乎不会变更的属性设备上线后发布一条保留消息后续所有订阅该主题的新客户端都可以直接获取到这些属性信息。MQTT保留消息是MQTT协议中用于解决“新订阅者无法立即获取主题最新状态”问题的核心特性它和之前介绍的离线消息缓存、持久会话是完全独立的机制即使发布消息的客户端会话已经结束保留消息也不会被自动删除。二、认识MQTT 保留消息核心定义保留消息是发布时将Retained标志设置为true的普通MQTT消息MQTT服务端会为每个主题单独存储最新的一条保留消息。当新的客户端订阅该主题或匹配该主题的通配符主题时服务端会立即将这条保留消息推送给订阅者无需等待发布者下一次主动发消息。核心特性单主题单缓存每个主题最多仅存储1条保留消息新发布的同主题保留消息会直接覆盖旧的内容始终保留该主题的“最后已知有效状态”独立于会话保留消息不属于任何客户端的持久会话发布该消息的客户端断开连接、会话过期销毁后保留消息依然会保存在服务端订阅即推送只有在保留消息发布之后才发起订阅的客户端才能收到这条保留消息提前订阅的客户端不会自动收到已存在的保留消息需要取消订阅后重新订阅才能获取QoS兼容保留消息的存储逻辑不受消息QoS等级影响即使是QoS 0等级的消息只要设置了Retain标志也会被服务端存储典型使用场景智能家居场景设备仅在状态变更时上报数据用户打开控制App订阅设备状态主题后能立刻获取设备当前的在线/离线、开关状态无需等待设备下一次主动上报低频次传感器场景温湿度、定位传感器上报间隔长达数小时新接入的监控端订阅后可直接拿到最新的采集数据不用长时间等待静态属性同步场景传感器固件版本、设备序列号这类几乎不会变更的属性发布为保留消息后后续所有新接入的订阅者都能直接获取无需重复发布发布与删除操作‌发布保留消息‌几乎所有MQTT客户端库都提供了对应参数发布消息时将retainFlag设置为true即可比如ESP8266的PubSubClient库中调用publish(topic, payload, true)就能发布保留消息‌删除保留消息‌最通用的方式是向目标主题发布一条0字节负载的保留消息服务端收到后会自动删除该主题下的保留消息部分服务端还支持在管理后台手动删除MQTT 5.0版本还可以通过设置消息过期间隔让保留消息到期后自动销毁常见配置说明以主流的EMQX服务端为例支持灵活配置保留消息的运行规则存储方式可选内存存储或内存磁盘持久化存储持久化模式下服务端重启后保留消息不会丢失可设置最大存储条数、单条消息最大负载大小超出限制的普通保留消息会被当作非保留的普通消息处理支持配置保留消息派发速率避免订阅者匹配大量通配符主题时一次性收到过多保留消息导致内存溢出三、如何发布和删除MQTT保留消息发布和删除MQTT保留消息的操作可以分为客户端侧通用配置、主流工具实操演示、服务端侧管理操作三个部分覆盖不同使用场景的需求一、通用发布规则发布保留消息的核心操作非常简单在调用MQTT客户端的发布接口时将消息的Retained标志设置为true即可。服务端会自动为该主题存储这条最新的保留消息后续新订阅该主题的客户端会立刻收到这条消息新发布的同主题保留消息会直接覆盖旧的内容每个主题最多仅保留1条有效保留消息保留消息不受QoS等级限制即使是QoS 0等级的消息只要设置了Retain标志就会被服务端存储二、主流工具发布实操‌MQTTX 桌面客户端‌创建好MQTT连接后在消息输入区域勾选界面上的「Retain」复选框填写目标主题和消息内容后点击发送即可完成保留消息发布。‌MQTTX CLI 命令行工具‌执行以下命令即可发布保留消息示例中向主题t/1发布指定内容的保留消息mqttx pub-tt/1-mA retained message from MQTTX CLI--retaintrue-hlocalhost-p1883‌Mosquitto 命令行工具‌使用mosquitto_pub命令添加-r参数即可发布保留消息mosquitto_pub-r-q1-ta/b/c-mhello三、删除保留消息的多种方式‌客户端主动发布空保留消息‌这是协议层面通用的删除方式向目标主题发布一条Payload长度为0的保留消息服务端收到后会自动删除该主题下的保留消息。以MQTTX CLI为例执行以下命令即可完成删除mqttx pub-tt/1-m--retaintrue-hlocalhost-p1883‌MQTT 5.0 自动过期删除‌在发布保留消息时通过MQTT 5.0新增的「消息过期间隔」属性设置消息的有效时长到期后服务端会自动清理这条保留消息无需手动操作。‌服务端管理后台手动删除‌以EMQX服务端为例在Dashboard的「监控 - 保留消息」页面可以查看所有已存储的保留消息直接选中指定主题的消息点击删除即可还支持通过REST API批量删除保留消息。‌服务端配置规则自动清理‌可以在服务端配置保留消息的全局有效期设置后所有未单独指定过期时间的保留消息达到配置的时长后会被自动回收清理。三、如何通过REST API批量删除MQTT保留消息以主流的EMQX MQTT服务端为例通过REST API批量删除保留消息的完整操作流程如下前置准备确认EMQX服务已开启REST API服务默认API端口为8081可在服务端配置文件中确认端口与访问权限设置提前获取EMQX的API访问凭证默认管理员账号密码为admin/public需提前在Dashboard中完成账号配置核心批量删除操作EMQX提供了原生的保留消息批量删除API无需额外编写复杂脚本即可完成全量或指定范围的清理‌删除集群所有保留消息‌向EMQX的管理API地址发送DELETE请求即可一次性清空集群中所有存储的保留消息示例请求如下curl-uadmin:public-XDELETEhttp://你的EMQX服务地址:8081/api/v5/retained/messages请求执行成功后会返回操作成功的状态码集群内所有节点上的保留消息都会被同步清除。‌按主题筛选批量删除‌如果不需要清空全部保留消息可先调用GET请求获取所有保留消息的主题列表通过通配符筛选出需要删除的目标主题再循环调用单条保留消息删除接口完成批量清理第一步获取全量保留消息列表curl-uadmin:publichttp://你的EMQX服务地址:8081/api/v5/retained/messages返回结果中会包含所有保留消息的主题、QoS、发布时间等完整信息。第二步筛选出需要删除的主题后调用单条删除接口指定主题URL编码后传入即可删除对应保留消息可通过脚本循环执行实现批量删除curl-uadmin:public-XDELETEhttp://你的EMQX服务地址:8081/api/v5/retained/messages/URL编码后的目标主题注意事项执行全量删除前建议先调用GET接口导出保留消息列表做备份避免误删需要保留的状态数据如果EMQX开启了保留消息的磁盘持久化存储API删除操作会同时清理内存和磁盘上的对应数据无需额外重启服务部分第三方MQTT服务端的REST API实现可能存在差异可参考对应服务端的官方API文档调整请求路径和鉴权方式。