← Tutti gli articoli

MongoDB arbiters possono bloccare le write e ridurre la durabilità

MongoDB arbiters possono bloccare le write e ridurre la durabilità

MongoDB arbiters possono aiutare un replica set a eleggere un primary, ma non possono archiviare, replicare o confermare dati. Percona afferma che i suoi casi di assistenza mostrano come questa distinzione possa trasformare un deployment di produzione apparentemente sano in uno che limita le write, va in timeout o esegue il rollback di record già confermati.

Un replica set è un gruppo di server MongoDB che mantiene copie degli stessi dati. MongoDB introdusse l'arbiter nelle sue prime release del 2010, in modo che gli operatori potessero creare un numero dispari di voti senza sostenere il costo di un altro server che archiviasse dati. Durante un'elezione, il processo che seleziona quale membro diventa primary, l'arbiter esprime un voto. Non applica l'oplog, il registro ordinato delle modifiche al database di MongoDB, e non ha mai migliorato la durabilità dei dati.

Questa limitazione divenne più rilevante durante le ere di MongoDB 3.x e 4.x. WiredTiger divenne lo storage engine predefinito, mentre il protocollo del replica set passò a pv1. MongoDB rese inoltre readConcern e writeConcern, impostazioni che controllano con quale livello di conferma devono essere gestite le read e le write, elementi centrali per la durabilità. Change streams, multi-document transaction, flow control e read concern e write concern predefiniti a livello di cluster dipendono tutti da forme di accordo di maggioranza. Un arbiter conta ai fini della maggioranza elettorale, ma non per la maggioranza dei membri che archiviano dati necessaria a confermare le write o a far avanzare il majority commit point, ossia la modifica più recente confermata in modo durevole da un numero sufficiente di replica.

Un caso di assistenza di Percona riguardava uno sharded cluster, che divide i dati tra più replica set. Aveva tre shard e un config-server replica set. Ogni shard collocava tre membri che archiviavano dati in un data center, tre in un secondo e un arbiter in un terzo sito. Ciò produceva sette membri votanti per shard, sei dei quali conservavano dati. I config server utilizzavano invece sei membri che archiviavano dati, due in ciascuno dei tre siti e senza arbiter.

Dopo il guasto di un data center, le elezioni furono completate e ogni shard selezionò un nuovo primary. Il throughput delle write scese quindi da circa 3.000-4.000 operazioni al secondo su ciascuno shard a circa 50-75. Le applicazioni si connettevano tramite mongos, il query router di MongoDB, e utilizzavano `{ w: 2, j: true }`, richiedendo la conferma da parte di due membri con persistenza nel journal. Su ogni shard rimanevano raggiungibili tre membri che archiviavano dati e l'arbiter.

Il problema era un'operazione interna, non il writeConcern selezionato dall'applicazione. Alcune attività dello sharded cluster, inclusi gli aggiornamenti del routing delle collection, eseguono un no-op locale, un'operazione che non modifica alcun dato dell'utente, con majority write concern. Con sette votanti e un arbiter, `writeMajorityCount` era pari a quattro. L'arbiter poteva votare ma non poteva confermare quella write, quindi i tre membri superstiti che archiviavano dati non riuscivano a soddisfare il requisito. Il majority commit point smise di avanzare e gli aggiornamenti del routing rimasero in attesa di un timeout hardcoded di circa 60 secondi. I config server evitarono lo stesso problema perché quattro dei loro sei membri che archiviavano dati erano sopravvissuti, un numero sufficiente per la loro maggioranza.

Un secondo caso mostrò perché un arbiter non può alleggerire il flow control, il meccanismo di MongoDB che rallenta il primary quando i replica rimangono troppo indietro. Il replica set aveva quattro membri che archiviavano dati, suddivisi equamente tra due data center, più un arbiter in un terzo sito. Due secondary in una sede accumularono un replication lag che arrivò a circa 1.000 secondi durante write intense, che generavano un oplog di grandi dimensioni sul primary. Il primary e il suo secondary locale rimasero aggiornati, ma per far avanzare il majority commit point erano necessari tre dei quattro membri che archiviavano dati. Con solo due membri allineati, il flow control limitò le write del primary, anche se l'arbiter rimaneva disponibile.

L'esempio più grave utilizzava una topologia Primary-Secondary-Arbiter, comunemente abbreviata in PSA. Il primary, N1, aveva priorità elettorale 2 e l'applicazione utilizzava `w: 1`, il che significava che una write poteva essere confermata dopo aver raggiunto un solo membro. Quando N1 si arrestò in modo anomalo, il secondary, N2, divenne primary e accettò write confermate per circa un'ora. N1 tornò quindi disponibile, ma N2 si arrestò prima che N1 si fosse allineato. N1 e l'arbiter formarono una maggioranza votante, permettendo a N1 di diventare primary nonostante gli mancassero le modifiche di quell'ora.

Quando N2 rientrò nel replica set, il suo oplog conteneva una cronologia più recente ma in conflitto oltre l'ultimo punto condiviso con N1. MongoDB eseguì il rollback di tali modifiche per renderle coerenti con il primary eletto. I documenti poterono essere recuperati soltanto perché MongoDB li aveva conservati come file BSON, il suo formato binario per documenti, nella directory di rollback sotto `dbPath`, la posizione di archiviazione del database. Non erano mai stati replicati altrove. Un terzo membro che archiviasse dati e fosse rimasto aggiornato avrebbe invece potuto trovarsi più avanti di N1 ed essere idoneo a diventare primary, anche se le eventuali write finali che non lo avessero raggiunto avrebbero comunque potuto subire un rollback.

Le linee guida documentate di MongoDB per il deployment riflettono questi rischi. Per i replica set con tre membri è consigliata la configurazione Primary-Secondary-Secondary, o PSS. PSA viene presentata come un'alternativa meno costosa, con ridondanza e fault tolerance inferiori, perché esistono soltanto due copie complete dei dati. Un arbiter non dovrebbe condividere un host con un primary o un secondary, poiché il guasto di un singolo host eliminerebbe sia dati sia un voto. Anche più arbiter compromettono l'affidabilità delle majority write. A partire da MongoDB 5.3, il supporto di più arbiter in un singolo replica set è disabilitato per impostazione predefinita, perché il replica set potrebbe accettare write senza disporre di un numero sufficiente di secondary per replicarle.

Gli arbiter impongono inoltre restrizioni alle transaction. Una shard key non può essere modificata tramite una transaction quando il replica set contiene un arbiter. Poiché gli arbiter non possono eseguire le operazioni sui dati necessarie per le multi-shard transaction, una transaction che coinvolge più shard genera un errore e viene interrotta se una qualsiasi operazione legge da o scrive su uno shard che ne contiene uno. MongoDB Atlas non supporta gli arbiter in alcun tier.

La lezione pratica è valutare separatamente la disponibilità dei voti e la durabilità dei dati. Una schermata di stato può mostrare un'elezione riuscita mentre il database non è in grado di far avanzare i majority commit, stare al passo con la replication o preservare le write confermate. I team dovrebbero monitorare replication lag, write latency e avanzamento del commit point, verificare guasti completi dei siti e scegliere write concern che riflettano l'importanza dei dati. Per le organizzazioni che devono decidere dove gestire questi sistemi, AEU Data fornisce infrastrutture cloud e dati europee, mentre una corretta progettazione del replica set rimane una responsabilità operativa.

Sostituire un arbiter con un membro che archivia dati richiede più capacità, ma aggiunge un'altra copia in grado di confermare e preservare le write. I casi di Percona mostrano che il membro votante meno costoso può imporre un costo operativo maggiore quando le write si bloccano, le transaction non riescono o i record sopravvivono soltanto nei file di rollback.

Disponibile anche in: EnglishDeutschShqip