練習 MongoDB 操做 —— 複製集篇(四)

複製集(Replication Set),也叫副本集;做用是把一份數據同時保存在多臺服務器上,保證數據的安全,不發生丟失;算法

示例

啓動服務器

經過指定 replSet選項啓動三臺Mongo服務器,端口號是 27017, 27018, 27019;指定加入的複製集名稱爲 demomongodb

./bin/mongod --dbpath master/data --logpath master/log/0923.log --port 27017 --fork --replSet demo

./bin/mongod --dbpath slave1/data --logpath slave1/log/0923.log --port 27018 --fork --replSet demo

./bin/mongod --dbpath slave2/data --logpath slave2/log/0923.log --port 27019 --fork --replSet demo

此時,在三臺服務器上分別鍵入rs.status()命令,均報「未初始化」的錯誤;數據庫

啓動服務器的另一種方式是經過配置文件啓動;舉個例子,這裏的27018以配置文件啓動;安全

配置文件以下所示:服務器

dbpath=/home/mongodb/slave1/data             # 數據存放目錄
 logpath=/home/mongodb/slave1/log/0923.log    # 日誌存放路徑
 pidfilepath=/home/mongodb/slave1/slave1.pid  # 進程文件,方便中止mongodb
 directoryperdb=false      # 爲每個數據庫按照數據庫名創建文件夾存放
 logappend=true                               # 以追加的方式記錄日誌
 replSet=demo                                 # Replication Set 的名稱
 #bind_ip=127.0.0.1                           # 限制只容許某一特定IP來訪問,逗號隔開
 port=27018                                   # 進程所使用的端口號,默認爲27017
 oplogSize=10000          # mongodb操做日誌文件的最大大小。單位爲Mb,默認爲硬盤剩餘空間的5%
 fork=true                                    # 之後臺方式運行進程                  
 noprealloc=false                             # 不預先分配存儲                      
 smallfiles=false                             # 當提示空間不夠時添加此參數

初始化

登入任意一臺機器的 MongoDB 執行,由於是全新的複製集,因此能夠任意進入一臺執行;要是一臺有數據,則須要在有數據上執行;要多臺有數據則不能初始化。app

筆者選擇在27017這臺MongoDB服務器進行初始化spa

rs.initiate({
    _id:'demo',  // 複製集名稱
    members:    // 複製集服務器列表
    [
        {
        _id:0, // 服務器的惟一 ID
        host:'192.168.1.168:27017' // 服務器的地址
        },
        {
        _id:1,
        host:'192.168.1.168:27018'
        },
        {
        _id:2,
        host:'192.168.1.168:27019'
        },
    ]
});

這樣,三臺服務器都加入了demo複製集;此時主節點27017能夠進行讀寫,從節點2701827019不能夠讀寫;全部的寫操做只能在主節點上進行;.net

那如何才能在從節點27018上讀數據呢?在27018上鍵入rs.slaveOk(), 這樣就能夠進行讀操做;命令行

注:能夠經過rs.status()查看複製集狀態;經過rs.config()查看複製集的配置信息;經過db.isMaster()查看是不是主節點信息;unix

添加從節點

先啓動想要添加的從節點服務器,筆者是本地的27020服務器,同時指定相要加入的複製集名稱;

./bin/mongod --dbpath slave3/data --logpath slave3/log/0923.log --port 27020 --fork --replSet demo

主節點27017配置添加:

rs.add('192.168.1.168:27020');

此時,經過鍵入rs.status()能夠看到members成員有四位,包括這臺新的27020從節點服務器;

若是想要移除27020從節點服務器,便可成功從demon複製集中移除該服務器;

rs.remove('192.168.1.168:27020');

模擬主服務器故障

目前環境:

  • 27017: Primary主服務器
  • 27018: SECONDARY從服務器
  • 27019: SECONDARY從服務器

在系統命令行上,手動drop掉主服務器

lsof -i:27017 | sed '1d' | while read line
do
    echo $line | awk '{print $2}' | xargs kill -9
done

或者在主服務器上執行下面的語句

db.shutdownServer()

此時,在經過rs.status()查看環境

  • 27017: 離線(not reachable/healthy
  • 27018: SECONDARY從服務器
  • 27019: Primary主服務器

這裏,爲何在主服務器27017服務器掛了以後,會選擇27019作新的主服務器呢,這是由MongoDB服務器內部的多數投票算法,即每臺服務器會爲secondary從節點服務器進行投票,票數多的從節點服務器會成爲新的Primary服務器;

筆者這裏很幸運,兩臺從節點服務器2701827019都選擇了27019做爲新的從節點服務器;另一種多是 2701827019各得一票,這樣會致使沒法選舉出新Primary服務器; 因此建議複製集的服務器數目爲奇數,若是碰巧是偶數,能夠添加一臺仲裁節點服務器;

添加仲裁節點

仲裁節點是一種特殊的節點,它自己並不存儲數據,主要的做用是決定哪個從節點在主節點掛掉以後提高爲主節點,因此客戶端不須要鏈接此節點。

仲裁節點服務器啓動,

./bin/mongod --dbpath arbiter/data --logpath arbiter/log/0923.log --port 27021 --fork --replSet demo

主服務器的配置上添加仲裁節點信息:

demo:PRIMARY> rs.addArb('192.168.1.168:27021')

手動設置Primay服務器

27017服務器重啓;

此時,在經過rs.status()查看環境

  • 27017: SECONDARY從服務器
  • 27018: SECONDARY從服務器
  • 27019: Primary主服務器
  • 27021: Arbiter仲裁服務器

如何能將當前的服務器從27019切換回27017服務器呢?

經過修改priority的值來實現(默認的優先級是1(0-100),priority的值設的越大,就優先成爲主);

27019主節點上執行

Primary > config=rs.conf()
Primary > config.members[0].priority = 3
Primary > rs.reconfig(config)

注意:第2步members大括號裏面的成員和_id是沒有關係的,而是rs.conf查出來節點的數值的順序;

原理

主節點的操做記錄成爲oplogoperation log)。 oplog存儲在一個系統數據庫local的集合oplog.rs中,這個集合的每一個文檔都表明主節點上執行的一個操做。咱們從新向主數據庫服務器中插入一條數據,而後查看這個集合能夠看到:

use local
db.getCollection('oplog.rs').find({})

文檔中的字段含義:

  • ts:8字節的時間戳,由4字節 unix timestamp + 4字節自增計數表示
  • h: 未知
  • v: 未知
  • op:操做類型,i表示insertu表示updated表示deletec表示db cmdn表示no op, 空操做,其會按期執行以確保時效性;
  • ns:操做所在的namespace
  • o:操做所對應的document,即當前操做的內容(好比更新操做時要更新的的字段和值)

從服務器會按期從主服務器中獲取oplog記錄,而後在本機上執行!

對於存儲oplog的集合,MongoDB採用的是固定集合,也就是說隨着操做過多,新的操做會覆蓋舊的操做!這樣作也是有道理的,否則,這個集合佔用的空間就沒法估算了!咱們在啓動服務時,能夠經過選項--oplogSize來指定這個集合的大小,單位是MB,在Windows平臺下,默認MongoDB會使用數據庫安裝分區可用空間的5%做爲這個集合的大小!

附錄

屬性說明

' 成爲Primary 對客戶端可見 參與同步 延遲同步 複製數據
Primary '
Secondary ' '
Hidden ' ' '
Delayed '
Arbiters ' ' ' '
Non-Voting ' '

參考閱讀

相關文章
相關標籤/搜索