MongoDB復制集

1、MongoDB復制集(副本集)簡介

復制集模式(replicaSet mode),也叫副本集模式佳晶,指兩個及以上的mongo實例組合在一起,其中一個主節(jié)點可以讀寫讼载,剩下的節(jié)點可能是備節(jié)點轿秧、仲裁節(jié)點中跌、隱藏節(jié)點等等。一般生產(chǎn)環(huán)境部署為3個實例組成一個復制集淤刃,常見的有PSS(主備備)模式和PSA(主備仲裁)模式晒他。備節(jié)點不承擔寫任務,可以承擔讀任務逸贾。當主節(jié)點掛掉時陨仅,mongo的選舉機制會在該復制集中的其他備節(jié)點中選出主節(jié)點。

2铝侵、復制集部署

部署復制集的方法很簡單灼伤,可以采用mlaunch工具自動安裝MongoDB復制集,也可以根據(jù)實際需求拉起mongo進程咪鲜,然后配置復制集狐赡。在生產(chǎn)環(huán)境中一般會采用后者。下面我們就一起動手操作下疟丙,大致思路為:首先啟動所有成員的mongo的進程颖侄,然后使用rs.initiate命令將這些進程根據(jù)配置組成一個復制集。

(1)啟動所有的成員服務器享郊,需加上-replSet參數(shù)指定復制集名稱

nohup ./mongod --port 30011 --dbpath /data/db/mongodb/shard1/data1 --bind_ip 127.0.0.1,172.16.0.2 -replSet shard1 &

nohup ./mongod --port 30012 --dbpath /data/db/mongodb/shard1/data2 --bind_ip 127.0.0.1,172.16.0.2 -replSet shard1 &

nohup ./mongod --port 30013 --dbpath /data/db/mongodb/shard1/data3 --bind_ip 127.0.0.1,172.16.0.2 -replSet shard1 &

注:nohup和&的作用是拉起mongo進程后不退出览祖。由于筆者只有一臺虛擬機,所以只能通過不同的端口和目錄來啟動mongo進程作為演示炊琉。在真實生產(chǎn)環(huán)境中展蒂,一個mongod數(shù)據(jù)進程應該獨占一臺虛擬機。

執(zhí)行上述命令后苔咪,我們得到三個mongo進程锰悼,指定的復制集名字叫“shard1”:

(2)配置復制集

①進入上述任意mongo實例

./mongo --port 30011

②定義復制集配置

var config={_id:"shard1", members:[{_id:1, host:"172.16.0.2:30011"}, {_id:2, host:"172.16.0.2:30012"}, {_id:3, host:"172.16.0.2:30013"}]}

注:配置中的_id字段就是啟動mongo進程時的replSet指定的復制集名稱。

③復制集初始化

rs.initiate(config)

注:只需對復制集內(nèi)一個成員調(diào)用rs.initiate就可以了团赏,該命令會自動將配置同步到其他members箕般。復制集初始化以后,這些成員會根據(jù)配置自動選出一個主節(jié)點舔清,然后就可以正常處理業(yè)務了隘世。如下圖所示,復制集初始化完成后,當前實例由單節(jié)點變?yōu)榱薙ECONDARY:

(3)修改復制集配置的方法

如果要修改復制集的配置,可以使用rs.reconfig()來重新加載配置(覆蓋原來的配置)扎唾,原理和rs.initiate()類似澄步。

如果是添加成員和刪除成員,可以使用rs.add()和rs.remove()目锭,當然也可以使用rs.reconfig()來實現(xiàn)评汰。

(4)查看復制集信息
通過rs.status()可以查看當前復制集所有成員信息以及狀態(tài)纷捞。

3、復制集選舉機制和成員角色

3.1 選舉機制

復制集中很重要的一個概念是“大多數(shù)(majority)原則”:選擇主節(jié)點時需要由大多數(shù)節(jié)點同意被去;寫操作備復制到大多數(shù)成員時這個寫操作才是安全的主儡。大多數(shù)被定義為“復制集中一半以上的成員”,如果復制集中有些成員掛了或者是不可用惨缆,并不會影響到“大多數(shù)”糜值,因為大多數(shù)是基于復制集的配置來計算的。例如三個節(jié)點組成的復制集中坯墨,如果兩個節(jié)點同時掛掉了寂汇,剩余的一個節(jié)點無法成為主,只能是備節(jié)點捣染,無法承接寫操作的業(yè)務骄瓣。

MongoDB復制集采用大多數(shù)原則是為了防止“腦裂”,即防止少數(shù)的節(jié)點由于網(wǎng)絡原因與大多數(shù)節(jié)點失聯(lián)耍攘,然后自己選出了一個主榕栏,這樣復制集就出現(xiàn)了雙主情況,都可以寫入數(shù)據(jù)蕾各,復制集的數(shù)據(jù)就會發(fā)生混亂扒磁。

每個成員在復制集中都有自己的選舉權(quán)重,權(quán)重越高越容易被選為主節(jié)點示损。成員的權(quán)重在加入復制集時由priority參數(shù)設置渗磅。

通過思考復制集的選舉規(guī)則,我們可以推理出一下兩個部署MongoDB復制集時的兩個基本策略:

(1)一個復制集的成員個數(shù)最好是奇數(shù)检访,防止兩個成員拿到相同的票數(shù)而遲遲選不出主始鱼;
(2)一個復制集的最高選舉權(quán)重成員最好有多個,且權(quán)重相等脆贵,防止故障恢復后又發(fā)生主備切換医清。比如說某權(quán)重最大的節(jié)點故障修復后重新加入到復制集,它發(fā)起了選舉請求卖氨,由于它的選舉權(quán)重最大会烙,就變成了主節(jié)點,這樣就多了一次主備切換筒捺,對業(yè)務會有些影響柏腻。

3.2 主節(jié)點降備

有時候為了維護,需要將主節(jié)點降備系吭。有多種方式可以將主降為備五嫂。注意,我們無法強制將某個成員變?yōu)橹鞴?jié)點,除非對復制集做適當?shù)呐渲谩?/p>

主節(jié)點降級為備節(jié)點的命令為:rs.stepDown()沃缘,不指定時間即默認為60s躯枢,在60s內(nèi)該節(jié)點不能再次選為主節(jié)點。

根據(jù)之前的描述來看槐臀,可以總結(jié)出復制集發(fā)生主備切換的觸發(fā)條件有:

(1)主節(jié)點上執(zhí)行了rs.stepDonw()降備锄蹂;
(2)主節(jié)點掛掉或失聯(lián),剩余大多數(shù)節(jié)點重新選出新主水慨;
(3)優(yōu)先級更高的節(jié)點加入了復制集中得糜。

3.3 復制集其他成員角色

MongoDB復制集除了主節(jié)點和備節(jié)點外,還可以存在其他角色讥巡。

(1)仲裁者

仲裁者的作用就是參與選舉掀亩,并不保存數(shù)據(jù),也會成為主欢顷,也不會為客戶端提供服務槽棍,它一般只是為了湊夠奇數(shù)個節(jié)點,可以部署在配置較差的服務器上抬驴。如果可能炼七,應該將仲裁節(jié)點部署在單獨的故障域中,這樣它就可以以“外部視角”來看待復制集中的成員了布持。

啟動仲裁者與啟動普通mongod進程的方式相同豌拙,然后使用rs.addArb()將仲裁者添加到復制集中:

rs.addArb("server-4")

也可以在成員配置中指定arbiterOnly選項,例如:

rs.add({_id:3, host:"server-4", arbiterOnly:true})

成員一旦以仲裁者身份加入到復制集中题暖,它就永遠只能是仲裁者按傅。一個復制集內(nèi)最多只能有一個仲裁者。如果有條件胧卤,盡可能在復制集中使用奇數(shù)個數(shù)據(jù)不成員唯绍,而不要使用仲裁者。例如用PSS部署模式代替PSA模式枝誊。這對于生產(chǎn)環(huán)境的可靠性和運維有著很重要的作用况芒。

(2)隱藏者

為了隱藏某個服務器,可以在配置中指定hidden:true叶撒,只有選舉權(quán)重為0的實例才能被掩藏绝骚。

客戶端不會向隱藏成員請求數(shù)據(jù),隱藏成員也不會作為復制源祠够。因此压汪,可以將不夠強大的服務器隱藏起來。隱藏成員有著該復制集的全量數(shù)據(jù)古瓤,當復制集內(nèi)其他成員的數(shù)據(jù)文件都被破壞了蛾魄,可以通過隱藏成員上保存的數(shù)據(jù)進行環(huán)境修復。

(3)延遲復制者

數(shù)據(jù)可能會因為操作錯誤而遭受毀滅性破壞,可能有人在主節(jié)點上執(zhí)行了誤刪除命令滴须,或者剛上線的應用代碼包含了致命bug,污染了所有mongo數(shù)據(jù)叽奥。為了防止這類問題扔水,可以使用slaveDelay設置一個延遲復制者。延遲復制者的數(shù)據(jù)會比主節(jié)點延遲指定的時間朝氓,如果主節(jié)點的數(shù)據(jù)受到了破壞或者污染魔市,可以通過延遲復制者將數(shù)據(jù)恢復到指定時間之前。

同樣的赵哲,延遲復制者的選舉權(quán)重必須設置為0待德。

(4)不創(chuàng)建索引者

有時,備份節(jié)點并不需要與主節(jié)點擁有相同的索引枫夺,甚至可以沒有索引将宪,可以在成員配置中指定buildIndexs:false。主要使用場景為只做數(shù)據(jù)備份或者是離線的批量任務橡庞。

同樣的较坛,不創(chuàng)建索引者的選舉權(quán)重必須設置為0。

4 復制集數(shù)據(jù)同步

4.1 oplog簡介

MongoDB復制集內(nèi)成員的數(shù)據(jù)同步復制是通過一個日志來存儲寫操作的扒最,這個日志就叫做oplog丑勤。oplog記錄了主節(jié)點上的每一次寫操作,它是一個固定集合(Capped Collection)吧趣,其他節(jié)點通過查詢該集合就可以同步數(shù)據(jù)法竞。每個數(shù)據(jù)成員維護著自己的oplog,也可以作為同步源給其他成員使用强挫。

下面是查看oplog的例子岔霸,其中op:"i"表示這是一個插入操作,是向test.foo集合中插入了一條數(shù)據(jù)纠拔。

oplog重要字段說明如下表所示:

字段 含義
ts 8字節(jié)的時間戳秉剑,由4字節(jié)unix timestamp + 4字節(jié)自增計數(shù)表示。這個值很重要稠诲,在選舉新primary時侦鹏,會選擇ts最大的那個secondary作為新的primary。
op 1字節(jié)的操作類型臀叙,可以是如下幾種情形之一:
i略水,表示insert;
u劝萤,表示update渊涝;
d,表示delete;
c跨释,表示command胸私;
n,表示no op鳖谈,即空操作岁疼,其會定期執(zhí)行以確保時效性。
ns 操作所在namespace缆娃,由數(shù)據(jù)庫名+集合名構(gòu)成
o 操作所對應的document捷绒,即當前操作的內(nèi)容,比如說更新操作時要更新的字段和值贯要。
o2 僅限于update操作時暖侨,表示更新條件。

4.2 oplog的增長速度

oplog是固定大小的崇渗,它只能保存特定數(shù)據(jù)的操作日志字逗,oplog使用空間的增長速度跟系統(tǒng)處理寫請求的速度相當。如果單次操作影響了多個文檔(比如說刪除了多個文檔或者更新了多個文檔)显押,則oplog就會產(chǎn)生多條操作日志扳肛。如果存在大批量的操作,oplog有可能很快會被寫滿乘碑。

在生產(chǎn)環(huán)境中挖息,需要根據(jù)實際業(yè)務需求設置oplog的大小。若一個復制集上的業(yè)務量預估會很大兽肤,則需要在第一次部署生產(chǎn)環(huán)境的時候就將oplog設置大一些套腹。因為后期再調(diào)整其大小會比較麻煩。一般將oplog大小設置成能夠存儲一天的寫操作較為合理资铡,若條件有限电禀,至少應該保證oplog大小能夠保存10小時以上的寫操作。當出現(xiàn)數(shù)據(jù)丟失問題時笤休,可以通過分析oplog找回數(shù)據(jù)尖飞。或者需要對復制集內(nèi)某數(shù)據(jù)成員進行運維時店雅,可以將備節(jié)點以單節(jié)點方式啟動單獨運維政基,再次加入到復制集中可以繼續(xù)增量同步,不會因為主節(jié)點的oplog的時間窗口過段而被老化闹啦,防止走初始化同步消耗大量時間沮明。

4.3 復制集數(shù)據(jù)同步過程

primary節(jié)點寫入數(shù)據(jù)產(chǎn)生oplog,secondary通過讀取primary的oplog得到復制信息窍奋,開始復制數(shù)據(jù)并且將數(shù)據(jù)寫入到自己的oplog中荐健。如果某個操作失斀闯(只有當同步源的數(shù)據(jù)損壞或者數(shù)據(jù)與主節(jié)點不一致時才可能發(fā)生),則備節(jié)點停止從當前數(shù)據(jù)源復制數(shù)據(jù)江场。如果某個備節(jié)點重啟了纺酸,會從上次自己最后一個oplog去主找同步點。

oplog很重要的一個特性是冪等性扛稽,即一條oplog執(zhí)行多次與執(zhí)行一次的效果是相等的吁峻。

4.4 復制集初始化同步

限于篇幅,此處不再贅述在张,大家可參考阿里專家張友東的博客:MongoDB同步原理解析

初始化同步的注意事項有:

(1)如果要跟蹤初始化同步過程矮慕,最好的方法是查詢服務器日志帮匾。
(2)初始化同步操作簡單,但是速度太慢痴鳄,遠不如從備份中恢復瘟斜。
(3)克隆可能損壞同步源的工作集。實際部署后會有一個頻繁使用的數(shù)據(jù)子集在內(nèi)存中痪寻,執(zhí)行初始化同步會強制將當前成員的所用數(shù)據(jù)分頁加載到內(nèi)存中螺句,者會導致熱點數(shù)據(jù)不能常駐內(nèi)存,進而導致數(shù)據(jù)庫請求變慢橡类。不過對于較小的數(shù)據(jù)集合性能比較好的服務器蛇尚,初始化同步是個簡單易用的選項。
(4)初始化同步如果耗時太長顾画,新成員就會與同步源脫節(jié)取劫,導致新成員的數(shù)據(jù)同步速度趕不上同步源的變化速度。這個問題沒有好的解決辦法研侣,只能在不忙的時候執(zhí)行初始化同步谱邪。這是就可以看到讓主節(jié)點使用足夠大的oplog保持足夠多的操作是很有必要的!

4.5 回滾

如果主節(jié)點執(zhí)行了一次寫請求后掛了庶诡,但是備節(jié)點還沒有來得及復制這次操作惦银,那么新選舉出來的主節(jié)點就會漏掉這次寫操作,這時就會執(zhí)行回滾過程末誓。

如果回滾的數(shù)據(jù)大于300MB扯俱,或者要回滾30分鐘以上的操作,回滾就是失敗基显。對于回滾失敗的節(jié)點蘸吓,必須要重新同步。這種情況最常見的原因是備節(jié)點遠遠落后于主節(jié)點撩幽,而這時主節(jié)點卻掛了库继,落后很久的備節(jié)點升為了主箩艺。為了防止這種情況,要保證復制集內(nèi)各個數(shù)據(jù)節(jié)點之間的網(wǎng)絡要好宪萄,并且磁盤要足夠好艺谆。

5 復制集的好處

(1)可靠性
引入復制集最開始的初衷是通過數(shù)據(jù)冗余來解決故障中斷,提供不間斷的數(shù)據(jù)庫服務拜英,提高產(chǎn)品可靠性静汤。當主節(jié)點掛掉時,復制集剩余成員可以很快地重新選出主節(jié)點居凶,繼續(xù)提供服務虫给。所以復制集有著與生俱來的可靠性特點。

(2)讀寫分離
為了防止復制集內(nèi)主節(jié)點的壓力過大侠碧,可以將業(yè)務中對時效性要求不高的查詢業(yè)務放在備節(jié)點上執(zhí)行抹估。特別是比較復雜的聚合操作和報表統(tǒng)計操作,這些操作往往很耗時弄兜,放在備節(jié)點操作是個很好的選擇药蜻。

(3)功能隔離
MongoDB的備份(不管采用dump方式還是拷貝原始數(shù)據(jù)文件的方式),我們可以在備節(jié)點上執(zhí)行替饿,減少主節(jié)點的壓力(cpu语泽、內(nèi)存、磁盤IO等)视卢;

復制集可以讓我們很方便的對生產(chǎn)環(huán)境進行運維踱卵。比如說將對一個非常大的表建立索引,若以阻塞方式建立索引腾夯,那勢必會阻塞正常業(yè)務颊埃;若以非阻塞方式建立索引,那建立完索引可能需要持續(xù)很長的時間蝶俱。有了復制集我們就可以這樣做:①將一個備節(jié)點從復制集中移除班利;②以單節(jié)點模式啟動該節(jié)點,然后以阻塞方式快速建立完索引榨呆;③將該節(jié)點再以復制集方式啟動罗标,加入到原復制集中;④依次對所有備節(jié)點都執(zhí)行這樣的操作积蜻;⑤對主節(jié)點進行降備闯割,然后再執(zhí)行同樣的操作。

(4)跨地區(qū)分發(fā)
復制集可以將數(shù)據(jù)分布在不同的地區(qū)竿拆,這為異地容災提供了很便捷的方法宙拉。比如說兩地三中心容災架構(gòu),我們就可以將復制集內(nèi)兩個節(jié)點放在一個地區(qū)丙笋,將另一個節(jié)點放到另一個地區(qū)中谢澈。

這樣部署方式要注意網(wǎng)絡帶寬煌贴,并且需考慮兩地實際距離。因為一次請求往返一次锥忿,那么每增加150公里就會多1毫秒的延遲牛郑。

(5)oplog便于運維
復制集內(nèi)的oplog存儲了數(shù)據(jù)庫最近時間段內(nèi)的所有寫操作,當業(yè)務出現(xiàn)數(shù)據(jù)異常時敬鬓,通過分析oplog很可能就得到了答案淹朋,并且根據(jù)oplog也可以修復一定的數(shù)據(jù)。

6 尾聲

本文給大家介紹了MongoDB復制集的安裝部署钉答、成員角色础芍、選舉機制、同步原理数尿、特點優(yōu)勢等者甲,相信大家有了一個基本的了解。在下一章我們一起學習MongoDB的分片(sharding)功能砌创,然后搭建一個分片集群,大家可以領略到MongoDB極強的水平擴展能力鲫懒。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嫩实,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子窥岩,更是在濱河造成了極大的恐慌甲献,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颂翼,死亡現(xiàn)場離奇詭異晃洒,居然都是意外死亡,警方通過查閱死者的電腦和手機朦乏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門球及,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人呻疹,你說我怎么就攤上這事吃引。” “怎么了刽锤?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵镊尺,是天一觀的道長。 經(jīng)常有香客問我并思,道長庐氮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任宋彼,我火速辦了婚禮弄砍,結(jié)果婚禮上仙畦,老公的妹妹穿的比我還像新娘。我一直安慰自己输枯,他們只是感情好议泵,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著桃熄,像睡著了一般先口。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瞳收,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天碉京,我揣著相機與錄音,去河邊找鬼螟深。 笑死谐宙,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的界弧。 我是一名探鬼主播凡蜻,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼垢箕!你這毒婦竟也來了划栓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤条获,失蹤者是張志新(化名)和其女友劉穎忠荞,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帅掘,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡委煤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了修档。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碧绞。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖萍悴,靈堂內(nèi)的尸體忽然破棺而出头遭,到底是詐尸還是另有隱情,我是刑警寧澤癣诱,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布计维,位于F島的核電站,受9級特大地震影響撕予,放射性物質(zhì)發(fā)生泄漏鲫惶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一实抡、第九天 我趴在偏房一處隱蔽的房頂上張望欠母。 院中可真熱鬧欢策,春花似錦、人聲如沸赏淌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽六水。三九已至俺孙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間掷贾,已是汗流浹背睛榄。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留想帅,地道東北人场靴。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像港准,于是被迫代替她去往敵國和親旨剥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 何以高可用? 我們以前用Mysql的時候浅缸,經(jīng)常是一臺服務器走天下泞边,如果只是用于學習,是沒有問題的疗杉,但是在生產(chǎn)環(huán)境中...
    zy_think123閱讀 922評論 0 0
  • 關(guān)注我,可以獲取最新知識蚕礼、經(jīng)典面試題以及微服務技術(shù)分享 ??MongoDB復制集(replica set):Mon...
    Ccwwl閱讀 490評論 0 1
  • 為什么需要使用復制集 如果系統(tǒng)只存在一個數(shù)據(jù)庫烟具,當這個數(shù)據(jù)庫發(fā)生故障不可用,那整個系統(tǒng)將不可用奠蹬。Mongodb復制...
    wildfox_9913閱讀 290評論 0 0
  • 1朝聋、副本集/復制集: mongo副本集/復制集是mongo高可用性特征之一,是有自動故障恢復功能的主要集群囤躁。由一個...
    Zhang21閱讀 1,425評論 0 3
  • 最近一段時間冀痕,感覺比較迷茫,早上早起來的時候狸演,沒有及時學習言蛇,就是倒頭大睡,也是因為晚上比較晚起宵距,一直沒有將重心擺正...
    子沫oh閱讀 181評論 0 0