MQTT-Grundlagen

MQTT Retained Message löschen (CLI, Python und Web-Client)

Eine veraltete Retained Message begrüßt jeden neuen Subscriber mit alten Daten. So löschen Sie eine Retained Message in MQTT mit einem leeren Retained-Publish, per Kommandozeile, Python, JavaScript und Browser-Client.

Illustration eines Broker-Topic-Baums, in dem ein veralteter Wert entfernt wird, um zu zeigen, wie man eine MQTT Retained Message löscht
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

Um eine MQTT Retained Message zu löschen, brauchen Sie kein Admin-Tool für den Broker: Sie veröffentlichen auf demselben Topic einen Payload der Länge null mit gesetztem Retain-Flag, und der Broker verwirft den gespeicherten Wert. Dieser Leitfaden zeigt die Technik per Kommandozeile, Python, JavaScript und Browser-Client und erklärt, wie Sie veraltete Retained Topics finden und sicher in großen Mengen bereinigen.

Warum Retained Messages hängen bleiben

Eine Retained Message ist die letzte Nachricht, die ein Broker für ein Topic speichert, damit jeder neue Subscriber sofort den aktuellen Wert erhält. Genau das wollen Sie für einen Gerätestatus, ein Konfigurationsdokument oder den neuesten Sensorwert. Wenn Ihnen die Funktion neu ist, erklärt der Leitfaden zu MQTT Retained Messages die Mechanik im Detail.

Problematisch wird es, wenn der gespeicherte Wert nicht mehr stimmt. Typische Situationen:

  • Ein Gerät wurde außer Betrieb genommen, aber sein letzter Status online taucht weiter in Dashboards auf.
  • Ein Test-Publish mit gesetztem Retain-Flag aus der Entwicklung verunreinigt jetzt einen produktiven Topic-Baum.
  • Ein Konfigurations-Topic wurde umbenannt, und das alte liefert neuen Clients weiterhin veraltete Einstellungen.
  • Eine Maschine wurde im Werk von Linie 1 an Linie 2 umgesetzt, doch im Unified Namespace (UNS) meldet ihr alter ISA-95-Pfad, etwa acme/werk-stuttgart/montage/linie-1/zelle-3/status, weiterhin running.
  • Ein Firmware-Bug hat fehlerhaftes JSON mit Retain veröffentlicht, und jeder neu verbundene Subscriber stürzt daran ab.

Da der Broker den Retained-Wert bei jeder neuen Subscription erneut ausliefert, verschwindet das Problem nie von selbst. Sie müssen den gespeicherten Wert ersetzen oder entfernen.

So löschen Sie eine Retained Message in MQTT

Die MQTT-Spezifikation definiert die Regel in einem Satz: Ein PUBLISH-Paket mit RETAIN-Flag 1 und einem Payload der Länge null entfernt jede Retained Message für dieses Topic, und der Broker speichert keine neue. Die leere Nachricht wird außerdem an aktuelle Subscriber weitergeleitet. Ihre Consumer sollten einen leeren Payload daher tolerieren, statt zu versuchen, ihn als JSON zu parsen.

In der Praxis kommt es auf einige Details an:

  1. Das Topic muss exakt übereinstimmen. Retained Messages werden pro Topic-Name gespeichert. Eine leere Retained Message an sensors/# bewirkt nichts, da Wildcards in Topic-Namen, auf die Sie veröffentlichen, nicht erlaubt sind.
  2. Der Payload muss wirklich leer sein. Ein einzelnes Leerzeichen, ein leeres JSON-Objekt {} oder der String null sind echte Payloads und werden als neuer Wert gespeichert.
  3. Der QoS spielt kaum eine Rolle. QoS 0 reicht zum Aufräumen, QoS 1 liefert Ihnen aber eine Bestätigung, dass der Broker die Nachricht erhalten hat.
  4. Sie brauchen Publish-Rechte auf dem Topic. Dürfen Ihre Zugangsdaten dort nicht veröffentlichen, wird die Löschung je nach Broker und Protokollversion abgelehnt oder stillschweigend verworfen.

Retained Messages mit mosquitto_pub löschen

Die Mosquitto-Kommandozeilentools sind der schnellste Weg, ein einzelnes Topic zu bereinigen. Das Flag -r setzt Retain, und -n sendet eine Null-Nachricht (Länge null):

# Prüfen, was aktuell auf dem Topic retained ist
mosquitto_sub -h broker.connectmq.com -p 1883 -i inspect-7f3a \
  -t "connectmq/demo/7f3a/device42/status" -v -C 1 -W 5

# Retained Message löschen
mosquitto_pub -h broker.connectmq.com -p 1883 -i cleanup-7f3a \
  -t "connectmq/demo/7f3a/device42/status" -r -n

# Bestätigen: Das sollte jetzt ohne Ausgabe in den Timeout laufen
mosquitto_sub -h broker.connectmq.com -p 1883 -i verify-7f3a \
  -t "connectmq/demo/7f3a/device42/status" -v -C 1 -W 5

Die Kombination -C 1 -W 5 lässt mosquitto_sub nach einer Nachricht oder fünf Sekunden beenden und macht es so zu einem schnellen Test, ob hier etwas retained ist. Die Beispiele verwenden den öffentlichen MQTT-Broker, der nur für Tests gedacht ist, mit einem eindeutigen Präfix; ersetzen Sie 7f3a durch Ihre eigene zufällige ID.

Auf einem privaten Broker ergänzen Sie Zugangsdaten und TLS:

mosquitto_pub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
  -u YOUR_USERNAME -P YOUR_PASSWORD -i YOUR_CLIENT_ID \
  -t "plant1/line2/press/status" -r -n -q 1

Massenbereinigung mit --remove-retained

mosquitto_sub bietet eine hilfreiche Option für ganze Teilbäume. Mit --remove-retained wird jede empfangene Retained Message gelöscht, indem eine leere Retained Message an dasselbe Topic zurückgesendet wird. Kombinieren Sie die Option mit --retained-only, damit nur Retained-Werte berührt und Live-Daten ignoriert werden:

mosquitto_sub -h broker.connectmq.com -p 1883 -i purge-7f3a \
  -t "connectmq/demo/7f3a/#" --retained-only --remove-retained -v -W 5

Führen Sie zuerst den Prüfbefehl aus, lesen Sie die Liste sorgfältig und bereinigen Sie erst dann. Eine Wildcard wie # auf einem geteilten Baum kann weit mehr löschen als beabsichtigt.

Retained Message mit Python löschen

Wenn das Aufräumen Teil eines Skripts zur Außerbetriebnahme ist, bietet sich Python mit paho-mqtt 2.x an. Mit payload=None entsteht ein Payload der Länge null:

import time
import paho.mqtt.client as mqtt

BROKER = "broker.connectmq.com"
TOPIC = "connectmq/demo/7f3a/device42/status"

def on_connect(client, userdata, flags, reason_code, properties):
    print("Connected:", reason_code)
    info = client.publish(TOPIC, payload=None, qos=1, retain=True)
    info.wait_for_publish(timeout=5)
    print("Retained message cleared on", TOPIC)
    client.disconnect()

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="cleanup-py-7f3a")
client.on_connect = on_connect
client.connect(BROKER, 1883, keepalive=30)
client.loop_forever()

Einen ganzen Teilbaum finden und bereinigen

Diese Variante abonniert mit einer Wildcard, sammelt in einem kurzen Zeitfenster jedes Topic, das eine Retained Message liefert, und löscht sie anschließend nacheinander. Sie drosselt das Veröffentlichen, was auf dem öffentlichen MQTT-Broker wichtig ist, wo jeder Client auf 10 Nachrichten pro Sekunde begrenzt ist.

import time
import paho.mqtt.client as mqtt

BROKER = "broker.connectmq.com"
FILTER = "connectmq/demo/7f3a/#"
found = set()

def on_message(client, userdata, msg):
    if msg.retain and msg.payload:
        found.add(msg.topic)

def on_connect(client, userdata, flags, reason_code, properties):
    client.subscribe(FILTER, qos=1)

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="purge-py-7f3a")
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, 1883, keepalive=30)
client.loop_start()
time.sleep(3)  # Retained Messages sammeln

print(f"Found {len(found)} retained topics")
for topic in sorted(found):
    print("Clearing", topic)
    client.publish(topic, payload=None, qos=1, retain=True).wait_for_publish(5)
    time.sleep(0.15)  # unter dem Rate-Limit pro Client bleiben

client.loop_stop()
client.disconnect()

Beachten Sie die Prüfung msg.retain. Broker setzen das Retain-Flag bei Nachrichten, die aufgrund einer neuen Subscription zugestellt werden. So werden Live-Nachrichten, die zufällig im Zeitfenster eintreffen, nicht mit gespeicherten Werten verwechselt.

Retained Message per JavaScript oder im Browser löschen

Mit MQTT.js gilt dieselbe Regel: ein leerer String oder leerer Buffer mit retain: true.

const mqtt = require("mqtt");

const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
  clientId: "cleanup-js-7f3a",
  protocolVersion: 5,
});

client.on("connect", () => {
  client.publish(
    "connectmq/demo/7f3a/device42/status",
    "",
    { qos: 1, retain: true },
    (err) => {
      console.log(err ? `Failed: ${err.message}` : "Retained message cleared");
      client.end();
    }
  );
});

Wenn Sie lieber gar keinen Code schreiben möchten, funktioniert auch der browserbasierte MQTT-Client im Portal von ConnectMQ: Verbinden Sie sich mit Ihrem Broker, geben Sie das exakte Topic ein, lassen Sie das Payload-Feld leer, aktivieren Sie Retain und veröffentlichen Sie. Mit dem Live-Topic-Explorer sehen Sie vor und nach der Bereinigung gut, welche Topics noch einen Wert enthalten.

Fehlerbehebung, wenn eine Retained Message nicht verschwindet

Symptom Wahrscheinliche Ursache Lösung
Alter Wert taucht Sekunden später wieder auf Ein Gerät oder Dienst veröffentlicht ihn weiterhin mit Retain Publisher finden, Retain-Flag korrigieren, dann erneut löschen
Nach dem leeren Publish ändert sich nichts Topic stimmt nicht überein (Groß-/Kleinschreibung, abschließender Schrägstrich, zusätzliche Ebene) Exaktes Topic aus einer -v-Subscription-Ausgabe kopieren
Subscriber stürzen nach der Bereinigung ab Consumer parsen den leeren Payload Nachrichten der Länge null im Message-Handler überspringen
Wert wird ersetzt statt entfernt Payload war ein Leerzeichen, {} oder null -n oder payload=None verwenden, keinen Platzhalter-String
Bereinigung klappt im Test, nicht in Produktion Zugangsdaten fehlen Publish-Rechte auf dem Topic Das Konto verwenden, dem der Topic-Baum gehört

Die erste Zeile ist mit Abstand die häufigste. Ein Retained-Wert, der „zurückkommt“, wird fast immer von irgendetwas erneut veröffentlicht, oft von einem Bridge-Skript, einem Node-RED-Flow oder einem Gerät, das seinen Status bei jedem Reconnect mit Retain sendet.

Veraltete Retained-Daten von vornherein vermeiden

Das Löschen von Retained Messages ist Aufräumarbeit; ein gutes Design reduziert, wie oft Sie sie brauchen.

  • Nutzen Sie den Nachrichtenablauf von MQTT 5. Setzen Sie bei Retained-Publishes ein Message Expiry Interval, damit der Broker sie nach einer gewissen Zeit verwirft. Der Leitfaden zum Message Expiry Interval behandelt sinnvolle Werte.
  • Kombinieren Sie den Status mit Last Will. Ein retained Status online sollte mit einem retained Last Will offline gepaart werden, damit der gespeicherte Wert korrekt bleibt, wenn ein Gerät ausfällt.
  • Halten Sie Retained Topics schmal. Speichern Sie Zustand, keine Datenströme. Hochfrequente Telemetrie braucht selten Retain, und weniger Retained Topics bedeuten weniger Aufräumarbeit.
  • Behandeln Sie Retained Messages nicht als Datenbank. Sie halten bequem den neuesten Wert vor, keine dauerhafte Historie. Speichern Sie alles, was Sie behalten müssen, in einer echten Datenbank, die ein Subscriber befüllt.
  • Dokumentieren Sie, welche Topics retained sind. Eine kurze Liste in Ihren Topic-Namenskonventionen verhindert Überraschungen, wenn jemand eine Wildcard-Subscription hinzufügt.

Das vollständige Verhalten des Retain-Flags ist im OASIS-MQTT-5.0-Standard spezifiziert, und das umfassendere MQTT-Tutorial setzt Retained Messages in den Kontext von QoS, Sessions und Wills.

Retained Topics bei ConnectMQ verwalten

ConnectMQ unterstützt Retained Messages sowohl unter MQTT 3.1.1 als auch unter 5.0, daher funktionieren alle oben gezeigten Techniken unverändert. Wenn Sie über Experimente hinausgehen, bietet Ihnen ein verwalteter MQTT-Broker private Zugangsdaten, TLS auf Port 8883 und ein Portal mit browserbasiertem Client und Live-Topic-Explorer für genau diese Art von Wartung. Mehr dazu, wie Sie einen MQTT-Broker in der Cloud betreiben, ohne selbst Server zu verwalten, lesen Sie hier.

Erstellen Sie unter app.connectmq.com einen kostenlosen Serverless-Broker, ganz ohne Kreditkarte, und Sie haben in wenigen Minuten Benutzername, Passwort und Client ID.

Häufig gestellte Fragen

Wie lösche ich eine Retained Message in MQTT?

Veröffentlichen Sie eine Nachricht mit einem Payload der Länge null und gesetztem Retain-Flag auf genau demselben Topic. Mit Mosquitto ist das mosquitto_pub -t <topic> -r -n, und der Broker speichert für dieses Topic keinen Retained-Wert mehr.

Kann ich alle Retained Messages mit einer Wildcard löschen?

Nicht mit einem einzelnen Publish, da Wildcards in Topic-Namen nicht erlaubt sind. Abonnieren Sie mit einem Wildcard-Filter, um Retained Topics zu finden, und löschen Sie dann jedes einzeln, oder verwenden Sie mosquitto_sub --retained-only --remove-retained.

Löscht ein leeres JSON-Objekt die Retained Message?

Nein. {} ist ein Payload von zwei Byte, daher speichert der Broker ihn als neuen Wert. Nur ein wirklich leerer Payload entfernt die Retained Message.

Erhalten Subscriber die leere Nachricht?

Ja, aktuelle Subscriber erhalten die Nachricht der Länge null wie jedes andere Publish. Stellen Sie sicher, dass Ihre Consumer leere Payloads ignorieren, statt beim Parsen zu scheitern.

Verwandte Artikel

Wer hat MQTT erfunden? Die Geschichte von Ölpipelines bis zum IoT

MQTT wurde 1999 von Andy Stanford-Clark (IBM) und Arlen Nipper (Arcom) erfunden, um Ölpipelines per Satellit zu überwachen. Verfolgen Sie den Weg zu Open Source, OASIS, ISO und den heutigen verwalteten MQTT-Brokern in der Cloud.

8 Min. Lesezeit

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.