Protocolli e dati

Memorizzazione dei dati IoT: architettura e opzioni

Confronta database IoT, storico locale, code di reinvio e archivi cloud. Dimensiona lo spazio e verifica conservazione e ripristino.

Un grafico locale, una coda di letture in attesa di una piattaforma cloud e un archivio di sette anni sono tre depositi diversi. Rispondono a domande diverse, hanno costi diversi per lettura e si guastano in modi diversi. Dimensiona, conserva e verifica ognuno separatamente.

Per misure con marca temporale, parti da un database di serie storiche. Usa un database relazionale quando le letture devono collegarsi ai record aziendali, uno documentale quando la struttura dei payload varia e lo storage di oggetti per file e insiemi di dati analitici. Ognuno può funzionare sul sito o centralmente.

Storico, consegna e ripristino

Parti da un contratto per i dati dei sensori: identità della sorgente, valore, unità, ora di misura, ora di ricezione, qualità e provenienza dell'elaborazione. Lo storage deve conservare abbastanza informazioni da interpretare una lettura anche dopo la sostituzione del dispositivo o la modifica della configurazione.

ArchivioCompitoImplementazione tipicaCosa elimina un record
Storico interrogabileRicerche per intervallo temporale, grafici e indaginiDatabase di serie storiche o tabella SQL partizionataCriterio di conservazione basato sull'età
Coda di consegnaConservare e ritentare le letture non confermate da una destinazioneTabella SQLite o coda del broker, un gruppo di righe per destinazioneConferma della destinazione
Archivio di risorse e configurazioneIdentità dei dispositivi, mappatura dei canali, scalatura e unitàDatabase relazionale o file di configurazione versionatiModifica intenzionale conservata nella cronologia
Archivio a lungo termineConservare record selezionati per anniFile Parquet o CSV nello storage di oggettiRegola del ciclo di vita o periodo legale di conservazione
BackupRipristinare un sistema dopo perdita o danneggiamentoSnapshot copiati fuori dall'hostPolitica di conservazione dei backup

L'ultima colonna spiega molte sorprese. Lo storico può scadere letture mai ricevute dalla destinazione. Una coda può essere vuota perché la consegna è terminata, perché non sono arrivati dati o perché un filtro ha escluso il punto. Un grafico può mostrare valori attuali mentre a una piattaforma cloud manca una settimana. Verifica ogni esito separatamente.

Confrontare database e storage per l'IoT

Database di serie storiche

Usa un database di serie storiche se gran parte del carico consiste in letture numeriche con marca temporale, aggregazioni per intervallo e ricerche degli andamenti. Prima di sceglierlo, prova dati in ritardo, gestione dei duplicati, cardinalità delle etichette, limiti delle query e impostazioni di conservazione nell'edizione che userai.

VictoriaMetrics a nodo singolo imposta la conservazione basata sull'età con -retentionPeriod, predefinita a un mese. La sua guida al dimensionamento indica circa 1 byte o meno per campione su disco dopo la compressione, che peggiora se le serie cambiano spesso. Calcola il valore reale da vm_data_size_bytes e dal numero di righe memorizzate. Mantieni libero almeno il 20% della directory dati: VictoriaMetrics usa lo spazio per unire parti di dati e le query rallentano quando non riesce a farlo.

La cardinalità è il numero di serie distinte. Nei sistemi IoT aumenta quando un'etichetta cambia spesso, per esempio una versione firmware o un valore di intensità del segnale registrato come etichetta. La frequenza dei punti resta uguale, ma l'indice cresce con ogni nuova combinazione. Conserva gli attributi variabili nell'archivio delle risorse, non nelle etichette delle serie.

Database relazionali

Usa un database relazionale quando le query collegano le letture ad apparecchiature, lotti di produzione, periodi tariffari o record di assistenza, e il team usa già SQL in produzione.

Il partizionamento PostgreSQL divide una tabella grande per intervallo temporale. Eliminare o separare una vecchia partizione è molto più rapido di un DELETE massivo ed evita il lavoro di VACUUM che ne consegue. L'estensione TimescaleDB automatizza il processo: divide una hypertable in blocchi temporali e una politica di conservazione elimina interi blocchi più vecchi dell'intervallo definito. Tale politica non si applica agli aggregati continui costruiti dalla hypertable, quindi le medie orarie possono sopravvivere alle letture grezze. Prova dimensione degli indici e piani delle query con almeno un mese di dati rappresentativi.

Database documentali

Gli archivi documentali sono adatti a record di dispositivi e payload di eventi la cui struttura varia. Le raccolte di serie storiche MongoDB memorizzano le misure in ordine temporale in formato colonnare, raggruppate da un metaField che identifica la serie. Gli aggiornamenti sono limitati: il manuale limita le espressioni di selezione per l'aggiornamento al metaField. Pianifica come conservare valori corretti prima di basarti su aggiornamenti sul posto. Una struttura documentale flessibile richiede comunque unità, identità e significato delle marche temporali ben definiti.

Storage di oggetti e archivi analitici

Lo storage di oggetti contiene file di misure esportate, evidenze di verifica e insiemi di dati analitici. Il motore delle query è un componente separato. Athena legge formati colonnari come Parquet e ORC e solo le colonne necessarie alla query.

Due regole della guida di ottimizzazione Athena contano soprattutto per gli archivi dei sensori. Primo: partiziona per la query più comune; se gli analisti cercano per giorno, non partizionare per ora. Ordina invece i record per marca temporale dentro ogni file. Secondo: evita molti file piccoli. Il gruppo di righe Parquet predefinito è di 128 MB e, per file piccoli, il sovraccarico del formato colonnare supera il vantaggio. Un sito con 1.440.000 letture al giorno produce un file Parquet giornaliero molto più piccolo. Partiziona per sito e mese, oppure riunisci più siti in un file giornaliero.

Scrivi accanto ai file una versione dello schema e un contratto dei dati. Una directory di CSV costa poco da scrivere ma molto da interpretare anni dopo.

Controlla la classe di storage. S3 Glacier Flexible Retrieval e Glacier Deep Archive richiedono una richiesta di ripristino prima di leggere un oggetto; Glacier Instant Retrieval no. Nel modello dei costi includi recupero, richieste, query e trasferimento, oltre al prezzo per gigabyte conservato.

Storage sul sito e centrale

Un sito autonomo può funzionare con il solo storico locale. Aggiungi un archivio centrale quando servono confronti fra siti, rendicontazione condivisa o una conservazione più lunga di quella sostenibile sul sito. Un'architettura ibrida offre entrambe le cose, ma aggiunge una seconda copia da riconciliare, una coda da controllare e una seconda politica di conservazione.

RequisitoArchivioProva
Indagare eventi recenti del sito durante un'interruzione WANStorico locale interrogabileScollega la WAN. Recupera l'intervallo richiesto come utente locale autorizzato.
Confrontare molti sitiArchivio analitico centrale con identità del sitoConfronta unità, scostamenti degli orologi, intervalli e mappature delle risorse di due siti.
Superare un'interruzione del collegamentoCoda di consegna con disco locale sufficienteBlocca la destinazione. Misura la crescita della coda e poi il tempo di svuotamento dopo il ripristino.
Conservare evidenze per anniArchivio grezzo o aggregato con percorso di esportazioneConsegna a qualcuno esterno al progetto un file vecchio di un anno e chiedigli di interpretarlo.
Ripristinare un Gateway o server guastoBackup fuori dall'host e procedura di ripristinoRipristina su hardware di riserva. Registra il tempo impiegato e la lacuna nei dati.

I livelli hot, warm e cold descrivono frequenza di lettura e velocità richiesta per recuperare i dati. Un solo database con due politiche di conservazione può fornire due livelli. Ogni livello aggiuntivo richiede un responsabile, una verifica del trasferimento e un'azione definita in caso di errore.

Come Edge conserva lo storico e reinvia i dati

EpiSensor Edge conserva uno storico locale interrogabile in VictoriaMetrics e i dati in attesa di consegna in una coda SQLite separata. La modalità dello storico locale registra tutte le letture valide, soltanto quelle abilitate all'esportazione oppure nessuna. La conservazione è impostata in giorni, con valore predefinito di 30. VictoriaMetrics legge questo valore all'avvio: una modifica si applica dopo il riavvio di Edge. Attivare lo storico inizia la registrazione da quel momento; non ricostruisce letture mai conservate.

La consegna normale inizia in memoria. Edge tiene ogni lettura in RAM fino a quando la destinazione segnala il successo, poi la elimina senza scriverla su disco. Scrive la lettura nella coda soltanto quando la consegna fallisce o la destinazione risulta già offline. Lo storico locale funziona in modo analogo: Edge raccoglie letture in memoria per un massimo di 250 ms, scrive il lotto in VictoriaMetrics e usa la coda soltanto se tale scrittura fallisce. Così limita le scritture sulla memoria eMMC del Gateway. Un'interruzione dell'alimentazione o l'arresto del processo prima della persistenza può perdere le letture ancora in transito.

Chi invia letture a Edge tramite HTTP può distinguere i casi. Una risposta 202 indica che Edge ha scritto il lavoro su disco per reinviarlo. Una 200 indica che ha accettato le letture in memoria. Una 503 o 507 indica che ha rifiutato il lavoro da conservare su disco perché lo storage non è disponibile o perché si è attivata la soglia di spazio libero minimo. Il mittente deve conservare e reinviare i dati.

Edge considera completa una consegna immediata in un punto che dipende dal trasporto:

  • MQTT: completamento della pubblicazione QoS 1.
  • Esportazione HTTP: stato di successo configurato, dopo aver ricevuto l'intero corpo della risposta.
  • Esportazione su file: scrittura nella coda dei file da inviare.
  • Modbus Server: completamento di ogni scrittura dei registri del messaggio.

Il reinvio gestito da Edge si applica alle destinazioni che lo dichiarano, per esempio EpiSensor Core. Altri flussi di integrazione hanno una propria politica di nuovi tentativi o consegnano senza garanzia. Conferma quale caso vale per ogni integrazione durante la messa in servizio.

La coda segue regole diverse dallo storico. Nell'implementazione attuale, i dati ancora in attesa non scadono per età: eliminarli significherebbe perdere dati non consegnati. Un'interruzione lunga fa crescere la coda finché la consegna non riprende o la soglia di spazio libero minimo rifiuta nuovo lavoro. Per impostazione predefinita, la soglia si attiva quando lo spazio libero scende al 10% del filesystem, con limite massimo di 1 GiB, oppure a 256 MiB. Ogni destinazione ha le proprie righe: una destinazione lenta non blocca né conferma i dati di un'altra. Le letture reinviate mantengono le marche temporali originali. Il reinvio va solo alla destinazione che non aveva ricevuto i dati e non esegue nuovamente dispositivi calcolati o automazione, che hanno già elaborato la lettura originale. Le scritture della coda usano SQLite synchronous=FULL, quindi una riga registrata con commit sopravvive a un'interruzione dell'alimentazione.

Dimensionare lo storico e la capacità durante un'interruzione

Conta i canali che inviano dati, non i dispositivi. Un contatore può inviare più grandezze con intervalli diversi. Per un intervallo fisso:

Punti al giorno = canali che inviano dati × 86.400 ÷ intervallo di invio in secondi

Per esempio, 1.000 canali che inviano una volta al minuto producono 1.440.000 punti al giorno, o 43.200.000 punti in 30 giorni, prima dei filtri. Con un invio al secondo la frequenza è 60 volte maggiore. Aggiungi separatamente raffiche di eventi e valori calcolati.

Storico. Con la stima VictoriaMetrics di circa 1 byte per punto, i 30 giorni dell'esempio richiedono circa 43 MB di campioni, oltre all'indice e al margine del 20% di spazio libero. Un anno comprende circa 526 milioni di punti, o circa 0,5 GB. In un benchmark sintetico EpiSensor, 200.000 letture regolari occupavano 35 KB in VictoriaMetrics e 36 MB in una normale tabella SQLite, un rapporto di circa 1.000 a 1. I valori variabili sul campo si comprimono meno di quelli sintetici: misura con i dati del sito.

Coda. Su un Gateway di campo, ogni lettura in coda occupava circa 550 byte in SQLite, indici compresi, per ogni destinazione. Gli stessi 1.000 canali durante un'interruzione di 72 ore mettono in coda 4.320.000 letture: circa 2,4 GB per una destinazione o 4,8 GB per due. Su uno ZGW-20 con eMMC standard da 16 GB è una parte consistente del disco; è la coda, non lo storico, a determinare l'interruzione più lunga che il Gateway può superare. L'opzione di calcolo con eMMC da 64 GB o SSD facoltativo da 128 GB la estende. Per stimare la durata coperta:

Ore di interruzione coperte = spazio libero per la coda ÷ (byte per lettura in coda × letture all'ora × destinazioni)

Dallo «spazio libero» escludi soglia minima di spazio, log, aggiornamenti e spazio temporaneo per i backup.

Nel progetto pilota, misura quattro valori:

  1. Crescita dello storico dopo la manutenzione del database: punti conservati, numero di serie, dimensione dell'indice e uso del disco.
  2. Crescita della coda per ogni destinazione durante un'interruzione controllata, compreso il log write-ahead di SQLite.
  3. Velocità di recupero: consegne confermate al secondo mentre continuano ad arrivare nuove letture.
  4. Tutto il resto sul disco: sistema operativo, log, aggiornamenti e spazio temporaneo dei backup.

Il tempo di svuotamento conta quanto la capacità. Se una coda contiene 120.000 record, arrivano 100 nuovi record al secondo e la destinazione ne conferma 300 al secondo, il tasso netto di svuotamento è 200 record al secondo. La coda si svuota in almeno 600 secondi, cioè 10 minuti. Nuovi tentativi e limitazioni della velocità allungano il tempo. Se il tasso di conferma non supera quello di arrivo, la coda non si svuota mai.

Cosa dimostra una conferma

Collegamento, invio, conferma e osservazione memorizzata sono eventi distinti. Definisci quale conta come completamento a ogni passaggio.

EvidenzaCosa dimostraVerifica successiva
Richiesta in ingresso accettataIl servizio ricevente ha accettato il lavoro secondo il proprio contratto APISe il contratto indica memoria, coda durevole o commit nel database
MQTT QoS 1 PUBACK con codice di successoIl broker ha assunto la responsabilità del messaggioElaborazione degli abbonati e lettura memorizzata nella piattaforma destinataria
Risposta HTTP riuscitaÈ soddisfatta la condizione di successo documentata dell'endpointCorpo della risposta, errori parziali ed eventuale esito dell'importazione asincrona
Trasferimento del file completatoUn file ha raggiunto la destinazione di trasferimentoEsito del parser e corretta mappatura dei record nell'applicazione
Una query dello storico restituisce una letturaL'archivio selezionato contiene l'osservazioneIdentità, marca temporale, unità, valore e completezza attesa

Secondo lo standard MQTT 5.0, un ricevente QoS 1 invia PUBACK dopo aver assunto la responsabilità del messaggio (sezione 4.3.2). Non dice nulla sugli abbonati o sui database a valle. Leggi il codice di motivo del PUBACK (sezione 3.4.2.1). 0x00 significa Success. Anche 0x10 No matching subscribers è un codice di successo: il broker ha accettato un messaggio che nessuno riceverà. I codici 0x80 e superiori indicano errori, per esempio 0x87 Not authorized e 0x97 Quota exceeded. La guida alla messa in servizio di MQTTS tratta trasporto e identità.

I nuovi tentativi creano duplicati quando il destinatario registra un lotto ma il mittente non ne registra il successo. Dai a ogni osservazione un'identità stabile e rendi idempotente l'acquisizione. Edge identifica le righe della coda con destinazione, ID di esportazione, ID del sensore, marca temporale e valore. Un errore segnalato più volte non crea una seconda riga, ma un valore corretto con la stessa marca temporale è un nuovo record. Anche il destinatario deve avere una regola propria. Un upsert su sorgente, canale e marca temporale conserva l'ultima correzione; un inserimento che ignora i conflitti sulla stessa chiave conserva il primo valore. Scegli deliberatamente e tratta allo stesso modo arrivi tardivi e campioni fuori ordine.

Il reinvio dipende dalla marca temporale di ogni lettura. Se l'orologio è errato quando la lettura viene marcata, per esempio dopo un'interruzione dell'alimentazione e prima della sincronizzazione, il reinvio consegna fedelmente l'ora sbagliata e il destinatario archivia la lettura nell'intervallo errato. Conserva l'ora di ricezione accanto a quella di misura per rendere visibile lo scostamento. Non cambiare mai la marca temporale originale di una misura vecchia per far apparire attuale un reinvio.

Conservazione, durabilità e backup

Conservazione indica per quanto tempo mantenere ogni classe di record. Definisci separatamente letture grezze, aggregati, eventi, configurazioni, dati in attesa di consegna e backup. Ridurre il periodo può eliminare evidenze necessarie; aumentarlo non recupera dati già scaduti.

Scegli gli aggregati in base alla decisione che devono sostenere. Una media d'intervallo può nascondere un picco breve. Un registro energetico cumulativo richiede gestione di azzeramento e ritorno a zero per superamento del limite: sommarne le letture non dà il consumo. Conserva con ogni riepilogo unità, confini dell'intervallo, copertura dei campioni e versione della trasformazione.

Durabilità indica quali scritture confermate sopravvivono a un guasto definito e dipende dall'intero percorso di scrittura. La documentazione SQLite su synchronous ne mostra il motivo. In modalità WAL con synchronous=FULL, SQLite sincronizza il log write-ahead dopo ogni commit e una transazione confermata sopravvive a un'interruzione dell'alimentazione. In modalità WAL con synchronous=NORMAL, il database rimane coerente ma una transazione confermata appena prima della perdita di alimentazione può essere annullata dopo il riavvio.

Backup e ripristino servono a recuperare da danni, cancellazioni o perdite. Una seconda copia sullo stesso disco non sopravvive al guasto del disco, e la replica copia le modifiche indesiderate con la stessa rapidità di quelle desiderate. Concorda un recovery point objective (massima lacuna accettabile nei dati recuperati) e un recovery time objective (tempo massimo accettabile per ripristinare il servizio).

Esegui il backup di un archivio attivo con il suo meccanismo di consistenza. vmbackup copia da snapshot istantanei, quindi VictoriaMetrics non deve fermarsi. Un backup di VictoriaMetrics a nodo singolo non si ripristina su un cluster, né viceversa. Mantieni le copie in un dominio di guasto separato, proteggi le credenziali e prova il ripristino su una destinazione isolata.

Su Edge verifica cosa ripristina l'ambito di backup scelto nella versione installata: storico della telemetria, servizi ausiliari, stato radio e configurazione dell'host non sono tutti inclusi in ogni ambito. Dimostralo con una prova di ripristino. Un caricamento riuscito dimostra soltanto che esiste il file di backup.

Mettere in servizio il percorso di memorizzazione

Prima di estendere oltre il progetto pilota, assegna un responsabile all'architettura di memorizzazione e completa queste verifiche:

  1. Dimostra acquisizione e storico. Segui una sorgente, un valore, un'unità e una marca temporale noti fino alle query locali e centrali richieste.
  2. Interrompi il percorso di consegna. Blocca una destinazione. Registra crescita della coda, lettura in attesa più vecchia, uso del disco e indicazione del guasto visibile agli operatori.
  3. Ripristina il collegamento. Verifica che la coda si svuoti mentre continuano i dati attuali. Poi confronta i record della piattaforma ricevente relativi all'interruzione con la sorgente.
  4. Prova duplicati e dati tardivi. Verifica che il reinvio non conti due volte le letture né sostituisca l'ora di misura con quella di arrivo.
  5. Prova il ripristino. Usa un sistema di prova. Ferma il servizio, poi togli alimentazione mentre arrivano letture. Ripristina un backup. Registra lacuna nei dati e tempo necessario.
  6. Assegna la responsabilità continuativa. Indica chi controlla letture mancanti, età della coda, capacità del disco, guasti dei backup, accesso, conservazione ed eliminazione.

Per una distribuzione EpiSensor, parti dalle funzioni locali di Edge e poi dalle integrazioni con le piattaforme. Se destinazione o requisiti di conservazione sono ancora da definire, parla del progetto indicando numero di canali, intervalli di invio, finestra di consultazione richiesta, durata prevista delle interruzioni e obiettivi di recupero.

Domande frequenti

Qual è il database migliore per i dati IoT?

Non esiste un database migliore per tutti i casi. Le serie storiche sono adatte a misure con marca temporale e query per intervallo. I database relazionali sono utili quando le letture si collegano a record aziendali; TimescaleDB aggiunge il partizionamento temporale a PostgreSQL. Anche MongoDB offre raccolte di serie storiche. Scegli dopo aver provato query rappresentative, uso reale del disco, conservazione, tempo di ripristino e capacità del team di gestire il sistema.

I dati IoT vanno conservati nel cloud o sul sito?

Tieni sul sito storico ed elaborazione che devono restare disponibili senza WAN. Aggiungi un archivio centrale per analisi fra siti o conservazione condivisa più lunga. Un’architettura ibrida richiede una coda di consegna, gestione dei duplicati e procedura di recupero per ogni copia. Un sistema locale di monitoraggio funziona anche senza invio al cloud.

Quanto spazio richiedono i dati dei sensori IoT?

I punti giornalieri sono canali di invio × 86.400 ÷ intervallo in secondi. Mille canali ogni minuto producono 1.440.000 punti al giorno. VictoriaMetrics conserva circa 1 byte o meno per punto compresso: 30 giorni sono circa 43 MB più l’indice. Una coda SQLite può richiedere circa 550 byte per lettura e destinazione: un’interruzione di 72 ore allo stesso ritmo richiede circa 2,4 GB per destinazione. Misura entrambi sui tuoi dati.

Una coda di reinvio è uguale a un database storico?

No. Un database storico risponde a query sulle misure registrate e le elimina in base all’età. Una coda di reinvio conserva le letture non ancora confermate dalla destinazione e le elimina alla conferma. Una coda vuota non dimostra che l’applicazione ricevente abbia memorizzato ogni lettura attesa.

EpiSensor Edge evita ogni perdita di dati durante un’interruzione?

No. Edge scrive una lettura nella coda su disco quando una destinazione fallisce o risulta già offline, e la reinvia al ripristino. Le letture ancora in memoria si perdono se manca alimentazione o Edge si arresta prima che sia noto un successo o un errore. La coda smette inoltre di accettare nuovi dati quando si attiva la soglia di spazio libero minimo.