MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Come prevenire i rollback in MongoDB

La replica in MongoDB implica set di repliche da parte di membri con un'architettura di membri primari e secondari ma a volte con un membro non contenente dati chiamato arbitro. Il processo di replica prevede che, ogni volta che i dati sono stati scritti nel nodo primario, le modifiche vengono registrate su un file oplog da cui i membri secondari applicano le stesse modifiche. Le operazioni di lettura possono essere eseguite da qualsiasi membro contenente dati, creando così uno scenario comunemente noto come Alta disponibilità.

Tuttavia, in alcuni casi i membri secondari potrebbero non riuscire a recuperare il ritardo con il primario nell'apportare modifiche e nel caso in cui il nodo primario si guasta prima che queste modifiche siano state applicate, sarà necessario risincronizzare l'intero cluster in modo che possano trovarsi nello stesso stato di dati.

Cos'è un rollback?

Questa è una funzionalità di failover automatico in MongoDB in cui il nodo primario in un set di repliche potrebbe non riuscire mentre si apportano modifiche che purtroppo finiscono per non essere riflesse ai membri secondari in tempo dall'oplog, quindi è necessario ripristinare il stato del primario a uno prima che venissero apportate le modifiche.

I rollback sono quindi necessari solo quando il primario ha accettato di scrivere le operazioni che non sono state replicate ai membri secondari prima che il primario scenda per qualche motivo come la partizione di rete. Se nel caso in cui le operazioni di scrittura riescano a essere replicate in uno dei membri che è disponibile e accessibile alla maggior parte del set di repliche, non si verificherà un rollback.

Il motivo principale alla base dei rollback in MongoDB è mantenere la coerenza dei dati per tutti i membri e pertanto, quando il primario si unisce nuovamente al set di repliche, se le sue modifiche non sono state applicate ai membri secondari, verrà ripristinato allo stato prima del fallimento.

Tuttavia, i rollback dovrebbero essere rari o meglio evitati in MongoDB in quanto possono comportare una grande perdita di dati e di conseguenza influire sul funzionamento delle applicazioni collegate al database.

Processo di ripristino di MongoDB

Consideriamo un insieme di repliche a tre membri con A come membri primari, B e C come membri secondari. Popoleremo i dati in A e allo stesso tempo attiveremo alcune partizioni di rete in B e C. Useremo MongoDB versione 4.2 e Atlas in questo test.

Per prima cosa otterremo lo stato del set di repliche eseguendo il comando rs.status() sulla mongo shell  

MongoDB Enterprise Cluster0-shard-0:PRIMARY> rs.status()

Guardando l'attributo dei membri puoi vedere qualcosa come

"members" : [

{

"_id" : 0,

"name" : "cluster0-shard-00-00-sc27x.mongodb.net:27017",

"health" : 1,

"state" : 2,

"stateStr" : "SECONDARY",

"uptime" : 1891079,

"optime" : {

"ts" : Timestamp(1594826711, 1),

"t" : NumberLong(27)

},

"optimeDurable" : {

"ts" : Timestamp(1594826711, 1),

"t" : NumberLong(27)

},

"optimeDate" : ISODate("2020-07-15T15:25:11Z"),

"optimeDurableDate" : ISODate("2020-07-15T15:25:11Z"),

"lastHeartbeat" : ISODate("2020-07-15T15:25:19.509Z"),

"lastHeartbeatRecv" : ISODate("2020-07-15T15:25:18.532Z"),

"pingMs" : NumberLong(0),

"lastHeartbeatMessage" : "",

"syncingTo" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",

"syncSourceHost" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",

"syncSourceId" : 2,

"infoMessage" : "",

"configVersion" : 4

},

{

"_id" : 1,

"name" : "cluster0-shard-00-01-sc27x.mongodb.net:27017",

"health" : 1,

"state" : 2,

"stateStr" : "SECONDARY",

"uptime" : 1891055,

"optime" : {

"ts" : Timestamp(1594826711, 1),

"t" : NumberLong(27)

},

"optimeDurable" : {

"ts" : Timestamp(1594826711, 1),

"t" : NumberLong(27)

},

"optimeDate" : ISODate("2020-07-15T15:25:11Z"),

"optimeDurableDate" : ISODate("2020-07-15T15:25:11Z"),

"lastHeartbeat" : ISODate("2020-07-15T15:25:17.914Z"),

"lastHeartbeatRecv" : ISODate("2020-07-15T15:25:19.403Z"),

"pingMs" : NumberLong(0),

"lastHeartbeatMessage" : "",

"syncingTo" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",

"syncSourceHost" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",

"syncSourceId" : 2,

"infoMessage" : "",

"configVersion" : 4

},

{

"_id" : 2,

"name" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",

"health" : 1,

"state" : 1,

"stateStr" : "PRIMARY",

"uptime" : 1891089,

"optime" : {

"ts" : Timestamp(1594826711, 1),

"t" : NumberLong(27)

},

"optimeDate" : ISODate("2020-07-15T15:25:11Z"),

"syncingTo" : "",

"syncSourceHost" : "",

"syncSourceId" : -1,

"infoMessage" : "",

"electionTime" : Timestamp(1592935644, 1),

"electionDate" : ISODate("2020-06-23T18:07:24Z"),

"configVersion" : 4,

"self" : true,

"lastHeartbeatMessage" : ""

}

],

Questo ti mostrerà lo stato di ogni membro del tuo set di repliche. Ora abbiamo aperto un nuovo terminale per il nodo A e lo abbiamo popolato con 20000 record:

MongoDB Enterprise Cluster0-shard-0:PRIMARY> for (var y = 20000; y >= 0; y--) {

    db.mytest.insert( { record : y } )

 }

WriteResult({ "nInserted" : 1 })

MongoDB Enterprise Cluster0-shard-0:PRIMARY> db.mytest 2020-07-15T21:28:40.436+2128 I NETWORK  [thread1] trying reconnect to 127.0.0.1:3001 (127.0.0.1) failed

2020-07-15T21:28:41.436+2128 I 

NETWORK  [thread1] reconnect 127.0.0.1:3001 (127.0.0.1) ok

MongoDB Enterprise Cluster0-shard-0:SECONDARY> rs.slaveOk()

MongoDB Enterprise Cluster0-shard-0:SECONDARY> db.mytest.count()

20000

Durante il partizionamento di rete, A sarà inattivo rendendolo non disponibile per B e C e quindi B eleggerà come primario nel nostro caso. Quando A si unisce di nuovo, verrà aggiunto come secondario e puoi verificarlo usando il comando rs.status(). Tuttavia, alcuni record sono riusciti a essere replicati nel membro B prima del partizionamento di rete come mostrato di seguito:(Ricorda che in questo caso B è il primario ora)

MongoDB Enterprise Cluster0-shard-0:PRIMARY> db.mytest.find({}).count()

12480    

Il numero è il conteggio dei documenti che è stato possibile replicare in B prima che A cadesse.

Se scriviamo alcuni dati in B e consentiamo ad A di unirsi alla rete, allora possiamo notare alcune modifiche ad A

connecting to: 127.0.0.1:3001/admin

MongoDB Enterprise Cluster0-shard-0:ROLLBACK> 

MongoDB Enterprise Cluster0-shard-0:RECOVERING> 

MongoDB Enterprise Cluster0-shard-0:SECONDARY> 

MongoDB Enterprise Cluster0-shard-0:SECONDARY> 

MongoDB Enterprise Cluster0-shard-0:PRIMARY>

Utilizzando un oplogFetcher i membri secondari sincronizzano le voci dell'oplog dal loro syncSource. OplogFetcher attiva un metodo find per l'oplog di origine seguito da una serie di serie di cursori getMores. Quando A si unisce come secondario, viene applicato lo stesso approccio e viene restituito un documento maggiore del timestamp del predicato. Se il primo documento in B non corrisponde all'ultima voce dell'oplog di A, A sarà forzato a un rollback.

Recupero dei dati di rollback in MongoDB

Il rollback non è una brutta cosa in MongDB, ma si dovrebbe cercare il più possibile per assicurarsi che non avvengano abbastanza spesso. È una misura automatica di sicurezza per garantire la coerenza dei dati tra i membri di un set di repliche. Nel caso in cui si verifichi il rollback, ecco alcuni passaggi per affrontare la situazione:

Raccolta dati di rollback

È necessario raccogliere i dati dei membri relativi al rollback. Ciò avviene assicurandosi che i file di rollback vengano creati (disponibile solo con MongoDB versione 4.0) abilitando createRollbackDataFiles. Per impostazione predefinita questa opzione è impostata su true, quindi i file di rollback verranno sempre creati.

I file di rollback sono inseriti nel percorso /rollback/. e contengono dati che possono essere convertiti dal formato BSON utilizzando lo strumento bsondump in un formato leggibile dall'uomo.

Caricamento dei dati dei file di rollback in un database o server separato

Mongorestore è un aspetto vitale di MongoDB che può aiutare a consentire il ripristino dei file di dati di rollback. La prima cosa è copiare i file di rollback in un nuovo server, quindi utilizzare mongorestore per caricare i file nel server. Il comando mongorestore è mostrato di seguito.

mongorestore -u <> -p <> -h 127.0.0.1 -d <rollbackrestoretestdb> -c <rollbackrestoretestc> <path to the .bson file> --authenticationDatabase=<database of user>

Pulizia dei dati non necessari e setacciamento dei dati

Questo passaggio richiede di usare discrezione per scegliere tra i dati da conservare dai file di rollback ei dati da buttare via. È consigliabile importare tutti i dati dei file di rollback, questo punto di decisione rende questo passaggio il passaggio più difficile nel recupero dei dati.

Utilizzo del primario come cluster per importare dati 

Inizia il passaggio finale scaricando i dati ripuliti tramite l'uso di mongorestore e mongodump, quindi reimporta i dati nel cluster di produzione originale.

Prevenire i rollback di MongoDB

Per evitare che si verifichino rollback dei dati quando si utilizza MongoDB, è possibile eseguire le seguenti operazioni.

Esecuzione di tutti i membri votanti "MAGGIORANZA"

Questo può essere fatto usando w:major write concern che ha il potere di richiedere il riconoscimento dell'opzione che consentirà l'operazione di scrittura su determinati tag di istanze Mongod. Questo può essere ottenuto usando l'opzione w seguita dal tag . Per impedire il rollback, tutti i membri votanti in MongoDB avranno il journal abilitato e l'uso di w:preoccupazione di scrittura della maggioranza, ciò garantisce che la maggioranza sia in grado di scrivere e impostare i nodi di replica prima che si verifichi un rollback. Garantisce inoltre che il client riceva il riconoscimento dopo la propagazione dell'operazione di scrittura sul set di repliche.

Operazioni utente  

La versione aggiornata di MongoDB, ovvero la versione 4.2 ha la possibilità di chiudere tutte le operazioni in corso in caso di rollback.

Build di indici 

La versione 4.2 della versione di compatibilità delle funzionalità di MongoDB (fcv) "4.2" è in grado di attendere tutti gli indici in corso che vengono creati e completati prima che venga eseguito un rollback posto. Tuttavia, la versione 4.0 attende il continuo in corso e crea un indice in background, quindi la possibilità di un rollback è alta.

Dimensioni e limitazioni

La versione 4.0 di MongoDB non ha limiti elencati di dati di cui è possibile eseguire il rollback durante la compilazione dell'indice in background in corso.

Conclusione 

Il rollback di MongoDB è un fenomeno comune a coloro che utilizzano MongoDB senza sapere come prevenirlo. I rollback sono prevenibili se si seguono e aderiscono scrupolosamente ad alcune delle pratiche e dei modi sicuri per evitare i rollback in MongoDB. In tutto, è sempre consigliabile eseguire l'aggiornamento alla versione più recente di MongoDB in modo da evitare qualche singhiozzo prevenibile.