Node-RED SD-Karte schonen: Persistent Context richtig nutzen
Im Beitrag „Node-RED Context nach Neustart behalten – so geht’s“ habe ich gezeigt, wie man Context-Daten in Node-RED dauerhaft speichern kann.
Dafür wird der sogenannte Persistent Context aktiviert. Node-RED speichert Werte dann nicht nur im Arbeitsspeicher, sondern zusätzlich im Dateisystem.
Gerade auf einem Raspberry Pi kommt dabei schnell eine wichtige Frage auf:
Kann das häufige Schreiben auf die SD-Karte zu Problemen führen?
Die kurze Antwort lautet: Ja, grundsätzlich sollte man Schreibzugriffe auf SD-Karten im Blick behalten. Für einfache Zähler, Zustände und Konfigurationswerte ist der Persistent Context aber in der Regel unkritisch.
https://youtu.be/uruYVypy1D4
Warum sind Schreibzyklen bei der Node-RED SD-Karte ein Thema?
SD-Karten nutzen Flash-Speicher. Dieser Speicher kann nicht unbegrenzt oft beschrieben werden.
Je nach Qualität der Karte, Speichertechnik und Controller gibt es deutliche Unterschiede. Sehr einfache Karten können eine deutlich geringere Lebensdauer haben als hochwertige Industrie- oder High-Endurance-Karten.
Deshalb sollte man bei Projekten mit Raspberry Pi immer überlegen, wie häufig Daten geschrieben werden.
Typische Beispiele für viele Schreibzugriffe sind:
- Logdateien - Messwerte in kurzen Intervallen - Datenbanken - temporäre Dateien - häufig aktualisierte Statusdateien
Wenn jede Sekunde neue Daten auf die SD-Karte geschrieben werden, kann das langfristig zu Problemen führen.
Wie schreibt Node-RED Context-Daten?
Beim localfilesystem Context Store schreibt Node-RED die Daten nicht zwangsläufig bei jeder einzelnen Änderung sofort auf die SD-Karte.
Stattdessen werden die Daten gepuffert und in Intervallen in das Dateisystem geschrieben.
Dafür gibt es unter anderem die Option flushInterval.
Ein Beispiel:
contextStorage: { default: { module: "localfilesystem", config: { cache: true, flushInterval: 30 } } }
Mit flushInterval: 30 legt Node-RED fest, in welchem Mindestabstand Daten in das Dateisystem geschrieben werden.
Das bedeutet: Wenn sich ein Context-Wert mehrfach innerhalb kurzer Zeit ändert, muss nicht jede Änderung sofort einen direkten Schreibvorgang auf die SD-Karte auslösen.
Ist das ein Problem für die SD-Karte?
Für einzelne Werte ist das normalerweise kein großes Problem.
Beispiele:
- ein Zählerstand - ein letzter Schaltzustand - eine Konfiguration - ein Grenzwert - ein Betriebsmodus - ein Merker innerhalb eines Flows
Solche Werte ändern sich meist nicht regelmäßig oder sind gering.
Problematisch wird es eher, wenn man versucht, viele Sensordaten in kurzen Intervallen im Persistent Context zu speichern.
Beispiele:
- Temperaturwert jede Sekunde - Stromverbrauch alle paar Sekunden - große JSON-Objekte - Messwert-Historien - viele verschiedene Sensoren gleichzeitig
Dafür ist der Persistent Context nicht die beste Lösung.
Bessere Lösung: Zwei Context Stores verwenden
Eine sehr saubere Lösung ist es, zwei Context Stores zu verwenden:
- einen flüchtigen Speicher im RAM - einen persistenten Speicher im Dateisystem
Die Idee dahinter ist einfach:
Standardmäßig bleiben Werte im Arbeitsspeicher. Nur Werte, die wirklich dauerhaft benötigt werden, werden gezielt im Dateisystem gespeichert.
Beispiel:
contextStorage: { default: "memoryOnly", memoryOnly: { module: "memory" }, file: { module: "localfilesystem" } }
Damit nutzt Node-RED standardmäßig den RAM. Der Dateispeicher wird nur verwendet, wenn man ihn bewusst auswählt.
Das ist besonders sinnvoll auf einem Raspberry Pi mit SD-Karte.
Speichern im File-Store
Wenn mehrere Context Stores definiert sind, kann man gezielt festlegen, wo ein Wert gespeichert wird.
Ein Wert im normalen RAM-Context:
flow.set("letzteTemperatur", 22.6);
Ein Wert im persistenten File-Context:
flow.set("letzteTemperatur", 22.6, "file");
Das Auslesen erfolgt entsprechend so:
let temperatur = flow.get("letzteTemperatur", "file");
Damit lässt sich perfekt steuern, welche Daten dauerhaft erhalten bleiben sollen.
Wann sollte ich welchen Store verwenden?
Den RAM-Context würde ich verwenden für:
- aktuelle Sensorwerte - temporäre Statuswerte - Zwischenberechnungen - Werte, die nach einem Neustart egal sind - häufig aktualisierte Daten
Den File-Context würde ich verwenden für:
- Zählerstände - Konfigurationswerte - letzte bekannte Zustände - Grenzwerte - Betriebsmodi - wichtige Merker
So hält man die Schreibzugriffe auf die SD-Karte gering und nutzt den Persistent Context trotzdem sinnvoll.
Das Schaubild vergleicht Arbeitsspeicher, persistenten Context und Datenbank in Node-RED und zeigt, welche Datentypen jeweils sinnvoll gespeichert werden sollten.
Wann sollte ich lieber eine Datenbank nutzen?
Wenn du viele Messwerte speichern und später auswerten möchtest, ist eine Datenbank meist die bessere Wahl.
Zum Beispiel für:
- Temperaturverläufe - Stromverbrauch über mehrere Tage - Diagramme - CSV-Export - historische Daten - viele Sensorwerte
Hier sind SQLite, InfluxDB oder andere Datenbanken besser geeignet als der Persistent Context.
Der Persistent Context ist ideal für wenige wichtige Zustände.
Eine Datenbank ist ideal für viele historische Werte.
Warum ist eine Datenbank dann nicht automatisch besser?
Eine berechtigte Frage ist: Wenn SQLite, PostgreSQL oder eine andere Datenbank ebenfalls auf der SD-Karte liegt, entstehen doch auch dort Schreibzugriffe.
Genau so ist es.
Eine Datenbank verhindert keine Schreibzugriffe und schont die SD-Karte nicht automatisch. Der Vorteil liegt eher darin, dass sie für viele strukturierte Daten, Abfragen, Historien und Auswertungen gemacht ist.
Der Unterschied ist also nicht: Datenbank schreibt nicht – Persistent Context schreibt.
Sondern:
Persistent Context eignet sich für wenige wichtige Zustände, etwa Zähler, Grenzwerte oder letzte Schaltzustände.
Eine Datenbank eignet sich für viele historische Messwerte, Diagramme, Auswertungen oder Exporte.
Das Schaubild zeigt, dass der Persistent Context für wenige wichtige Zustände geeignet ist, während eine Datenbank besser zu vielen historischen Messwerten, Diagrammen und Auswertungen passt.
Wenn sehr viele Daten geschrieben werden, sollte man zusätzlich über eine High-Endurance-SD-Karte, eine SSD, größere Speicherintervalle oder das Speichern nur bei Änderungen nachdenken.
Merksatz:
Entscheidend ist nicht nur, ob Context oder Datenbank genutzt wird, sondern auch, wie oft geschrieben wird und wo die Daten gespeichert werden.
Alternative: Raspberry Pi mit SSD oder NVMe betreiben
Eine weitere Möglichkeit, die SD-Karte zu entlasten, ist der Betrieb des Raspberry Pi mit einer SSD oder NVMe-Festplatte.
Dafür gibt es spezielle Erweiterungsplatinen, sogenannte NVMe HATs. Diese werden auf den Raspberry Pi aufgesteckt und ermöglichen den Anschluss einer NVMe-SSD.
Ein NVMe HAT ermöglicht den Anschluss einer SSD am Raspberry Pi und kann helfen, die microSD-Karte bei vielen Schreibzugriffen zu entlasten.
Der Vorteil: Die Daten werden dann nicht mehr auf die microSD-Karte geschrieben, sondern auf ein Speichermedium, das deutlich besser für häufige Schreibzugriffe geeignet ist.
Das ist besonders interessant, wenn auf dem Raspberry Pi mehrere Dienste laufen, zum Beispiel:
- Node-RED - MQTT-Broker - Home Assistant - SQLite oder PostgreSQL - InfluxDB - Grafana - Docker-Container
Gerade bei Datenbanken oder vielen Log- und Messwerten kann eine SSD die bessere Wahl sein.
Für kleine Projekte reicht eine gute microSD-Karte oft aus. Wenn aber dauerhaft viele Daten geschrieben werden, ist ein Raspberry Pi mit SSD oder NVMe-Speicher deutlich robuster.
Damit verschiebt man die Grenze weg von der SD-Karte und schafft eine stabilere Grundlage für Smarthome- und IoT-Projekte.
Wo bekommt man ein NVMe HAT und was kostet es?
NVMe HATs für den Raspberry Pi bekommt man bei verschiedenen Händlern. Dazu gehören zum Beispiel offizielle Raspberry-Pi-Händler, Elektronikshops, Amazon, eBay oder AliExpress.
Die Preise hängen stark vom Modell und vom Funktionsumfang ab. Ein einfaches NVMe HAT ist deutlich günstiger als ein Gehäuse mit integrierter NVMe-Erweiterung, Kühlung oder zusätzlichen Funktionen.
ShopPreishttps://amazon.deab 12 €*https://ebay.deab 18 €*https://www.pollin.de15,49 €
Hinweis von mir: Die mit einem Sternchen (*) markierten Links sind Affiliate-Links. Wenn du über diese Links einkaufst, erhalte ich eine kleine Provision, die dazu beiträgt, diesen Blog zu unterstützen. Der Preis für dich bleibt dabei unverändert. Vielen Dank für deine Unterstützung!
Node-RED SD-Karte entlasten: Speicheroptionen im Vergleich
Wenn viele Schreibzugriffe entstehen, lohnt sich ein Blick auf das verwendete Speichermedium. Denn egal ob Persistent Context, Datenbank oder Logdatei: Am Ende werden die Daten irgendwo gespeichert.
Beim Raspberry Pi gibt es dafür mehrere Möglichkeiten.
SpeicherlösungVorteileNachteileGeeignet fürmicroSD-Kartegünstig, einfach, direkt nutzbar, keine Zusatzhardware nötigbegrenzte Schreibzyklen, Qualität stark unterschiedlich, bei vielen Schreibzugriffen nicht idealkleine Node-RED-Projekte, einfache Automationen, wenige SchreibvorgängeUSB-Stickgünstig, schnell angeschlossen, entlastet die microSD-Karteebenfalls Flash-Speicher, Qualität stark unterschiedlich, nicht ideal für dauerhafte hohe Schreiblasteinfache Auslagerung von Logs, Backups oder kleineren Datenexterne USB-SSDrobuster als USB-Stick, besser für viele Schreibzugriffe, gute Geschwindigkeitetwas teurer, benötigt mehr Platz, ggf. mehr StromDatenbanken, Logs, Home Assistant, Docker, dauerhafte Smarthome-ProjekteNVMe HAT mit SSDsehr schnell, kompakt, saubere Lösung für den Raspberry Pi, gut für Dauerbetriebteurer, Zusatzhardware nötig, Kompatibilität zum Raspberry-Pi-Modell beachtenMini-Server, viele Dienste, viele Schreibzugriffe, Datenbanken und Smarthome-Setups
Für kleine Projekte reicht eine gute oder sogenannte High-Endurance-microSD-Karte oft völlig aus.
Wenn du nur einzelne Werte wie Zählerstände, Konfigurationen oder letzte Zustände speicherst, ist das normalerweise unkritisch.
Wenn aber regelmäßig viele Daten geschrieben werden, zum Beispiel durch Datenbanken, Logs, Home Assistant, InfluxDB oder mehrere Docker-Container, ist eine externe SSD oder ein NVMe HAT mit SSD die robustere Lösung.
Ein USB-Stick kann eine günstige Zwischenlösung sein, sollte aber nicht mit einer SSD verwechselt werden. Auch USB-Sticks nutzen Flash-Speicher und sind qualitativ sehr unterschiedlich.
Als einfache Orientierung:
Wenig Schreiblast: microSD-Karte Günstige Auslagerung: USB-Stick Viele Schreibzugriffe: externe USB-SSD Kompakter Dauerbetrieb: NVMe HAT mit SSD
Node-RED Context Stores praktisch nutzen: RAM, SD-Karte und USB-Stick
Nachdem wir uns die verschiedenen Speicheroptionen angeschaut haben, wird es nun etwas praktischer.
Der Flow empfängt einen Sensorwert per MQTT und speichert ihn gezielt im RAM, auf der SD-Karte oder auf einem USB-Stick. Flow JSON für MQTT-Sensorwert und Context Stores anzeigen , "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "sensor/wohnzimmer/temperatur", "payload": "", "payloadType": "date", "x": 180, "y": 80, "wires": ] }, { "id": "a8d74225924844ad", "type": "function", "z": "b9a1e07bb447b3d1", "name": "Zufallswert 10 bis 30 °C", "func": "let zufallswert = Math.random() * (30 - 10) + 10;nzufallswert = Number(zufallswert.toFixed(2));nnmsg.payload = zufallswert;nmsg.topic = "sensor/wohnzimmer/temperatur";nnreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": , "x": 450, "y": 80, "wires": ] }, { "id": "c6b41cbdf945d245", "type": "mqtt out", "z": "b9a1e07bb447b3d1", "name": "MQTT Sensorwert senden", "topic": "", "qos": "", "retain": "", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "ec3f5f670a624e22", "x": 730, "y": 80, "wires": }, { "id": "f75bfa1a756fa168", "type": "mqtt in", "z": "b9a1e07bb447b3d1", "name": "MQTT Sensorwert empfangen", "topic": "sensor/wohnzimmer/temperatur", "qos": "0", "datatype": "auto-detect", "broker": "ec3f5f670a624e22", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 190, "y": 180, "wires": ] }, { "id": "d49a39e499a62e39", "type": "function", "z": "b9a1e07bb447b3d1", "name": "Sensorwert aufbereiten", "func": "let sensorwert = Number(msg.payload);nnlet zeitstempel = new Date().toLocaleString("de-DE", {n timeZone: "Europe/Berlin",n day: "2-digit",n month: "2-digit",n year: "numeric",n hour: "2-digit",n minute: "2-digit",n second: "2-digit"n});nnmsg.payload = {n sensor: "Wohnzimmer",n typ: "Temperatur",n wert: sensorwert,n einheit: "°C",n zeitstempel: zeitstempeln};nnreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": , "x": 470, "y": 180, "wires": ] }, { "id": "d127437b75dc028f", "type": "function", "z": "b9a1e07bb447b3d1", "name": "Speichern im RAM", "func": "flow.set("temperaturAktuell", msg.payload, "memoryOnly");nnmsg.payload = {n speicher: "memoryOnly / RAM",n hinweis: "Wert wird nur im Arbeitsspeicher gespeichert und ist nach Neustart weg.",n daten: msg.payloadn};nnreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": , "x": 760, "y": 140, "wires": ] }, { "id": "aa4f11d9d23c2966", "type": "function", "z": "b9a1e07bb447b3d1", "name": "Speichern auf SD-Karte", "func": "let letzterWert = flow.get("temperaturLetzteSD", "sdcard");nlet geaendert = !letzterWert || letzterWert.wert !== msg.payload.wert;nnif (geaendert) {n flow.set("temperaturLetzteSD", msg.payload, "sdcard");n}nnmsg.payload = {n speicher: "sdcard / localfilesystem",n hinweis: "Wird persistent auf der SD-Karte gespeichert. Durch flushInterval 180 aber nicht sofort bei jeder Änderung auf die Karte geschrieben.",n gespeichert: geaendert,n vorherigerWert: letzterWert ? letzterWert.wert : null,n daten: msg.payloadn};nnreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": , "x": 780, "y": 200, "wires": ] }, { "id": "cefc0e1283c6127a", "type": "function", "z": "b9a1e07bb447b3d1", "name": "Speichern auf USB-Stick", "func": "flow.set("temperaturLetzteUSB", msg.payload, "usbstick");nnmsg.payload = {n speicher: "usbstick / localfilesystem",n hinweis: "Wird persistent auf dem USB-Stick gespeichert.










