MongoDB 复制机制
一、復(fù)制原理
MongoDB的復(fù)制功能是使用操作日志oplog實(shí)現(xiàn)的,oplog包含主節(jié)點(diǎn)(Master)的每一次寫(xiě)操作,oplog是local本地?cái)?shù)據(jù)庫(kù)中的一個(gè)數(shù)據(jù)集合,其它非主節(jié)點(diǎn)(Secondary)通過(guò)讀取主節(jié)點(diǎn)的oplog集合中的記錄同步到對(duì)應(yīng)的集合,然后再寫(xiě)入到自身的local數(shù)據(jù)庫(kù)的oplog集合中。每個(gè)節(jié)點(diǎn)都維護(hù)著自己的oplog,記錄著每一次從主節(jié)點(diǎn)復(fù)制數(shù)據(jù)的操作。這樣每個(gè)成員都可以作為同步源提供給其它成員使用。
注意:需要注意Secondary節(jié)點(diǎn)同步數(shù)據(jù)的順序是先同步數(shù)據(jù),然后再寫(xiě)入oplog;這點(diǎn)和mysql的機(jī)制不同。但是每個(gè)節(jié)點(diǎn)oplog中記錄的同步數(shù)據(jù)是完全一致的,所以也不擔(dān)心被執(zhí)行多次。
?
二、oplog集合
1.insert操作
/* 1 */{"ts" : Timestamp(1520580648, 1),"t" : NumberLong(20),"h" : NumberLong(-8701728013874689868),"v" : 2,"op" : "i","ns" : "test.person","ui" : UUID("782befd9-80ae-4a2c-86ae-33a147e7c948"),"wall" : ISODate("2018-03-09T07:30:48.120Z"),"o" : {"_id" : ObjectId("5aa2382f7239a98c7e679114"),"name" : "zhang"} }2.update操作
/* 1 */{"ts" : Timestamp(1520584444, 2),"t" : NumberLong(20),"h" : NumberLong(7151217369265341585),"v" : 2,"op" : "u","ns" : "test.person","ui" : UUID("782befd9-80ae-4a2c-86ae-33a147e7c948"),"o2" : {"_id" : ObjectId("5aa2382f7239a98c7e679114")},"wall" : ISODate("2018-03-09T08:34:04.777Z"),"o" : {"$v" : 1,"$set" : {"name" : "wang"}} }- ts: 操作時(shí)間,當(dāng)前timestamp + 計(jì)數(shù)器,計(jì)數(shù)器每秒都被重置
- h:操作的全局唯一標(biāo)識(shí)
- v:oplog版本信息
- op:操作類(lèi)型:
- ns:操作針對(duì)的集合
- ui:
- o:操作內(nèi)容,如果是更新操作
- o2:操作查詢條件,僅update操作包含該字段
- wall:記錄的時(shí)間戳。
3.查詢oplog集合
db.oplog.rs.find({"op":{$in:["i","u","d"]}}).sort({"wall":-1});三、初始化同步
1.選擇一個(gè)成員作為同步源,在local.me中創(chuàng)建標(biāo)識(shí)符;刪除已存在的數(shù)據(jù)庫(kù)。
2.將同步源的所有數(shù)據(jù)復(fù)制到本地。所有的操作都被集合到oplog中。
3.將第一個(gè)oplog同步中的操作記錄下來(lái)。
4.創(chuàng)建相關(guān)索引,如果集合比較大該過(guò)程可能會(huì)花費(fèi)很長(zhǎng)的時(shí)間。
5.將創(chuàng)建索引過(guò)程中同步源增加的記錄同步過(guò)來(lái)。
6.同步完成,修改節(jié)點(diǎn)狀態(tài)為SECONDARY
四、心跳
每個(gè)成員每隔兩秒鐘就會(huì)向其它成員發(fā)送一個(gè)心跳請(qǐng)求,心跳的請(qǐng)求信息量非常的小,用于檢查每個(gè)成員的狀態(tài)。
心跳最主要的功能之一就是讓主節(jié)點(diǎn)知道自己是否滿足集合“大多數(shù)”的條件。如果主節(jié)點(diǎn)不再得到“大多數(shù)”服務(wù)器的支持,它就會(huì)退位變成備份節(jié)點(diǎn)。
成員狀態(tài)
| Number | Name | State Description |
| 0 | STARTUP | Not yet an active member of any set. All members start up in this state. The?mongod?parses the?replica set configuration document?while inSTARTUP. |
| 1 | PRIMARY | The member in state?primary?is the only member that can accept write operations. Eligible to vote. |
| 2 | SECONDARY | A member in state?secondary?is replicating the data store. Eligible to vote. |
| 3 | RECOVERING | Members either perform startup self-checks, or transition from completing a?rollback?or?resync. Eligible to vote. |
| 5 | STARTUP2 | The member has joined the set and is running an initial sync. |
| 6 | UNKNOWN | The member’s state, as seen from another member of the set, is not yet known. |
| 7 | ARBITER | Arbiters?do not replicate data and exist solely to participate in elections. |
| 8 | DOWN | The member, as seen from another member of the set, is unreachable. |
| 9 | ROLLBACK | This member is actively performing a?rollback. Data is not available for reads. |
| 10 | REMOVED | This member was once in a replica set but was subsequently removed. |
五、選舉
當(dāng)一個(gè)成員無(wú)法到達(dá)主節(jié)點(diǎn)時(shí),它就會(huì)申請(qǐng)被選舉為主節(jié)點(diǎn)。希望被選舉為主節(jié)點(diǎn)的成員會(huì)向它能到達(dá)的所有成員發(fā)送通知。如果這個(gè)成員不符合候選人的要求,其它成員可能會(huì)知道相關(guān)原因:這個(gè)成員的數(shù)據(jù)落后于副本集,或者已經(jīng)有一個(gè)運(yùn)行中的主節(jié)點(diǎn)(希望被選舉為主節(jié)點(diǎn)的成員無(wú)法到達(dá)這個(gè)主節(jié)點(diǎn))。在這些情況下,其它成員不會(huì)允許進(jìn)行選舉。
如果沒(méi)有其它成員反對(duì),其他成員就會(huì)對(duì)這個(gè)成員進(jìn)行選舉投票,如果滿足副本集中“大多數(shù)”贊成票,它就被選舉成功,轉(zhuǎn)換成為主節(jié)點(diǎn)。否則選舉失敗仍然處于備份節(jié)點(diǎn)狀態(tài),之后還可以再次申請(qǐng)被選舉為主節(jié)點(diǎn)。而主節(jié)點(diǎn)會(huì)一直主節(jié)點(diǎn)狀態(tài),除非它由于不再滿足“大多數(shù)”的要求或者宕機(jī)而退位,另外副本集被重新配置也會(huì)導(dǎo)致主節(jié)點(diǎn)退位。
在網(wǎng)絡(luò)良好的情況下,同時(shí)投票服務(wù)器也正常運(yùn)行那么選舉過(guò)程會(huì)很快,由于節(jié)點(diǎn)之間的互ping是每隔2S,所以如果有主節(jié)點(diǎn)不可用那么2S之內(nèi)就會(huì)有成員發(fā)現(xiàn),然后就會(huì)立即開(kāi)始選舉,整個(gè)過(guò)程正常只會(huì)花費(fèi)幾毫秒。如果存在網(wǎng)絡(luò)問(wèn)題或者服務(wù)器過(guò)載響應(yīng)緩慢都有可能觸發(fā)選舉。在這種情況下,心跳會(huì)在最多10S之后超時(shí)。如果選舉打成平局,每個(gè)成員都需要等待30S才能開(kāi)始下一次選舉,所以如果發(fā)生太多錯(cuò)誤的情況下選舉可能會(huì)花費(fèi)幾分鐘的時(shí)間。
六、回滾
?
一般情況下跨數(shù)據(jù)中心復(fù)制要比同數(shù)據(jù)中心復(fù)制慢。
上圖的兩個(gè)數(shù)據(jù)中心之間出現(xiàn)網(wǎng)絡(luò)故障,DC1最后的操作是126,DC2最后的操作是125;DC1的126操作還沒(méi)有被復(fù)制到DC2;由于采取的是多數(shù)節(jié)點(diǎn)的投票機(jī)制,DC2數(shù)據(jù)中心的副本滿足“大多數(shù)”節(jié)點(diǎn)的要求(一共5臺(tái)服務(wù)器,3臺(tái)服務(wù)器即可超過(guò)半數(shù)投票)。因此其中一臺(tái)服務(wù)器會(huì)被選舉成為新的主節(jié)點(diǎn),這個(gè)主節(jié)點(diǎn)會(huì)繼續(xù)后續(xù)的寫(xiě)操作。假設(shè)在DC1的網(wǎng)絡(luò)恢復(fù)之前DC2已經(jīng)操作到了130。
DC1
| 123 | 124 | 125 | 126 |
DC2
| 123 | 124 | 125 | 126'' | 127'' | 128'' | 129'' | 130'' |
?
在DC1網(wǎng)絡(luò)恢復(fù)之后,DC1就會(huì)從DC2同步126之后的操作,但是會(huì)發(fā)現(xiàn)這個(gè)操作是無(wú)法操作的,這時(shí)候DC1和DC2就會(huì)進(jìn)入回滾過(guò)程,DC1和DC2會(huì)查找到二者共同的操作點(diǎn)125,DC1和DC2都會(huì)回滾到125,然后二者才會(huì)繼續(xù)后面的同步操作
注意:如果回滾的數(shù)據(jù)量比較大需要很長(zhǎng)的時(shí)間,這時(shí)可能會(huì)導(dǎo)致回滾失敗,對(duì)于回滾失敗的節(jié)點(diǎn),必須要重新進(jìn)行同步。一般造成這種情況的主要原因是備份節(jié)點(diǎn)遠(yuǎn)遠(yuǎn)落后于主節(jié)點(diǎn),而這時(shí)主節(jié)點(diǎn)掛了。
?
?
?
?
?
?
?
?
| 備注: ??? 作者:pursuer.chen ??? 博客:http://www.cnblogs.com/chenmh 本站點(diǎn)所有隨筆都是原創(chuàng),歡迎大家轉(zhuǎn)載;但轉(zhuǎn)載時(shí)必須注明文章來(lái)源,且在文章開(kāi)頭明顯處給明鏈接,否則保留追究責(zé)任的權(quán)利。 《歡迎交流討論》 |
?
總結(jié)
以上是生活随笔為你收集整理的MongoDB 复制机制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 在 Scale Up 中使用 Healt
- 下一篇: 吃自助餐怎么样一个顺序吃法才合算?