MongoDB是一個面向文檔的數據庫,實際上是一個介於關係型與非關係型之間的數據庫。在MongoDB的世界裏,沒有行(row)的概念,取而代之的是文檔(document)模型,文檔內還能嵌入文檔、數組等,很是靈活。它支持json和bson的數據格式,能夠存儲比較複雜的數據類型,於是也受到廣大DBA的青睞。
在生產環境中,不多用單節點來支撐業務流量,主要是節點性能與數據安全性方面的考慮,MongoDB能夠用副本集來實現數據備份、故障恢復等功能,使用分片技術來使集羣存儲更多的數據,實現更大的負載,也能保證存儲的負載均衡。本文主要介紹的是副本集,有關分片技術會在後面的文章中來進行介紹。linux
副本集是一組運行着mongod進程的服務器,維護着同一個數據集,其中有一個是主服務器(primary),用於處理客戶端請求,其餘節點爲備份服務器(secondary),用於保存數據庫副本。當主服務器掛掉的時候,其餘備份服務器會自動選取一個節點做爲新的主服務器,保證數據安全性、業務可用性。
下面是官方提供的一張架構圖:數據庫
主服務器(primary)接受全部客戶端的讀寫請求(能夠經過配置使得備份服務器也能接受讀請求,在要求數據強一致性的環境中不建議這樣作),主服務器會將對數據的改動記錄到operation log中,即oplog(相似MySQL中的binlog),備份服務器會從主服務器中複製此日誌,而後應用到自身數據庫中,以保證數據與主庫中一致。副本集中各個節點之間會互相發送心跳報文來獲取各個節點的信息。
當主服務器(primary)宕機或者因爲網絡故障與其它節點失去聯繫以後(10秒),其中一個備份服務器會發起選舉流程來將本身提高爲新的主服務器。整個過程通常在一分鐘以內完成。json
在介紹複製原理以前先來看一下整個副本集中會有哪些成員,它們的功能分別是什麼。數組
主服務器用於處理客戶端請求,默認狀況下,客戶端的讀寫請求都到達主服務器。安全
保存數據副本,在主服務器故障時參與選舉。用於保障集羣高可用。默認狀況下備份服務器不接受讀請求。服務器
MongoDB支持一種特殊類型的成員--仲裁者(arbiter)。它不用於保存數據,惟一能施展拳腳的地方就是參與選舉過程,履行投票的義務。若是應用數據比較小,但又想使用副本集來預防數據意外丟失的風險,使用多個數據節點比較浪費資源,這時仲裁者將是不二之選。它能夠做爲一個輕量級的進程運行在一臺配置比較差的服務器上。能夠將其部署在與數據節點不一樣的故障域內,這樣將會加強副本集的健壯性。
在使用仲裁者的時候應該注意如下兩個限制:網絡
在小副本集中,好比三個節點的副本集,使用一個主服務器、一個備份服務器、一個仲裁者,假設主服務器掛掉(連數據都損壞),另一個備份服務器升爲主服務器,這個時候若是新的主服務器也掛掉,而仲裁者又不保存數據,那將是毀滅性的打擊。因此選擇使用仲裁者以前必定要做各方面考慮。架構
以上三種便是一個副本集中主要的成員類型,下面兩種其實也是備份節點,但因爲有一些特別的功能,因此單獨介紹。app
隱藏成員不會做爲一個副本集中的複製源,並且對於客戶端來講,它是不可見的(只有當其優先級爲0時才能設置爲隱藏成員)。不少朋友喜歡將一些性能不那麼強大的服務器隱藏起來。負載均衡
顧名思義,延遲備份節點是比主服務器數據落後某一段時間的節點。此節點的目的是爲了防止出現重大故障,好比DBA朋友小手一抖將某些數據給刪掉了,執行完刪除命令以後頓悟,這個時候主服務器上數據沒了,跑得快的備份服務器上數據也沒有了,但因爲延遲備份節點配置爲落後主服務器一段時間,它上面的數據還在,這個副本集就還能一救。
延遲備份節點的優先級也需爲0,而且爲了保證數據一致性,還須要將延遲備份節點設置爲隱藏成員。
MongoDB的複製功能經過操做日誌oplog來實現。客戶端對數據的更改操做會寫進oplog中,它其實也是一個集合,存放於local數據庫中,比較特殊的是它是一個固定大小的集合(capped collection),也就是說它並非保存了全部對數據庫的更改操做,只是一部分,當記錄佔滿了這個集合時,新的操做日誌會將老的沖掉。副本集中每個成員都會維護一份本身的oplog。
另外,若是將oplog中的某一個操做在節點上執行屢次,其實與執行一次的效果是同樣的。這樣設計的好處是爲了不備份節點同步過程當中主服務器掛掉,重新的主服務器上拷貝過來的oplog中與從舊的主服務器上拷貝過來的oplog有重疊。
MongoDB的數據同步大致也可分爲兩種:初始化同步(Initial Syncing)和增量同步。
咱們也能夠將其理解爲全量同步。通常在副本集中成員啓動後或者新加入成員就會進入這一個階段。
觸發初始化同步有如下三個條件:
整個初始化同步階段包括如下幾個步驟:
當初始化同步完成以後,就進入增量同步階段,備份節點在初始化同步結束後的第一時間就經過tailable cursor來不斷從主服務器上拉取oplog,而後應用到自身的數據庫中。tailable cursor遊標相似linux裏的tailf命令。增量同步會用幾個線程來協做完成,具體過程在之後的文章的介紹。
咱們已經知道副本集中各個節點之間每隔2秒(可經過抓包看出)會發送心跳報文,報文中會包含節點自身的狀態信息,下面來看當作員會有哪些狀態,什麼狀況下會進入這些狀態。
官方將這11個狀態分爲三大類:Core States(包含RPIMARY、SECONDARY和ARBITER)、Other States(包含STARTUP、STARTUP2和RECOVERING)、Error States(包含UNKNOWN、DOWN、REMOVED、ROLLBACK和FATAL)。