MongoDB 副本集(Replica Set)是有自動故障恢復功能的主從集羣,有一個Primary節點和一個或多個Secondary節點組成。副本集的工作模式如下圖:
副本集中數據同步過程:
Primary節點寫入數據,Secondary通過讀取Primary的oplog得到複製信息,開始複製數據並且將複製信息寫入到自己的oplog。如果某個操作失敗,則備份節點停止從當前數據源複製數據。如果某個備份節點由於某些原因掛掉了,當重新啓動後,就會自動從oplog的最後一個操作開始同步,同步完成後,將信息寫入自己的oplog,由於複製操作是先複製數據,複製完成後再寫入oplog,有可能相同的操作會同步兩份,不過MongoDB在設計之初就考慮到這個問題,將oplog的同一個操作執行多次,與執行一次的效果是一樣的。
簡單的說就是:
當Primary節點完成數據操作後,Secondary會做出一系列的動作保證數據的同步:
1:檢查自己local庫的oplog.rs集合找出最近的時間戳。
2:檢查Primary節點local庫oplog.rs集合,找出大於此時間戳的記錄。
3:將找到的記錄插入到自己的oplog.rs集合中,並執行這些操作
環境搭建(以下爲linux系統,windows系統同理)
1:下載安裝程序,地址爲:https://www.mongodb.org/downloads 根據需要下載合適的版本
2:解壓,進入bin目錄,創建配置文件(否則每次啓動時都要輸入各個參數):mongod.conf
輸入配置內容(僅供參考,各個參數請以實際需求調整):
配置參數
##端口配置 net: port: 27017 ##日誌文件 systemLog: destination: file path: "mongod.log" logAppend: true storage: ##存儲引擎 engine: wiredTiger ##數據文件存儲位置 dbPath: /home/soft/mongodb-3.2.1/data ##數據會先寫入日記文件,然後定時刷新到磁盤,生產環境必須打開 journal: enabled: true #enable at production wiredTiger: engineConfig: cacheSizeGB: 1 statisticsLogDelaySecs: 3600 journalCompressor: snappy directoryForIndexes: true collectionConfig: blockCompressor: snappy indexConfig: prefixCompression: true processManagement: ##以後臺進程運行 fork: true replication: ##副本集oplog大小 oplogSizeMB: 2048 ##副本集名稱 replSetName: candao_qc secondaryIndexPrefetch: all enableMajorityReadConcern: false |
(啓動前,記得有創建了dbPath: /home/soft/mongodb-3.2.1/data 這個目錄)
3:以同樣方式配置好其他2臺服務器(官方推薦副本集成員爲3或奇數個),分別運行./mongod -f mongod.conf 以啓動mongodb。此時各個機器仍爲單機模式,需要運行mongo程序進行初始化(且只能以此方式初始化)
4:在任意一臺服務器上運行./mongo 輸入命令:
初始化副本集
var conf = { "_id" : "candao_qc" , members : [{ "_id" :0, //機器在副本集中的ID "host" : "192.168.86.73:27017" , //本機的IP地址 "priority" :1, //優先級(最高優先級的節點總是會被選爲主節點,默認值爲1) },...] } rs.initiate(conf); //現在Mongo的primary中的priority是配置最高的,這樣把primary停掉,再其他副本集種推舉primary,當再把剛剛停掉的primary再次啓動,由於它的priority是最高的,它會再次推舉當選爲primary. //只需要在任意一臺服務器上進行執行,然後,這臺服務器會把這個配置信息推送到其他服務器上 |
更多配置參數,請訪問:https://docs.mongodb.org/manual/reference/replica-configuration/
5:輸入 rs.status() 以查看副本集狀態,如果沒有錯誤,副本集會在短時間內初始化成功,正常的輸出會是這樣的:
有時可能需要修改副本集的配置信息,步驟如下:
1.在主機器上運行mongo 程序
2.輸入 var conf = rs.conf();
3.conf.members[n] = {.........各種json參數 }//和初始化一樣修改
4.rs.reconfig(conf, {force:true});
5.rs.status()查看副本集狀態,是否修改成功
mongo的數字是從0開始,和java中的起始位置一樣。
注意
在複製集運行的過程中,難免會遇到需要重啓節點的場景,比如複製集版本升級、節點維護等,在重啓節點的過程中,建議不要直接shutdown Primary
,這樣可能導致已經寫入primary但未同步到secondary的數據丟失
,過程類似如下:
shutdown Primary (shutdown會等待Secondary oplog追到10s以內)
Primary退出後,剩餘的節點選舉出一個新的Primary(複製集只包含1或2節點例外)
Primary重新啓動,因爲當前複製集已經有了新的Primary,這個Primary將以Secondary的角色運行。
從新的Primary同步的過程中,發現自己有
無效的oplog
,會先進行rollback。(rollback的數據只要不超過300M是可以找回的)
如果想不丟數據重啓複製集,更優雅的打開方式應該是這樣的
逐個重啓複製集裏所有的Secondary節點
對Primary發送stepDown命令,等待primary降級爲Secondary
重啓降級後的Primary
注意:如果Secondary的同步一直追不上Primary,步驟2可能會失敗,這時應該重試步驟2直到stepDown成功;步驟2也可以通過調用replSetReconfig命令,來調整節點優先級來實現,讓Secondary擁有更高的優先級,然後等待Primary降級爲Secondary。
所以連接複製集一定不要直連Primary,否則在節點角色切換時不能正確容錯,服務高可用無法保證。
#關閉
mmm:PRIMARY> use admin
switched to db admin
mmm:PRIMARY> db.shutdownServer()