Replikace v MongoDB zahrnuje sady replik členů s architekturou primárního a sekundárního člena, ale někdy s členem, který nenese data, zvaným arbitr. Proces replikace spočívá v tom, že kdykoli jsou data zapsána do primárního uzlu, změny se zaznamenají do souboru oplog, ze kterého sekundární členové aplikují stejné změny. Operace čtení lze provádět z libovolného člena nesoucího data, čímž se vytváří scénář běžně známý jako vysoká dostupnost.
V některých případech se však sekundárním členům nemusí podařit dohnat primární uzel při provádění změn a v případě, že primární uzel selže dříve, než budou tyto změny aplikovány, jeden bude nucen znovu synchronizovat celý cluster aby mohly být ve stejném stavu dat.
Co je vrácení zpět?
Toto je funkce automatického převzetí služeb při selhání v MongoDB, kde primární uzel v sadě replik může selhat při provádění změn, které se bohužel nakonec neprojeví na sekundárních členech včas z oplogu, a proto je potřeba vrátit stavu primárního na jeden před provedením změn.
Vrácení změn je proto nutné pouze tehdy, když primární souhlasil se zápisem operací, které nebyly replikovány na sekundární členy, než primární z nějakého důvodu, jako je síťový oddíl, odejde. Pokud se operace zápisu podaří replikovat v jednom z členů, který je dostupný a přístupný většině sady replik, k vrácení nedojde.
Hlavním důvodem vrácení v MongoDB je zachování konzistence dat pro všechny členy, a proto, když se primární znovu připojí k sadě replik, pokud její změny nebyly aplikovány na sekundární členy, bude vrácena do stavu před poruchou.
Nicméně návraty by měly být v MongoDB vzácné nebo se jim spíše vyhnout, protože mohou vést ke ztrátě velkého množství dat a následně ovlivnit provoz aplikací připojených k databázi.
Proces vrácení zpět MongoDB
Uvažujme tříčlennou sadu replik s A jako primárními členy, B a C jako sekundárními členy. Data naplníme do A a zároveň spustíme nějaké rozdělení sítě na B a C. V tomto testu použijeme MongoDB verze 4.2 a Atlas.
Nejprve získáme stav sady replik spuštěním příkazu rs.status() na mongo shell
MongoDB Enterprise Cluster0-shard-0:PRIMARY> rs.status()
Při pohledu na atribut členů můžete vidět něco jako
"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" : ""
}
],
To vám ukáže stav každého člena vaší sady replik. Nyní jsme otevřeli nový terminál pro uzel A a naplnili jej 20 000 záznamy:
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
Během rozdělování sítě bude A mimo provoz, čímž bude nedostupný pro B a C, a proto B bude v našem případě zvolen jako primární. Když se A znovu připojí, bude přidán jako sekundární a můžete to zkontrolovat pomocí příkazu rs.status(). Některé záznamy se však podařilo replikovat do člena B před rozdělením sítě, jak je vidět níže:(Pamatujte si, že v tomto případě je B nyní primární)
MongoDB Enterprise Cluster0-shard-0:PRIMARY> db.mytest.find({}).count()
12480
Číslo je počet dokumentů, které bylo možné replikovat do B, než A zmizelo.
Pokud zapíšeme nějaká data do B a umožníme A připojit se k síti, můžeme si všimnout některých změn v 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>
Pomocí nástroje oplogFetcher sekundární členové synchronizují položky oplog ze svého zdroje synchronizace. OplogFetcher spouští metodu hledání do zdrojového oplogu následovanou řadou sérií kurzorů getMores. Když se A znovu připojí jako sekundární, použije se stejný přístup a vrátí se dokument větší než časové razítko predikátu. Pokud se první dokument v B neshoduje s posledním záznamem oplogu A, A bude nucen vrátit zpět.
Obnovení dat o vrácení v MongoDB
Rollback není v MongDB špatná věc, ale člověk by se měl snažit co nejvíce, aby se ujistil, že k nim nedochází příliš často. Jde o bezpečnostní automatické opatření zajišťující konzistenci dat mezi členy sady replik. V případě, že dojde k vrácení zpět, zde je několik kroků k vyřešení situace:
Rollback Data Collection
Potřebujete shromáždit data členů týkající se vrácení zpět. Toho dosáhnete vytvořením souborů vrácení zpět (k dispozici pouze s MongoDB verze 4.0) povolením createRollbackDataFiles. Ve výchozím nastavení je tato možnost nastavena na hodnotu true, takže soubory vrácení budou vždy vytvořeny.
Soubory vrácení zpět jsou umístěny v cestě
Načtení dat zpětných souborů do samostatné databáze nebo serveru
Mongorestore je důležitým aspektem MongoDB, který může pomoci při obnově datových souborů pro vrácení zpět. První věcí je zkopírovat soubory vrácení zpět na nový server a poté pomocí mongorestore načíst soubory na váš server. Příkaz mongorestore je zobrazen níže.
mongorestore -u <> -p <> -h 127.0.0.1 -d <rollbackrestoretestdb> -c <rollbackrestoretestc> <path to the .bson file> --authenticationDatabase=<database of user>
Čištění nepotřebných dat a prosévání dat
Tento krok vyžaduje, abyste si zvolili podle vlastního uvážení mezi daty, která mají být uchována ze souborů pro vrácení zpět, a daty, která mají být vyhozena. Je vhodné naimportovat všechna data z rollback souborů, toto rozhodnutí činí tento krok nejobtížnějším krokem při obnově dat.
Použití primárního jako clusteru k importu dat
Začněte poslední krok stažením vyčištěných dat pomocí mongorestore a mongodump a poté znovu importujte data do původního produkčního clusteru.
Prevence vrácení MongoDB
Aby se při používání MongoDB zabránilo vrácení dat zpět, můžete provést následující.
Spuštění všech hlasujících členů „MAJORITY“
To lze provést pomocí w:většinový zápisový podnik, který má možnost požádat o potvrzení, které umožní operaci zápisu do daných konkrétních značek instancí Mongod. Toho lze dosáhnout použitím volby w následované tagem
Uživatelské operace
Aktualizovaná verze MongoDB, tedy verze 4.2, má schopnost vypnout všechny probíhající operace v případě vrácení zpět.
Sestavení indexu
Verze 4.2 verze MongoDB pro kompatibilitu funkcí (fcv) "4.2" je schopna čekat na všechny probíhající indexy, které se sestavují a dokončují, než dojde k vrácení zpět místo. Verze 4.0 však čeká na pokračující vývoj a vytváří index na pozadí, takže možnost vrácení je vysoká.
Velikost a omezení
Verze 4.0 MongoDB nemá žádné uvedené limity daných dat, které lze vrátit zpět, když probíhá sestavení indexu na pozadí.
Závěr
Vrácení MongoDB je běžný jev pro ty, kteří používají MongoDB, aniž by věděli, jak tomu zabránit. Vrácení změn lze předejít, pokud se důsledně řídíte a dodržujete některé z bezpečných postupů a způsobů, jak se v MongoDB vyhnout rollbackům. Celkově vzato je vždy vhodné upgradovat na nejnovější verzi MongoDB, abyste se vyhnuli některým škytavkám, kterým lze předejít.