Progettazione dell'architettura API per letture veloci di file di testo con 150 milioni di etichette univoche
Supponi un file di testo con 150 milioni di record unici.
Ogni record ha due colonne: (1) stringa e (2) intero.
La stringa è un'etichetta univoca e il numero intero è il valore dell'etichetta.
L'unica query restituirà il valore intero per una data etichetta.
Stiamo esplorando più architetture per esporre questo file di testo come un'API.
Questo file di testo viene rigenerato ogni 72 ore. ~ 90% dei dati rimane lo stesso durante la rigenerazione, ma questa rigenerazione è controllata da una terza parte. Riceviamo semplicemente un nuovo file di testo ogni 72 ore.
Puntiamo a prestazioni di query di 100 ms - 500 ms per lettura.
Architettura 1
- Memorizza il file di testo su disco. Interroga il file di testo. Cache query in memoria.
- Pro: implementazione semplice. Facile aggiornare i dati.
- Contro: Inelegant. Le query di lettura non memorizzate nella cache sono lente.
Architettura 2
- Analizza il file di testo in un database tradizionale / NoSQL, con ogni riga trattata come un record / documento del database. Esegui query sul database.
- Pro: sembra un'architettura standard.
- Contro: l'aggiornamento di 150 milioni di record di database è lento e sembra uno spreco, soprattutto perché circa il 90% dei record rimane lo stesso.
Architettura 3
- Utilizzare Redis o il database in memoria per archiviare il file di testo da 5 GB. Esegui query sul database in memoria.
- Pro: query veloci. Facile aggiornare i dati.
- Contro: costoso.
Architettura 4
- Utilizza ElasticSearch per eseguire query sui record.
- Pro: ElasticSearch è progettato per la ricerca.
- Contro: ES può essere eccessivo per domande così semplici.
Domande:
Dovremmo considerare altre architetture o ci sono pro / contro che abbiamo trascurato?
Questa sfida ingegneristica sembra comune: qual è l'architettura più "standard" per bilanciare costi / prestazioni quando si cerca di produrre letture veloci rispetto a un archivio dati di 150 milioni di record che cambiano?
Risposte
In generale, questo sembra un classico caso per un flusso ETL: ottieni il nuovo file, estrai i dati, trasformalo nel tuo formato e carica nel tuo DB. Alcune note:
La cosa importante da ricordare è che il caricamento e l'interrogazione riguardano operazioni diverse e completamente indipendenti. Una domanda è "come faccio a caricare in modo efficiente un file di record di 150 m giornalieri in un archivio dati quando il 90% dei record sono duplicati", e l'altra è "come posso interrogare in modo efficiente un archivio chiave / valore di 150 m". Rispondi a queste due domande separatamente, perché sono indipendenti.
Per la tua prima domanda, ti preoccupi che caricare il 90% di record identici sia uno spreco. Hai misurato il tempo necessario? La lettura di 150 milioni di record da un file di testo dovrebbe richiedere pochi secondi e un buon archivio chiave / valore dovrebbe essere in grado di ottimizzare le operazioni di AGGIORNAMENTO ridondanti. In alternativa, diff il nuovo file con quello precedente per creare un elenco di modifiche effettive come parte del flusso ETL, quindi procedi al caricamento. Definisci le metriche per questa soluzione (tempo totale di lettura, diff, caricamento, interruzione dell'operazione di query durante il caricamento, ecc.) In modo da poter valutare la tua soluzione.
Per la domanda n. 2, evitare di implementare soluzioni personalizzate quando esistono opzioni standard. ElasticSearch potrebbe essere eccessivo perché stai solo archiviando numeri interi con chiave, ma ci sono molti archivi chiave / valore là fuori che ti daranno buone prestazioni per le letture, tra cui la memorizzazione nella cache supportata da disco, la memorizzazione nella cache MRU o diverse strategie di memorizzazione nella cache a seconda del tuo utilizzo, forse la summenzionata operazione UPDATE non operativa e altro ancora. Ancora una volta, come nella domanda n. 1, definisci le metriche per il successo. Hai detto "caricare 5 GB nella RAM è costoso. È? Quanta RAM ha il tuo server? Prendi in considerazione la memorizzazione nella cache delle query comuni. È necessario? Quanto sono veloci le letture non nella cache? Misura! Hai bisogno di una strategia di memorizzazione nella cache personalizzata come il precaching dei record correlati ? Esamina il tuo modello di utilizzo.
Non posso dirti quale sia l'approccio migliore. Ci sono troppe variabili che solo tu conosci: il tuo budget e il tuo modello di utilizzo, i piani futuri per il sistema e il potenziale di estensibilità, relazione con l'origine dati di terze parti (ad esempio possono essere convinti a generare solo differenze o aggiungere timestamp / tag di versione per i record, ecc.). Tutto quello che posso fare è suggerire modelli fondamentali: separare i flussi di importazione dai flussi di query, utilizzare strumenti collaudati e, soprattutto, misurare, misurare, misurare.
Puoi considerare l'approccio adottato dal cdb di DJBernstein , che è:
cdb è un pacchetto veloce, affidabile e semplice per creare e leggere database costanti. La sua struttura del database offre diverse funzionalità:
Ricerche rapide: una ricerca riuscita in un database di grandi dimensioni richiede normalmente solo due accessi al disco. Una ricerca non riuscita ne richiede solo una.
Basso overhead: un database utilizza 2048 byte, più 24 byte per record, più lo spazio per chiavi e dati.
Nessun limite casuale: cdb può gestire qualsiasi database fino a 4 gigabyte. Non ci sono altre restrizioni; i record non devono nemmeno entrare nella memoria. I database sono archiviati in un formato indipendente dalla macchina.
Sostituzione rapida del database atomico: cdbmake può riscrivere un intero database due ordini di grandezza più velocemente di altri pacchetti di hashing.
Veloce dump del database: cdbdump stampa il contenuto di un database in un formato compatibile con cdbmake.
cdb è progettato per essere utilizzato in applicazioni mission-critical come la posta elettronica. La sostituzione del database è sicura contro i crash del sistema. I lettori non devono fare una pausa durante una riscrittura.
Probabilmente vorrai un'implementazione più moderna, che non abbia il limite di 4GiB, come questa .