MongoDB e set di dati che non si adattano alla RAM, non importa quanto duri


12

Questo dipende molto dal sistema, ma è quasi certo che riusciremo a superare una scogliera arbitraria e ad entrare in Real Trouble. Sono curioso di sapere che tipo di regole empiriche esistono per un buon rapporto tra RAM e spazio su disco. Stiamo pianificando il nostro prossimo giro di sistemi e dobbiamo fare alcune scelte in merito a RAM, SSD e alla quantità di ciascuno dei nuovi nodi.

Ma ora per alcuni dettagli sulle prestazioni!

Durante il normale flusso di lavoro di un singolo progetto, MongoDB viene colpito con un'altissima percentuale di scritture (70-80%). Una volta che la seconda fase della pipeline di elaborazione ha esito positivo, è estremamente alta lettura in quanto deve deduplicare i record identificati nella prima metà dell'elaborazione. Questo è il flusso di lavoro per cui è fatto "mantieni il tuo set di lavoro nella RAM", e stiamo progettando intorno a questo presupposto.

L'intero set di dati viene continuamente sottoposto a query casuali da fonti derivate dall'utente finale; sebbene la frequenza sia irregolare, la dimensione è generalmente piuttosto piccola (gruppi di 10 documenti). Poiché questo è rivolto all'utente, le risposte devono essere al di sotto della soglia "annoiata" di 3 secondi. È molto meno probabile che questo modello di accesso sia nella cache, quindi sarà molto probabile che si verifichino hit del disco.

Un flusso di lavoro di elaborazione secondario è di alta lettura delle precedenti esecuzioni di elaborazione che potrebbero avere giorni, settimane o addirittura mesi e viene eseguito di rado ma deve comunque essere zippy. Sarà possibile accedere fino al 100% dei documenti nell'esecuzione di elaborazione precedente. Sospetto che nessuna quantità di riscaldamento della cache possa essere d'aiuto.

Le dimensioni del documento finito variano ampiamente, ma la dimensione mediana è di circa 8 K.

La parte di lettura elevata della normale elaborazione del progetto suggerisce fortemente l'uso di repliche per aiutare a distribuire il traffico di lettura. Ho letto altrove che un 1:10 da RAM-GB a HD-GB è una buona regola empirica per i dischi lenti, poiché stiamo seriamente prendendo in considerazione l'uso di SSD molto più veloci, vorrei sapere se esiste una regola simile di pollice per dischi veloci.

So che stiamo usando Mongo in un modo in cui tutto ciò che la cache non sta per volare, è per questo che sto cercando dei modi per progettare un sistema in grado di sopravvivere a tale utilizzo. L' intero set di dati sarà probabilmente la maggior parte di un TB entro sei mesi e continuerà a crescere.


Una domanda difficile ben posta.
gWaldo,

Sembra che probabilmente ti imbatterai in problemi di blocco della scrittura prima di poter sintonizzarti su IO molto, onestamente. Se martelli il DB con le scritture, probabilmente tieni i blocchi di scrittura abbastanza a lungo che le query si fermeranno indipendentemente dalla velocità dell'IO sottostante. Qualcosa come Fusion IO può ridurre un po 'il blocco della scrittura, ma richiede solo un po' di tempo, non è una vera correzione.
MrKurt,

@MrKurt Parte di ciò che sto cercando di capire è quando ho bisogno di frammentare, oltre a quanto robusto possa creare i singoli nodi di replica. Le mie specifiche provvisorie includono una scheda SSD basata su PCIe.
sysadmin1138

Ah, capito. Potresti considerare lo sharding sin dall'inizio, facciamo molto sharding su server singolo. Ti consente di aggirare il blocco della scrittura e ridimensionare efficacemente le scritture sui core totali. Inoltre, è facile spostare i frammenti tra i server in un secondo momento.
MrKurt,

Risposte:


5

Questo sarà un mucchio di piccoli punti. Purtroppo non c'è una sola risposta alla tua domanda.

MongoDB consente al kernel del sistema operativo di gestire la gestione della memoria. Oltre a lanciare quanta più RAM possibile al problema, ci sono solo alcune cose che possono essere fatte per "gestire attivamente" il tuo Working Set.

L'unica cosa che puoi fare per ottimizzare le scritture è la prima query per quel record (fai una lettura), in modo che sia nella memoria di lavoro. Ciò eviterà i problemi di prestazioni associati al Global Lock a livello di processo (che dovrebbe diventare per-db in v2.2)

Non esiste una regola rigida per il rapporto RAM vs SSD, ma penso che gli IOPS grezzi degli SSD dovrebbero permetterti di andare con un rapporto molto più basso. Dall'alto della mia testa, 1: 3 è probabilmente il più basso con cui vuoi andare. Tuttavia, dati i costi più elevati e le capacità inferiori, è probabile che sia necessario mantenere tale rapporto comunque basso.

Per quanto riguarda le fasi di "Scrittura vs Lettura", sto leggendo correttamente che una volta che un record è stato scritto, viene raramente aggiornato ("modificato")? In tal caso, può essere utile ospitare due cluster; il normale cluster di scrittura e il cluster ottimizzato per la lettura di dati "obsoleti" che non sono stati modificati in [periodo di tempo X] . Sicuramente abiliterei la lettura slave su questo cluster. (Personalmente, lo farei includendo un valore modificato nella data nei documenti oggetto del tuo db.)

Se hai la possibilità di testare il carico prima di entrare in Prod, perf monitorne l'inferno. MongoDB è stato scritto partendo dal presupposto che sarebbe spesso distribuito nelle macchine virtuali (i loro sistemi di riferimento sono in EC2), quindi non abbiate paura di eseguire il partizionamento alle macchine virtuali.


Durante l'elaborazione viene creato uno stub iniziale del documento che viene quindi continuamente aggiornato da varie fasi secondarie nella prima parte dell'elaborazione. Abbiamo valutato la possibilità di eseguire alcune operazioni di riempimento manuale sulla creazione iniziale per ridurre la quantità di estensione che stiamo eseguendo, ma la nostra attuale percentuale di blocco della scrittura è felicemente bassa.
sysadmin1138

Il consiglio di leggere un disco prima di scriverlo per inserirlo nella RAM non è un buon consiglio. Dalla 2.0 (metà 2011) MongoDB ha avuto un rendimento se i dati a cui si accedeva non si trovano nella RAM, quindi si sta solo causando una lettura in più e un round trip in più sul server senza una buona ragione se lo si fa dal momento che il blocco non non si terrà comunque per quella durata.
Asya Kamsky,

13

Questo è inteso come un addendum alle altre risposte pubblicate qui, che discute molti degli elementi rilevanti da considerare qui. Tuttavia, esiste un altro fattore, spesso trascurato, quando si tratta di un utilizzo efficiente della RAM in un sistema di tipo ad accesso casuale: readahead.

Puoi controllare le impostazioni correnti di readahead (su Linux) eseguendo blockdev --report(di solito richiede i privilegi sudo / root). Questo stamperà una tabella con una riga per ogni dispositivo disco. La colonna RA contiene il valore per readahead. Quel valore è il numero di settori a 512 byte (a meno che la dimensione del settore non sia quella predefinita - si noti che al momento della stesura di questo post, anche i dischi con dimensioni maggiori sono trattati dal kernel come settori a 512 byte) che vengono letti su ogni accesso al disco.

È possibile configurare l'impostazione readahead per un determinato dispositivo disco eseguendo:

blockdev --setra <value> <device name>

Quando si utilizza un sistema RAID basato su software, assicurarsi di impostare il readahead su ciascun dispositivo disco e sul dispositivo corrispondente al controller RAID.

Perché questo è importante? Bene, readahead utilizza la stessa risorsa che MongoDB sta cercando di utilizzare per ottimizzare le letture per l'accesso sequenziale: la RAM. Quando si eseguono letture sequenziali su dischi rotanti (o dispositivi che si comportano in qualche modo come dischi rotanti - EBS ti sto guardando), recuperare i dati vicini nella RAM può migliorare le prestazioni in modo massiccio, risparmiarti sulle ricerche e un'impostazione di lettura elevata in l'ambiente giusto può ottenere risultati impressionanti.

Per un sistema come MongoDB in cui il tuo accesso sarà generalmente un accesso casuale attraverso un set di dati, ciò significa solo sprecare memoria che è meglio utilizzata altrove. Il sistema, che come menzionato altrove gestisce anche la memoria per MongoDB, allocherà un pezzo di memoria da leggere prima che venga richiesto e quindi lascia meno RAM affinché MongoDB possa utilizzarlo in modo efficace.

Scegliere la dimensione corretta del readahead è complicato e dipende dall'hardware, dalla configurazione, dalla dimensione del blocco, dalla dimensione dello stripe e dai dati stessi. Se, ad esempio, passi agli SSD, avrai bisogno di un'impostazione bassa, ma quanto in basso dipenderà dai dati.

Per spiegare: vuoi assicurarti che readahead sia abbastanza alto da contenere un singolo documento completo e non devi tornare sul disco. Prendiamo la tua dimensione media menzionata di 8k - poiché i settori su disco sono generalmente di 512 byte, occorrerebbero 16 accessi al disco per leggere l'intero documento senza readahead. Se avessi una lettura di almeno 16 settori, leggeresti l'intero documento con un solo viaggio su disco.

In realtà, poiché i bucket di indice MongoDB sono 8k, non vorrai mai impostare readahead al di sotto di 16 o ci vorranno 2 accessi al disco per leggere in un bucket di indice. Una buona pratica generale è iniziare con le impostazioni correnti, dimezzarle, quindi rivalutare l'utilizzo della RAM e l'IO e passare da lì.


1
Informazioni preziose che torneranno sicuramente utili una volta che avremo dell'hardware in casa. Grazie!
sysadmin1138

3

Si consiglia di utilizzare le repliche per le query degli utenti finali e di eseguire il flusso di lavoro su altre macchine.

Usando la tua regola empirica 1:10, stai cercando circa 128 GB di RAM per 1 TB di spazio su disco; Mentre alcuni SSD convenienti oggi affermano di raggiungere> 60K IOPS, i numeri del mondo reale possono differire un po ', anche se stai usando RAID con i tuoi SSD o meno, e se lo sei, allora anche la scheda RAID è estremamente importante .

Al momento di questo post, passare da 128 GB di RAM DDR3 ECC a 256 GB sembra essere circa 2000 $ in più su un server Intel 1U, e questo ti darà un rapporto 1: 5 con 1 TB di dati, che ritengo sarebbe un rapporto ancora migliore. Se hai bisogno che il tuo carico di lavoro sia finito il più velocemente possibile, sicuramente più RAM ti aiuterà, ma è davvero così urgente?

Dovrai fare anche qualche messa a punto del file system, qualcosa come "noatime, data = writeback, nobarrier" su ext4, e potresti aver bisogno di apportare alcune modifiche alle impostazioni del kernel per ottenere il massimo dalle prestazioni che puoi sistema.

Se vai con RAID, RAID-10 sarà una scelta abbastanza buona e con il controller RAID appropriato offrirà un notevole aumento delle prestazioni, ma con la metà dello spazio disponibile. Puoi anche esaminare RAID50 se desideri un aumento decente delle prestazioni senza dimezzare lo spazio disponibile. Il rischio di eseguire un RAID è che non hai più accesso a TRIM sulle tue unità, il che significa che ogni tanto devi spostare i tuoi dati, rompere il RAID, TRIM le unità e ricreare il RAID.

In definitiva, devi decidere quanta complessità vuoi, quanti soldi vuoi spendere e quanto velocemente vuoi che il tuo carico di lavoro venga elaborato. Valuterei anche se MongoDB è il database ideale da utilizzare, in quanto potresti ancora utilizzare Mongo per query degli utenti finali che richiedono risposte rapide, ma utilizzare qualcos'altro per elaborare i tuoi dati, che non devono essere pronti in pochi secondi e può anche consentire di distribuire il carico di lavoro su più macchine con maggiore facilità.

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.