閱讀631 返回首頁    go 阿裏雲 go 技術社區[雲棲]


從MongoDB Replica Set HA 看分布式係統讀寫一致性問題

副本集基礎
Replica Set是mongodb提供的一個去中心化的備份模式(同時mongodb還提供了主從部署和分片模式),每個mongod都可以是master,且副本集內會自動選舉出一個primary,其他都暫時為seconary,primary掛掉後會自動選舉出新的primary。副本集內所有mongod存儲的都是數據全集,secondary節點會從primary同步數據操作以保證自己的數據up-to-date。副本集有自己的選舉機製,相對是一種比較簡單的選舉,根據心跳、權重等因素選取一個可用的節點來做primary。

副本集  
副本集裏隻有一個primary可以寫,保持嚴格的一致性(primary是嚴格一致性,secondary是最終一致性)。primary把log寫在oplog裏,secondary的節點異步拷貝primary的oplog(為了便利,副本集內各自的oplog都可以互相獲得和拷貝),將operation作用在自己的數據集上。oplog裏對於數據集的操作,都是冪等的。mongod啟動的時候會產生一個默認大小的oplog,想要改變oplog size需要在啟動前設置,啟動後再設置需要走另一個流程,比較麻煩些。
如果副本集是偶數的話,可以加一個arbiter,他不維護數據,隻參加投票。member還有別的狀態,如delayed memberhidden member
clients默認讀的是primary的數據集,讀secondary的數據集可以另外指定。既然secondary是根據oplog對自己的數據集異步實施operation的,就一定存在延遲。
副本集數據同步存在兩種方式:
1. 初始化同步:對於新的沒有數據的member或者丟失了一部分曆史記錄的缺失數據集,拷貝現有副本集內某個member的整份數據。整個過程流程為先clone數據,然後apply all changes,最後建索引。
2. 不間斷同步:一般secondary都是從primay同步(定時ping primary查看state)。
為了保證續航性(Durability),在單線程上提供了journaling,每次寫需要先寫進journal,然後再到數據集(默認需要64bit的mongodb2.0以上版本才有journal)。
對於多線程的Replication而言,mongodb用多線程批量寫來保證並發,批處理按namespace分組,每個namespace裏的並發寫是有序的。當使用批量寫的時候,mongodb不允許read。

Journaling
使用journaling的時候,mongodb先把寫操作記錄存在內存裏,實施在journal裏。默認journal路徑為/data/db,啟動mongod的時候會預分配一定大小,裏麵的journal files是append-only的。jfile的最大容量可以設置,當jfile大於1G時候,會創建新jfile。jfile的路徑也可以另外指定,指定到別的文件係統加快讀寫速度。一旦mongodb完成了所有寫操作,這些jfile就會被刪除。
簡單描述下從內存到jfile再到disk數據集的過程。Journalling提供三種視圖,shared views,private views(隻讀)和?。他們權限不同。mongodb用批處理的方式,先把內存裏的寫操作以private view的方式刷到jfile裏,然後再把jfile裏的內容以share view的方式flush到磁盤上,此時數據集得以更新到最新。

總結
Mongodb通過副本集的方式提高可用性,一方麵副本集是去中心化的模式,能夠自動檢測選舉新的primary,同步節點之間的數據,通過mongos路由路口,保證對client端透明;另一方麵副本集存儲數據全集,隻要你能容忍他的最終一致性,secondary節點一樣可以提供read。在Mongodb2.0之後的版本加入了journaling這個東西,更加增強了可靠性,保證當你的primary掛掉之後,前麵幾次修改操作仍然被記錄在journal中,可以被還原也可以被撤銷,避免數據不一致或弄髒的情況。journaling其實類似很多分布式係統中采用的做法,涉及到內存,涉及到先寫到journal中,寫成功後再執行到真的數據集中。
本文嚐試通過mongodb副本集的分析,對分布式係統讀寫一致性問題做簡單的理解,理解有誤之處還請多包涵。

(全文完)

最後更新:2017-04-03 14:54:06

  上一篇:go 【NET】--基本常識
  下一篇:go HttpOperater-模擬HTTP操作類