MQTT-Grundlagen

MQTT Retained Messages: Funktionsweise und sinnvolle Einsatzfälle

Mit dem Retain-Flag übergibt ein MQTT-Broker jedem neuen Subscriber sofort den letzten bekannten Wert eines Topics. Erfahren Sie, wie das funktioniert, wo es glänzt und wo es zu Fehlern durch veraltete Daten führt.

Broker, der den letzten Wert jedes Topics speichert, als Illustration von MQTT Retained Messages für neue Subscriber
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

MQTT Retained Messages lösen ein einfaches, aber lästiges Problem: Ein Client, der ein Topic abonniert, muss auf das nächste Publish warten, bevor er irgendetwas weiß. Mit dem Retain-Flag behält der Broker die letzte Nachricht auf diesem Topic und liefert sie jedem neuen Subscriber sofort aus. In diesem Leitfaden sehen Sie genau, wie sich Retained Messages verhalten, probieren sie auf dem öffentlichen MQTT-Broker aus und lernen, wann Sie sie einsetzen und wann Sie besser darauf verzichten.

Was MQTT Retained Messages sind

Jedes MQTT-PUBLISH-Paket trägt ein Ein-Bit-Retain-Flag. Publiziert ein Client mit gesetztem Retain-Flag, tut der Broker zweierlei: Er leitet die Nachricht wie gewohnt an aktuelle Subscriber weiter und speichert eine Kopie als Retained Message für genau dieses Topic. Jedes Topic hält höchstens eine Retained Message, ein neues Retained-Publish ersetzt also das alte.

Abonniert später ein Client einen Filter, der auf dieses Topic passt, sendet der Broker die gespeicherte Nachricht direkt nach dem SUBACK. Der Subscriber sieht bei dieser Zustellung das gesetzte Retain-Flag, das ihm sagt: „Das ist der letzte bekannte Wert, kein frisches Ereignis.“ Auch Wildcard-Subscriptions funktionieren: Ein Abonnement von factory/+/status liefert die Retained Message jedes passenden Topics auf einmal.

Einige Regeln, die man leicht übersieht:

  • Die Speicherung erfolgt pro Topic, nicht pro Client. Jeder Client darf den Retained-Wert überschreiben.
  • Ein Publish mit Retain und leerem (null Byte langem) Payload löscht die Retained Message.
  • Nachrichten, die an bereits verbundene Subscriber weitergeleitet werden, kommen in MQTT 3.1.1 normalerweise mit gelöschtem Retain-Flag an. MQTT 5 ergänzt die Subscription-Option „Retain as Published“, um es zu erhalten.
  • Die QoS der Retained-Zustellung ist der niedrigere Wert aus der QoS der gespeicherten Nachricht und der QoS der Subscription.

Wenn Sie auffrischen möchten, wie ein Broker Nachrichten generell routet, lesen Sie zuerst Was ein MQTT-Broker macht.

Wie das Retain-Flag die Zustellung verändert

Am einfachsten verstehen Sie den Unterschied, wenn Sie dasselbe Publish mit und ohne Retain vergleichen.

Szenario Retain false Retain true
Subscriber beim Publish online Erhält die Nachricht Erhält die Nachricht
Subscriber verbindet sich 5 Minuten später Erhält nichts bis zum nächsten Publish Erhält sofort den letzten Wert
Zweites Publish auf demselben Topic Zugestellt, nichts gespeichert Zugestellt, ersetzt den gespeicherten Wert
Publish mit leerem Payload Liefert eine leere Nachricht Löscht den gespeicherten Wert
Wildcard-Subscription Nur künftige Nachrichten Letzter Wert jedes passenden Topics

Deshalb werden Retained Messages oft als „letzter bekannter guter Wert“ beschrieben. Sie verwandeln einen Strom von Ereignissen in etwas, das Sie durch Abonnieren abfragen können.

Retained Messages auf dem öffentlichen MQTT-Broker ausprobieren

Mit den Mosquitto-Kommandozeilentools testen Sie das in weniger als einer Minute gegen den öffentlichen MQTT-Broker unter broker.connectmq.com. Er akzeptiert anonyme Verbindungen mit jeder nicht leeren Client ID und ist für Tests und Prototypen gedacht, nicht für Produktionsdaten. Verwenden Sie ein eindeutiges Topic-Präfix, denn alles auf dem öffentlichen MQTT-Broker ist für jeden lesbar.

Publizieren Sie zuerst einen Retained-Wert und trennen Sie dann die Verbindung:

mosquitto_pub -h broker.connectmq.com -p 1883 -i demo-pub-r7k2 \
  -t connectmq/demo/r7k2/thermostat/setpoint \
  -m '{"setpoint":21.5,"unit":"C"}' -q 1 -r

Abonnieren Sie nun in einem anderen Terminal. Obwohl niemand publiziert, kommt der Wert sofort an. Das Flag -v gibt das Topic aus, und mit -F zeigen wir das Retain-Flag explizit an:

mosquitto_sub -h broker.connectmq.com -p 1883 -i demo-sub-r7k2 \
  -t 'connectmq/demo/r7k2/#' -F 'retained=%r %t %p'

Sie sollten retained=1 gefolgt von Topic und Payload sehen. Publizieren Sie bei geöffnetem Subscriber erneut ohne -r, zeigt die neue Zeile retained=0, weil es sich um eine Live-Nachricht und keine gespeicherte handelt.

Um den Retained-Wert zu löschen, publizieren Sie eine leere Retained Message. Das Flag -n sendet einen Null-Payload:

mosquitto_pub -h broker.connectmq.com -p 1883 -i demo-pub-r7k2 \
  -t connectmq/demo/r7k2/thermostat/setpoint -r -n

Abonnieren Sie erneut, und es kommt nichts zurück. Das Aufräumen inklusive Skripten für Wildcard-Bereinigung behandeln wir ausführlicher in So löschen Sie eine Retained Message.

Retained Messages aus Python publizieren

Im Anwendungscode ist das Retain-Flag nur ein Parameter. Hier ein vollständiges Beispiel mit paho-mqtt 2.x, das einen Gerätezustand als Retained Message publiziert und ihn mit einem frischen Client wieder ausliest:

import json
import time
import uuid
import paho.mqtt.client as mqtt

BROKER = "broker.connectmq.com"
PREFIX = f"connectmq/demo/{uuid.uuid4().hex[:6]}"
TOPIC = f"{PREFIX}/pump-07/state"

# 1. Zustand als Retained Message publizieren und trennen
pub = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"pub-{uuid.uuid4().hex[:8]}")
pub.connect(BROKER, 1883, keepalive=30)
pub.loop_start()
info = pub.publish(TOPIC, json.dumps({"running": True, "rpm": 1480}), qos=1, retain=True)
info.wait_for_publish()
pub.loop_stop()
pub.disconnect()

# 2. Ein neuer Subscriber erhält den gespeicherten Wert sofort
def on_connect(client, userdata, flags, reason_code, properties):
    client.subscribe(TOPIC, qos=1)

def on_message(client, userdata, msg):
    print(f"{msg.topic} retain={msg.retain} payload={msg.payload.decode()}")

sub = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"sub-{uuid.uuid4().hex[:8]}")
sub.on_connect = on_connect
sub.on_message = on_message
sub.connect(BROKER, 1883, keepalive=30)
sub.loop_start()
time.sleep(3)
sub.loop_stop()
sub.disconnect()

Der Subscriber gibt retain=True aus, obwohl er sich erst verbunden hat, nachdem der Publisher schon weg war. In einem Dashboard oder einem digitalen Zwilling bedeutet das: Die Oberfläche kann den aktuellen Zustand beim Laden anzeigen, statt leere Felder zu zeigen.

Wann Sie MQTT Retained Messages einsetzen

Retained Messages eignen sich am besten für Daten, die einen aktuellen Zustand beschreiben, nicht ein Ereignis:

  1. Gerätestatus. Online/Offline-Flags, Firmware-Version, Betriebsmodus. Kombiniert mit Last Will ergibt das eine zuverlässige Präsenzerkennung; siehe MQTT-Online-Status von Geräten.
  2. Konfiguration und Sollwerte. Ein Gerät, das neu startet, abonniert sein Konfigurations-Topic und erhält seine Einstellungen ohne separaten API-Aufruf.
  3. Langsam veränderliche Messwerte. Ein Tankfüllstand, der alle 10 Minuten aktualisiert wird, nützt einem gerade geöffneten Dashboard nichts, wenn der letzte Wert nicht gespeichert ist.
  4. Discovery-Metadaten. Viele Tools aus Hausautomation und Industrie publizieren Retained-Deskriptoren, damit neue Konsumenten Geräte finden.
  5. Anfangszustand digitaler Zwillinge. Ein Zwilling braucht beim Start ein vollständiges Bild, und Retained-Topics liefern es mit einem einzigen Wildcard-Abonnement.

In einem Unified Namespace (UNS) ist genau das der Normalfall: Jeder Knoten der ISA-95-Hierarchie (Enterprise → Site → Area → Line → Cell) publiziert seinen aktuellen Zustand retained, etwa unter acme/werk-stuttgart/montage/linie-1/zelle-3/status. Ein MES, ein Dashboard oder ein digitaler Zwilling erhält dann mit einem Abonnement auf acme/werk-stuttgart/# sofort das vollständige Bild des Werks. Wie das mit Sparkplug B zusammenspielt, zeigt der Artikel Sparkplug B und Unified Namespace.

Wann Sie auf Retained Messages verzichten sollten

Das Retain-Flag ist weder Datenbank noch Queue. Vermeiden Sie es für:

  • Ereignisse und Befehle. Ein gespeicherter Befehl „Ventil öffnen“ wird jedem Gerät erneut zugestellt, das später abonniert – auch nach einem Neustart. Das ist ein klassischer und gefährlicher Fehler. Befehle sollten nicht retained sein, idealerweise mit einem Ablaufdatum; siehe das MQTT Message Expiry Interval.
  • Historie hochfrequenter Telemetrie. Nur die letzte Nachricht wird gespeichert. Brauchen Sie Historie, betreiben Sie einen Subscriber, der in eine Zeitreihendatenbank schreibt.
  • Alarme, die quittiert werden müssen. Ein gespeicherter Alarm bleibt sichtbar, nachdem er aufgehoben wurde, sofern ihn nichts explizit überschreibt.

Fallstricke und Fehlersuche

Veraltete Werte nach der Stilllegung eines Geräts. Retained Messages leben, bis jemand sie löscht. Nehmen Sie das Aufräumen in Ihren Stilllegungsprozess auf und publizieren Sie für jedes Topic, das dem Gerät gehörte, einen leeren Retained-Payload.

Geisterdaten aus Testläufen. Während der Entwicklung bleibt leicht Retained-Datenmüll auf Topics zurück. Ein eindeutiges Präfix pro Projekt macht das Aufräumen mit einem Wildcard-Subscriber deutlich einfacher.

Unerwartete Wiederholungen beim erneuten Abonnieren. Jedes SUBSCRIBE löst die Retained-Zustellung erneut aus, was Code überraschen kann, der beim Reconnect neu abonniert. MQTT 5 bietet die Subscription-Option Retain Handling: 0 sendet Retained Messages bei jedem Subscribe, 1 nur bei einer neuen Subscription, 2 nie. Prüfen Sie, ob Ihre Client-Bibliothek sie bereitstellt.

Retain-Flag erscheint bei Live-Nachrichten als false. Das ist in MQTT 3.1.1 so vorgesehen. Hängt Ihre Logik davon ab, ob eine Nachricht ursprünglich retained war, nutzen Sie MQTT 5 mit Retain as Published.

Retained-Werte nach einem Broker-Neustart. Ob Retained Messages einen Neustart des Brokers überstehen, hängt von dessen Persistenzkonfiguration ab. Entwerfen Sie Geräte so, dass sie ihren Zustand periodisch oder beim Reconnect erneut publizieren, damit ein frischer Broker schnell wieder befüllt ist, statt anzunehmen, der Retained-Speicher sei dauerhaft.

Das Verhalten ist in der OASIS-MQTT-5.0-Spezifikation definiert, falls Sie den exakten normativen Wortlaut brauchen.

Retained Messages auf einem verwalteten MQTT-Broker

Bei einem verwalteten MQTT-Broker konfigurieren Sie den Retained-Speicher nicht selbst, das Topic-Design liegt aber weiterhin bei Ihnen. ConnectMQ unterstützt Retained Messages unter MQTT 3.1.1 und 5.0, und das Portal enthält einen Live-Topic-Explorer und einen browserbasierten MQTT-Client. So können Sie Ihr Präfix abonnieren und zusehen, wie Retained-Werte im Moment der Verbindung eintreffen. Damit erkennen Sie leicht veraltete Testdaten oder ein Gerät, das nie hinter sich aufgeräumt hat.

Eine praktische Checkliste vor dem Produktivbetrieb:

  1. Pro Topic entscheiden: Zustand (retain) oder Ereignis (kein retain).
  2. Befehle niemals retained senden.
  3. Zustand bei jedem Reconnect erneut publizieren, nicht nur bei Änderungen.
  4. Retained-Topics leeren, wenn Geräte ausgemustert werden.
  5. Retained-Payloads klein halten; jeder neue Subscriber erhält sie alle auf einmal.

Mehr zum Protokoll als Ganzes bietet das MQTT-Tutorial, das Publish, Subscribe, QoS und Sessions durchgängig erklärt, und der Leitfaden zum Cloud-MQTT-Broker zeigt, wie verwaltete MQTT-Broker in ein reales Deployment passen.

Starten Sie mit ConnectMQ

Erstellen Sie unter app.connectmq.com einen kostenlosen Broker im Serverless-Plan, ganz ohne Kreditkarte. Sie erhalten in wenigen Minuten Benutzername, Passwort und Client ID und sehen Ihre Retained-Topics im ConnectMQ-Topic-Explorer erscheinen, sobald Ihr erstes Gerät publiziert.

Häufig gestellte Fragen

Wie viele Retained Messages kann ein Topic haben?

Genau eine. Ein neues Retained-Publish auf demselben Topic ersetzt das vorherige, und ein leerer Retained-Payload entfernt es.

Laufen Retained Messages ab?

In MQTT 3.1.1 standardmäßig nicht. In MQTT 5 können Sie für ein Retained-Publish ein Message Expiry Interval setzen; danach liefert der Broker die Nachricht nicht mehr an neue Subscriber aus.

Beeinflusst QoS Retained Messages?

Die Retained Message behält die QoS, mit der sie publiziert wurde, und ein neuer Subscriber erhält sie mit dem niedrigeren Wert aus dieser QoS und der QoS seiner eigenen Subscription.

Kann ich sehen, welche Topics Retained Messages haben?

Abonnieren Sie eine breite Wildcard wie your/prefix/#, und jede darunter liegende Retained Message wird sofort zugestellt. Bei ConnectMQ geht das ebenso mit dem browserbasierten Client im Portal.

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.