Quale database potrebbe gestire l'archiviazione di miliardi / trilioni di record?


75

Stiamo cercando di sviluppare uno strumento per acquisire e analizzare i dati del flusso di rete, di cui raccogliamo enormi quantità. Ogni giorno acquisiamo circa 1,4 miliardi di registrazioni di flusso che sarebbero così in formato json:

{
   "tcp_flags": "0",
   "src_as": "54321",
   "nexthop": "1.2.3.4",
   "unix_secs": "1352234521",
   "src_mask": "23",
   "tos": "0",
   "prot": "6",
   "input": "105",
   "doctets": "186",
   "engine_type": "0",
   "exaddr": "2.3.4.5",
   "engine_id": "2",
   "srcaddr": "9.8.7.6",
   "dst_as": "12345",
   "unix_nsecs": "752265174",
   "sysuptime": "2943529544",
   "dst_mask": "24",
   "dstport": "80",
   "last": "2943523241",
   "srcport": "52672",
   "dpkts": "4",
   "output": "111",
   "dstaddr": "6.5.4.3",
   "first": "2943517993"
}

Vorremmo essere in grado di eseguire ricerche rapide (meno di 10 secondi) sul set di dati, molto probabilmente su intervalli di tempo ristretti (intervalli di 10-30 minuti). Vogliamo anche indicizzare la maggior parte dei punti dati in modo da poter effettuare rapidamente ricerche su ciascuno di essi. Vorremmo anche avere una vista aggiornata dei dati quando vengono eseguite le ricerche. Sarebbe bello rimanere nel mondo open source, ma non siamo contrari a cercare soluzioni proprietarie per questo progetto.

L'idea è di conservare circa un mese di dati, che sarebbero circa 43,2 miliardi di record. Una stima approssimativa che ogni record conterrebbe circa 480 byte di dati, equivarrebbe a ~ 18,7 terabyte di dati in un mese, e forse tre volte rispetto agli indici. Alla fine vorremmo aumentare la capacità di questo sistema di archiviare trilioni di record.

Abbiamo valutato (in sostanza) couchbase, cassandra e mongodb per quanto possibile candidati a questo progetto, tuttavia ognuno propone le proprie sfide. Con couchbase l'indicizzazione viene eseguita a intervalli e non durante l'inserimento dei dati, quindi le viste non sono aggiornate, gli indici secondari di cassandra non sono molto efficienti nel restituire i risultati poiché in genere richiedono la scansione dell'intero cluster per risultati e mongodb sembra promettente ma sembra essere molto più difficile da ridimensionare in quanto è master / slave / sharded. Alcuni altri candidati che intendiamo valutare sono elasticsearch, mysql (non sono sicuro che ciò sia applicabile) e alcuni database relazionali orientati alle colonne. Qualsiasi suggerimento o esperienza nel mondo reale sarebbe apprezzato.


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Paul White

Risposte:


57

In un'azienda per cui lavoro ci occupiamo di una quantità simile di dati (circa 10 TB di dati ricercabili in tempo reale). Risolviamo questo con Cassandra e vorrei menzionare un paio di idee che ti permetteranno di fare una ricerca O (1) su un database multi TBs. Questo non è specifico per Cassandra db, ma puoi usarlo anche con altri db.

Teoria

  • Frammenta i tuoi dati. Non è possibile che un singolo server gestisca in modo affidabile e realistico tale volume di dati.
  • Siate pronti per guasti hardware e guasti dell'intero nodo, duplicate i dati.
  • Inizia a utilizzare molti server back-end dall'inizio.
  • Utilizzare molti server di prodotti più economici rispetto a quelli di fascia alta ad alte prestazioni.
  • Assicurarsi che i dati siano equamente distribuiti tra i frammenti.
  • Trascorri molto tempo a pianificare le tue domande. Deriva l'API dalle query e quindi progetta attentamente le tabelle. Questo è il compito più importante e prolungato.
  • In Cassandra, puoi progettare una chiave di colonna composita e ottenere l'accesso a quella chiave in O (1). Trascorri del tempo lavorando su di loro. Questo verrà utilizzato per accedere a record ricercabili anziché indice secondario.
  • Utilizza righe larghe. Sono utili per la memorizzazione di eventi con data e ora.
  • Non eseguire mai la scansione completa o qualsiasi operazione oltre O (Log N) su tale volume. Se hai bisogno di qualcosa di più di O (Log N), scarica tali operazioni sugli algoritmi Map-Reduce.

Pratica

  • Non perdere tempo a costruire immagini del sistema operativo o installare server su macchine fisiche. Utilizza provider basati su cloud per la prototipazione rapida. Ho lavorato con Amazon EC2 e lo consiglio vivamente per la sua semplicità, affidabilità e velocità di prototipazione.
  • I computer Windows tendono ad essere più lenti durante l'avvio e richiedono molte più risorse nello stato Inattivo. Prendi in considerazione l'utilizzo del sistema operativo basato su Unix. Personalmente, ho trovato il server Ubuntu come un sistema operativo affidabile, ma in più su askubuntu esiste una comunità abbastanza buona
  • Pensa al networking, i nodi dovrebbero idealmente essere vicini l'uno all'altro per consentire rapidi pettegolezzi e scambi di metadati.
  • Non andare in casi estremi: file di colonne molto ampie o famiglie di colonne eccezionalmente lunghe (tabelle). Le migliori prestazioni si ottengono nei limiti sani - se db supporta molte N righe in base alla progettazione, ciò non significa che funzioni bene.
  • La nostra ricerca richiede circa 3-5 secondi, in gran parte a causa dei nodi intermedi tra l'interfaccia utente e il database. Considera come avvicinare le richieste al database.
  • Utilizzare un bilanciamento del carico di rete. Scegli uno affermato. Usiamo HAProxy, che è semplice, ma velocissimo. Non ho mai avuto problemi con esso.
  • Preferisci la semplicità a soluzioni complesse.
  • Cerca soluzioni open source gratuite, a meno che non sia supportato dal budget delle dimensioni di una società. Una volta che vai su più server, i costi dell'infrastruttura potrebbero salire alle stelle.

Non lavoro per Amazon e non ho relazioni con i team HAProxy e Ubuntu. Questa è un'opinione personale piuttosto che qualsiasi tipo di promozione.


5
Sono abbastanza sicuro che una ricerca O (1) sia impossibile a parte casi estremamente banali / inutili.
Fitzsimmons,

2
Per favore, non offenderti, ma dillo a Google. O (1) la ricerca è possibile su scala PB con una progettazione accurata.
oleksii,

9
@oleksii I bilanci di Google da miliardi di dollari non sono un confronto ragionevole da trarre.
Mark Storey-Smith,

4
Posso collegare i 3 commenti precedenti conO(1) search <=> unbounded storage space <=> unlimited supply of cash
ypercubeᵀᴹ

3
O (1) la ricerca di un singolo record può essere effettuata con una tabella hash lineare. . Tuttavia, questo non ti dà alcuna efficienza nella ricerca sequenziale (per intervalli). Per questo è necessaria una variante di una struttura BTree, che è O (log n) per un singolo elemento.
Preoccupato di TunbridgeWells

41

Se avessi intenzione di inserirlo in SQL Server, avrei suggerito una tabella simile a:

CREATE TABLE tcp_traffic
(
    tcp_traffic_id bigint constraint PK_tcp_traffic primary key clustered IDENTITY(1,1)
    , tcp_flags smallint    /* at most 9 bits in TCP, so use SMALLINT */
    , src_as int        /* Since there are less than 2 billion A.S.'s possible, use INT */
    , netxhop bigint    /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , unix_secs bigint  
    , src_mask int      /* an assumption */
    , tos tinyint       /* values are 0-255, see RFC 791 */
    , prot tinyint      /* values are 0-255, see RFC 790 */
    , input int         /* an assumption */
    , doctets int       /* an assumption */
    , engine_type int   /* an assumption */
    , exaddr bigint     /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , engine_id int     /* an assumption */
    , srcaddr bigint    /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , dst_as int        /* Since there are less than 2 billion A.S.'s possible, use INT */
    , unix_nsecs bigint /* an assumption */
    , sysuptime bigint  /* an assumption */
    , dst_mask int      /* an assumption */
    , dstport smallint  /* ports can be in the range of 0 - 32767 */
    , [last] bigint     /* an assumption */
    , srcport smallint  /* ports can be in the range of 0 - 32767 */
    , dpkts int         /* an assumption */
    , output int        /* an assumption */
    , dstaddr bigint    /* use a big integer for the IP address instead of storing
                            it as dotted-decimal */
    , [first] bigint    /* an assumption */
);

Ciò si traduce in un fabbisogno di archiviazione totale stimato per la singola tabella, senza ulteriori indici di 5,5 TB per 43,2 record di beeellion (requisito specificato). Questo viene calcolato come 130 byte per i dati stessi, più 7 byte per riga di sovraccarico, più 96 byte per pagina di sovraccarico. SQL Server archivia i dati in pagine da 8 KB, consentendo 59 righe per pagina. Ciò equivale a 732.203.390 pagine per un singolo mese di dati.

Ad SQL Server piace scrivere su disco in blocchi di 8 pagine (64 KB), il che equivale a 472 righe per I / O fisico. Con 16.203 record di flusso generati ogni secondo, sarà necessaria una velocità I / O minima di 34 IOps, garantita ogni secondo. Sebbene questo di per sé non sia una quantità enorme, altri I / O nel sistema (SQL Server e non) non devono mai violare questa necessaria velocità di IOps. Pertanto, è necessario progettare un sistema in grado di almeno un ordine di grandezza maggiore di IOps o di 340 IOps sostenuti. Tenderei a stimare che sono necessari 2 ordini di grandezza di IOps più sostenibili per garantire il throughput.

Noterai che non sto memorizzando gli indirizzi IP nella loro forma decimale puntata. Ciò consente di risparmiare un'enorme quantità di spazio di archiviazione (7 byte per indirizzo) e rende molto più efficiente l'indicizzazione, il recupero, l'ordinamento e il confronto degli indirizzi IP. Il rovescio della medaglia qui è che è necessario convertire gli IP decimali puntati in numeri interi a 8 byte prima di memorizzarli e tornare agli IP decimali puntati per la visualizzazione. Il codice per farlo è banale, tuttavia il tuo rateo di riga aggiungerà una notevole quantità di sovraccarico di elaborazione a ciascuna riga del flusso in elaborazione - potresti voler eseguire questo processo di conversione su un computer fisicamente diverso da SQL Server.

Discutere gli indici richiesti è una questione totalmente separata poiché non sono stati elencati requisiti specifici. Il design di questa tabella memorizzerà le righe di flusso nell'ordine fisico in cui sono state ricevute da SQL Server, il tcp_traffic_idcampo è univoco per ciascun record e consente l'ordinamento delle righe in base all'ordine in cui sono state registrate (in questo caso molto probabilmente relative all'una contro l'altra al momento dell'evento di flusso).


4
Probabilmente userei binary(4)o binary(16), rispettivamente. 4 byte / riga aggiungono molta memoria se moltiplicati per 1.000.000.000.000.
Jon Seigel,

2
E i numeri di porta hanno un intervallo compreso tra 0 e 65535, quindi puoi usarli SMALLINTma deve esserci anche una routine di conversione.
ypercubeᵀᴹ

7
@MrTelly Non sono d'accordo. Farlo in SQL Server è costoso solo se hai bisogno di HA o roba di grande failover. Per un solido data store, con cui è davvero facile convivere, SQL Server è perfetto per questo. Tutti i sistemi diventano molto costosi (e complicati) se è necessario HA.
samsmith,

2
IMO, SQL Server può sicuramente archiviare i dati; Non sono ancora sicuro se sia la soluzione giusta per risolvere la parte analitica del progetto, soprattutto perché non ho abbastanza familiarità con gli altri sistemi considerati.
Jon Seigel,

3
@MrTelly Ci sono due spese: a) Memoria su disco (per 5-8 tb, a seconda dello spazio utilizzato dagli indici) b) RAM (per supportare query, memorizzazione nella cache degli indici). Per fare questo monoliticamente di solito sarebbe fatto con un grande array RAID10 o SAN. Tuttavia, si noti che lo sharding può certamente essere eseguito e potrebbe consentire di utilizzare la logica a livello di applicazione per suddividere il carico di lavoro su più server SQL. Ciò potrebbe consentire di utilizzare server economici, con 0,5-2 TB ciascuno, e forse anche utilizzare l'edizione gratuita di SQL Server. (Nota che lo sharding è un concetto generico, spesso viene eseguito a livello di app e si applica a qualsiasi metodo di persistenza)
samsmith

5

Consiglierei HBase . È possibile memorizzare tutti i dati non elaborati in una o più tabelle HBase, a seconda di ciò che è necessario interrogare. HBase è in grado di gestire set di dati di grandi dimensioni e esegue la condivisione automatica attraverso le suddivisioni della regione.

Inoltre, se si progettano bene le chiavi di riga, è possibile ottenere query O (1) estremamente veloci. Si noti che se si sta recuperando un set di dati di grandi dimensioni, sarà comunque lento poiché il recupero dei dati è un'operazione O (n).

Poiché desideri eseguire una query in ciascun campo, ti consiglio di creare una tabella univoca per ciascuno di essi. Esempio per i dati src_address, avere una tabella simile alla seguente:

1.2.3.4_timestamp1 : { data }
1.2.3.4_timestamp2 : { data }

Quindi, se si desidera eseguire una query per tutti i dati su 1.2.3.4 a partire dal 27 marzo dalle 12:00 al 27 marzo alle 00:01, è possibile eseguire una scansione dell'intervallo con le righe di inizio e fine specificate.

IMHO, il design delle chiavi di riga è la parte più critica dell'utilizzo di HBase: se lo progetti bene, sarai in grado di eseguire query rapide e archiviare grandi volumi di dati.


3

Detto questo:

... non siamo contrari a cercare soluzioni proprietarie per questo progetto

Suggerisco di prendere in considerazione il database IBM Informix + il datablade TimeSeries. Di fronte a ciò che dicono alcune persone, Informix è vivo e sta andando molto bene. L'ultima versione è stata rilasciata il mese scorso (marzo / 2013, versione 12.10).

TimeSeries è come un "plug-in" (gratuito) in grado di gestire situazioni come la tua.
E puoi usarlo in produzione con la versione gratuita del database Informix ( edizione Innovator-C ). (ovviamente, solo per valutare le parti tecniche poiché la versione gratuita ha molte risorse limitate)

Qui puoi controllare un PDF di benchmark che può essere usato come riferimento. Ecco due presentazioni con esempi più tecnici: guida dei manichini e altri suggerimenti

Non ho esperienza personale con TimeSeries , quindi non posso essere d'accordo sul fatto che sarà "la soluzione", solo un suggerimento da valutare.


2

Secondo la raccomandazione di guardare Informix TimeSeries. La letteratura IBM afferma che TimeSeries può memorizzare questo tipo di informazioni in 1/5 dello spazio ed eseguire 5 volte più velocemente delle tradizionali tabelle relazionali.

Ulteriori vantaggi sarebbero l'interfaccia della tabella virtuale in grado di far apparire i dati di TimeSeries come tabelle relazionali tradizionali per l'utente finale (semplificando lo sviluppo di applicazioni pur ottenendo i vantaggi di TimeSeries), HA semplice con nodi HDR che ora supportano i dati di TimeSeries nella versione 12.1 e integrazione dei dati TimeSeries in Informix Warehouse Accelerator che possono essere utilizzati per accelerare i report di data warehouse complicati e la capacità di prototipare una soluzione TimeSeries in Informix utilizzando le edizioni Informix Developer o Innovator-C gratuite.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.