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.















