2013-03-10 6 views
5

Ho un piccolo set di repliche di tre server mongod (16 GB di RAM ciascuno, almeno 4 core CPU e veri HDD) e un arbitro dedicato. I dati replicati hanno attualmente circa 100.000.000 di record. Quasi tutti questi dati si trovano in una raccolta con un indice su _id (l'ID Mongo generato automaticamente) e date, che è un campo di data Mongo nativo. Periodicamente posso eliminare vecchi dischi di questa collezione utilizzando l'indice data, qualcosa di simile (dalla shell mongo):MongoDB cancellazioni molto lente

db.repo.remove({"date" : {"$lt" : new Date(1362096000000)}}) 

Questo funziona, ma funziona molto, molto lentamente. Uno dei miei nodi ha un I/O più lento degli altri due, avendo solo una singola unità SATA. Quando questo nodo è primario, le eliminazioni vengono eseguite a circa 5-10 documenti al secondo. Usando rs.stepDown() ho retrocesso questo primario più lento e ho forzato un'elezione per ottenere un primario con un migliore I/O. Su quel server, sto ottenendo circa 100 docs/sec.

La mia domanda principale è, dovrei essere preoccupato? Non ho i numeri prima di introdurre la replica, ma so che l'eliminazione è stata molto più veloce. Mi chiedo se la sincronizzazione del set di repliche stia causando l'attesa di I/O, o se c'è qualche altra causa. Sarei totalmente felice di disattivare temporaneamente gli aggiornamenti di sincronizzazione e indice fino a quando l'istruzione delete non termina, ma non conosco alcun modo per farlo al momento. Per qualche ragione, quando disabilito due dei tre nodi, lasciando solo un nodo e l'arbitro, il nodo rimanente viene abbassato di livello e le scritture sono impossibili (l'arbitro non dovrebbe risolvere il problema?).

Per fornire indicazioni sulla prestazione generale, se si rilasciano e si ricrea l'indice della data, sono necessari circa 15 minuti per eseguire la scansione di tutti i documenti da 100 M.

+0

il motivo per cui non è possibile disabilitare due dei quattro nodi è che non può esserci un primario senza la maggioranza del set disponibile. Perché hai quattro membri, a proposito? Non è necessario un arbitro con tre nodi in un set di repliche. –

+0

Gotcha - Al momento ho solo quattro nodi perché al 5 ° nodo manca un disco rigido e l'ho rimosso dal cluster :) Ironia della sorte, ho sollevato un arbitro per garantire che ci sarebbe sempre un vincitore in un'elezione principale. Ad ogni modo, l'arbitro è una piccola VM che uso anche per altre cose overhead basse come i server di configurazione in altri cluster sharding. – SteveK

+0

ti serviva un arbitro quando avevi quattro nodi (per avere cinque voti) ma quando rimuovi il quinto nodo dal set di repliche dovresti rimuovere anche l'arbitro, in modo che rimangano tre membri. –

risposta

7

Questo sta accadendo perché, anche se

db.repo.remove({"date" : {"$lt" : new Date(1362096000000)}}) 

si presenta come un unico comando in realtà è operare su molti documenti - come molti come soddisfare questa domanda.

Quando si utilizza la replica, ogni operazione di modifica deve essere scritta in una raccolta speciale nel database local denominato oplog.rs - oplog in breve.

L'oplog deve avere una voce per ogni documento eliminato e ognuna di queste voci deve essere applicata all'oplog su ciascun secondario prima che possa anche eliminare lo stesso record.

Una cosa che posso suggerire che si considera è TTL indexes - saranno "automaticamente" cancellare i documenti in base alla data di scadenza/valore impostato - in questo modo non sarà necessario un massiccio eliminare e invece sarà in grado di distribuire il carico più nel tempo.

+0

Grazie per la spiegazione, questo ha molto senso. Inoltre, non conoscevo gli indici TTL: sembra una funzionalità eccezionale! – SteveK

+0

Non sono sicuro che questa soluzione sia accurata. Nei documenti Mongo su https://docs.mongodb.org/manual/core/index-ttl/ si afferma, "Sui set di repliche, il thread in background TTL elimina solo i documenti sul primario, tuttavia viene eseguito il thread in background TTL sui secondari I membri secondari replicano le operazioni di cancellazione dal primario. " A questo non significherebbe che non c'è differenza nelle prestazioni di oplog con un TTL rispetto a un'operazione manuale? – Nucleon

+0

la differenza è che il thread TTL viene eseguito ogni minuto alla ricerca di documenti da eliminare. L'utente in questo caso stava eseguendo un'unica eliminazione enorme per rimuoverli tutti in una volta. TTL distribuisce l'eliminazione solo su un periodo più lungo, in modo da eseguire blocchi più piccoli ogni minuto. Questo presuppone che la scadenza sia su un campo preciso al minuto. –

1

Un altro suggerimento che non si può andare bene, ma era la soluzione ottimale per me:

  1. goccia indici della collezione
  2. iterare su tutte le voci di raccolta e Codice del negozio di di record da cancellare in un array di memoria
  3. ogni volta array è abbastanza grande (per me è stato 10K record), ho rimosso questi record da IDS
  4. ricostruire indici

È il modo più veloce, ma richiede l'arresto del sistema, che era adatto a me.