MongoDB 復制


1.主從復制

主從復制是MongoDB最常用的復制方式,這種方式很靈活.可用於備份,故障恢復,讀擴展等.

最基本的設置方式就是建立一個主節點和一個或多個從節點,每個從節點要知道主節點的地址.

運行mongod --master就啟動了主服務器,運行mongod --slave --source master_address

就啟動了從服務器.其中master_address是主節點的地址.

生產環境下會有多台服務器的,這里用一台機器來測試.

首先給主節點建立數據目錄:

mongod --dbpath "F:\mongo\dbs\master" --port 10000 --master

--logpath "F:\mongo\logs\master\MongoDB.txt" --rest

設置從節點:

mongod --dbpath "F:\mongo\dbs\slave" --port 10001 --slave --source 127.0.0.1:10000 --logpath "F:\mongo\logs\slave\MongoDB.txt" --rest

現在向主節點服務器添加數據:

在從節點服務器查詢數據:

所有的從節點都從主節點復制內容.

一個集群中有多少個從節點並沒有明確的限制.最好是不超過12個從節點數據庫的集群.

 

2.主從復制的選項

--only

在從節點上指定只復制特定的某個數據庫(默認是復制所有數據庫)

--slavedelay

用在從節點上,當應用主節點的操作時,從節點增加延時復制(單位秒).這樣就能輕松設置延時從節點,這種節點對用戶

無意中刪除重要文檔或者插入垃圾數據等有防護作用,這些不良操作都會被復制到所有的從節點上,通過延時執行操作,

可以有個恢復的時間差.

--fastsync

以主節點的數據快照為基礎啟動從節點.如果數據目錄一開始是主節點的數據快照,從節點用這個選項啟動要比

做完整的同步快的多.

--autoresync

如果從節點與主節點不同步了,則自動重新同步

--oplogsize

主節點oplog的大小(單位MB)

 

3.添加及刪除源

啟動從節點時可以用--source指定主節點,也可以在shell中配置這個源.

如上例主節點綁定了127.0.0.1:10000.啟動從節點時可以不添加源,而后向source集合添加主節點信息:

mongod --dbpath "F:\mongo\dbs\slave" --port 10001 --slave --logpath "F:\mongo\logs\slave\MongoDB.txt" --rest

可以在shell中,將127.0.0.1:10000作為源添加到從節點上:

use local

db.sources.insert({"host":"127.0.0.1:10000"})

看看從屬節點的日志,會發現它與127.0.0.1:10000同步.

如果在生產環境下,想更改從節點的配置,改用refactor.com為源,這可以這樣做:

db.sources.insert({"host":"refactor.com"})
db.sources.remove({"host":"127.0.0.1:10000"})

可以把sources集合當作普通的集合進行操作.

要是切換的兩個主節點有相同的集合,MongoDB或嘗試合並,但不能保證正確合並.要是使用一個從節點對應

多個不同的主節點,最好在主節點上使用不同的命名空間

 

4.副本集

副本集(Replica Set)就是有自動故障恢復功能的主從集群.主從集群和副本集最明顯的區別是副本集沒有固定的"主節點",

整個集群會選舉出一個"主節點",當其不能工作時則變更到其他節點.副本集總會有一個活躍節點(primary)和

一個或多個備份節點(secondary).

副本集可以在活躍節點有問題時自動切換.

 

5.初始化副本集

設置副本集比設置主從集群稍微復雜一點.

先給副本集起個名稱,是為了易於與別的副本集區分,也是為了方便將整個集合視為一個整體,這里取名:refactor

啟動服務器--replSet的作用是讓服務器知道這個"refactor"副本集還有別的同伴 位置在 refactor/127.0.0.1:10001

mongod --dbpath "F:\mongo\dbs\master" --port 10000 --replSet refactor/127.0.0.1:10001 --logpath "F:\mongo\logs\master\MongoDB.txt" --rest

以同樣的方式啟動另一台:

mongod --dbpath "F:\mongo\dbs\slave" --port 10001 --replSet refactor/127.0.0.1:10000 --logpath "F:\mongo\logs\slave\MongoDB.txt" --rest

如果想要添加第三台,兩種方式:

mongod --dbpath "F:\mongo\dbs\slave1" --port 10002
--replSet refactor/127.0.0.1:10000
--logpath "F:\mongo\logs\slave1\MongoDB.txt" --rest

mongod --dbpath "F:\mongo\dbs\slave1" --port 10002
--replSet refactor/127.0.0.1:10000,127.0.0.1:10001
--logpath "F:\mongo\logs\slave1\MongoDB.txt" --rest

副本集有自動檢測功能:在其中指定單台服務器后,MongoDB就會自動搜索並連接其余的節點.

 

在shell中初始化副本集

 

在shell,連接其中一個服務器,初始化命令只能執行一次:

use admin
db.runCommand(
  {
    "replSetInitiate":
    {
      "_id":"refactor",//副本集的名稱
      "members"://副本集中的服務器列表
      [
        {
          "_id":1,//每個服務器的唯一id
          "host":"127.0.0.1:10000"//指定服務器的主機
        },
        {
          "_id":2,
          "host":"127.0.0.1:10001"
        }
      ]
    }
  }
)

在活躍節點中添加數據:

在備份節點查詢,會出現

error: { "$err" : "not master and slaveok=false", "code" : 13435 }錯誤.

執行如下語句:

db.getMongo().setSlaveOk()

 

6.副本集中的節點

任何時間,集群中只有一個活躍節點,其他的都是備份節點.活躍節點實際上是活躍服務器,指定的活躍節點可以隨時間而改變.

有幾種不同類型的節點可以存在與副本集中

standard 標准節點

這是常規節點,它存儲一份完整的數據副本,參與選舉投票有可能成為活躍節點

passive 被動結點

存儲了完整的數據副本,參與投票,不能成為活躍節點

arbiter 仲裁者

仲裁者只能參與投票,不接收復制的數據,也不能成為活躍節點.

標准節點和被動節點之間的區別僅僅是數量的差別,每個參與節點(非仲裁)有優先權.

優先權按照優先值從大到小.

在節點配置中修改priority鍵,來配置標准節點或者被動節點.

>members.push({"_id":3,"host":"127.0.0.1:10002","priority":40})

默認優先級為1,可以是0-1000(含)

"arbiterOnly"鍵可以指定仲裁節點

>members.push({"_id":4,"host":"127.0.0.1:10003","arbiterOnly":true})

備份節點會從活躍節點抽取oplog,並執行操作,就像活躍備份系統中的備份服務器一樣.活躍節點也會寫操作

到自己的本地oplog.oplog中的操作包含嚴格遞增的序號,這個序號來判定數據的時效性.

 

7.故障切換和活躍節點選舉

如果活躍節點出現故障,其余節點會選一個新的活躍節點.選舉過程可以由任何非活躍節點發起,新的活躍節點由

副本集中的大多數選舉產生.仲裁節點也參與選舉,避免出現僵局.新的活躍節點將是優先級最高的節點,優先級相同

這數據較新的節點獲勝.

不論活躍節點何時變化,新的活躍節點的數據就被假定為系統的最新數據.對其他幾點(原來的活躍節點)的操作都會

回滾,即便是之前的活躍節點已經恢復工作了.為了完成回滾,所有節點連接新的活躍節點后重新同步.這些節點會查看

自己的oplog,找出自重活躍節點沒有的操作,然后向活躍節點請求這些操作影響的文檔最新副本.正在執行重新同步的

節點被視為恢復中,在完成這個過程之前不能成為活躍節點的候選者.

 

8.在從服務器上執行操作

從節點的主要作用是作為故障恢復機制,以防主節點數據丟失或停止服務.

從節點可以用作備份數據源,可以用來擴展讀取性能,或者進行數據處理.

 

9.讀擴展

用MongoDB擴展讀取的一種方式是將查詢放在從節點上.這樣,主節點的負載就減輕了.一般來說,當負載是讀取密集型

時,這是很好的方案.要是謝密集型,則要用分片來進行擴展.

使用從節點來擴展MongoDB的讀取有個要點,就是數據復制並不同步,也就是說在主節點插入和更新數據后,

有片刻從節點的數據不是最新的.在考慮用查詢從節點完成請求時,應注意.

擴展讀取本身很簡單,像往常一樣設置主從復制,連接從服務器處理請求.唯一的技巧是有個特殊的查詢選項,告訴

從服務器是否可以處理請求(默認是不可以的).這個選項是slaveOkay,所有的MongoDB驅動程序都提供了

一種機制來設置它.有些驅動程序還提供工具使得請求分布到從節點的過程自動化,但這個過程隨驅動程序的

不同而不同.

 

10.用從節點做數據處理

從節點的另外一個用途是作為一種機制來減輕密集型處理的負載,或作為聚合,避免影響主節點的性能.用--mster

參數啟動一個普通的從節點.同時使用--slave和--master有點矛盾,這意味着如果能對從節點進行寫入,像往常

一樣查詢,就把它作為一個普通的MongoDB主節點就行了,向從節點插入數據不會同步到主節點中.

從節點還是會不斷的從真正的主節點復制數據.

這樣,就可以對從節點執行阻塞操作也不影響主節點的性能.

用這種技術的時候,一定要確保不能對正在復制主節點數據的從節點上的數據庫進行寫入.從節點不能恢復這些操作,

就不能映射主節點.

 

11.工作原理

MongoDB的復制至少需要兩個服務器或節點.其中一個是主節點,負責處理客戶端請求,其他都是從節點

負責映射主節點的數據.主節點記錄在其上執行的所有操作.從節點定期輪訓主節點獲得這些操作,然后對自己的

數據副本執行這些操作.由於和主節點執行了相同的操作,從節點就能保持與主節點的數據同步.

 

oplog

主節點的操作記錄成為oplog(operation log).oplog存儲在一個特殊的數據庫中,叫做local.

oplog就在其中的oplpg.$main集合里面.oplpg中的每個文檔都代表主節點上執行的一個操作.

> db.oplog.$main.findOne()
{
  "ts" : {
      "t" : 1342705298000,
      "i" : 11
     },
  "op" : "n",
  "ns" : "",
  "o" : {

      }
}

"ts" 

操作的時間戳.時間戳是一種內部類型,用於跟蹤操作執行的時間,由4個字節的時間戳和4個自己的遞增計數器構成

"op"

操作類型,只有一個字節.("i"代表插入)

"ns" 

執行操作的命名空間(集合名)

"o"

進一步執行要執行操作的文檔,對插入來說,就是要插入的文檔.

oplog只記錄改變數據庫狀態的操作.如查詢不會存儲在oplog中,這是因為oplog只是作為從節點與

主節點保持數據同步的機制.

存儲在oplog中的操作也不是完全和主節點的操作已於一樣的.這些操作在存儲之前先要做等冪變換,也就是說

這些操作可以在服務器端多次執行,只要順序是對的,就不會有問題.如使用"$inc"執行的增加更新操作,

會變成"$set"操作.

oplog存儲在固定集合中.由於新操作也會存儲在oplog中,他們會自動替換舊的操作.這樣能保證oplog不能

超過預先設定的大小.啟動服務器時可以用--oplogsize指定這個大小,單位是MB.默認情況下,64位的實例將會使用

oplog 5%的可用空間.這個空間將在local數據庫中分配,並在服務器啟動時預先分配.

 

12.同步

從節點第一次啟動時,會對主節點數據進行完整的同步.從節點復制主節點上的每個文檔,很耗資源.同步完成后,

從節點開始查詢主節點的oplog並執行這些操作,以保證數據是最新的.

如果從節點的操作和主節點的相差很遠,從節點就跟不上同步了.跟不上同步的從節點無法一直追趕主節點.因為

主節點oplog的所有操作太新了.從節點發生了宕機或着疲於應付讀取時會出現這個情況,也會在執行完完整同步以后

反生類似的事,因為只要同步的時間太長,同步完成時,oplog可能已經操作了很多.

從節點跟不上同步時,復制就會停下來,從節點需要重新做完整的同步.可以用{"resync":1}命令手動執行從新同步,

也可以在啟動從節點時使用--autoresync選項讓其自動重新同步,重新同步的代價很高,應盡量避免,方法是配置

足夠大的oplog,配置足夠大的oplog能存放相當長的時間操作記錄.大的oplog會占用更多的磁盤空間,則需要權衡一下.

默認的oplog大小是剩余磁盤空間的5%.

 

13.復制狀態和本地數據庫

本地數據庫 用來存儲所有內部復制狀態,子節點和從節點都有.本地數據庫 的名字是local,其內容不會被復制.這樣能

確保一個MongoDB服務器只有一個local數據庫.local數據庫不限於存放MongoDB的內部狀態,如果有不想被復制的文檔

也可以將其存在local數據庫.

主節點上的復制狀態還包括從節點的列表(從節點連接主節點時會自行handshake命令進行握手),這個列表存放在

slaves集合中.

從節點也在local數據庫中存放狀態.在me集合中存放從節點的唯一標識符,在sources集合中存放源或節點的列表.

主節點和從節點都跟中從節點的更新情況,這是通過存放在"syncedTo"中的時間戳來完成的.每次從節點查詢主節點

的oplog時,都會用"syncedTo"來確定那些操作需要執行,或者查看是否已經跟不上同步了.

 

14.阻塞復制

開發者可以用gerLastError的"w"參數來確保數據的同步性.這里運行gerLastError會進入阻塞狀態,知道n個

服務器復制了嘴型的寫入操作為止

db.runCommand({"gerLastError":1,w:N})

如果沒有N,或者小於2命令就會立刻返回,如果N等於2,主節點要等到至少一個從節點復制了上個操作才會響應命令

主節點本身也包括在N里面.主節點使用local.slaves中存放的"syncedTo"信息跟蹤從節點的更新情況.

指定"w"選項后,還可以使用"wtimeout"選項,表示以毫秒為單位的超時,gerLastError就能在上一個操作復制到N個

節點超時返回錯誤(默認情況下沒有超時)

阻塞復制會導致寫操作變慢,尤其"w"的值比較大時.實際上,對重要操作將其值設為2或3就能效率和安全兼備了.

 

15.管理

MongoDB提供了工具來查看復制的狀態,當連接到主節點后,使用

> db.printReplicationInfo()
configured oplog size: 944.1375732421875MB//oplog的大小大致為944M
log length start to end: 3395secs (0.94hrs)//最大大約能放置3395秒的操作.
oplog first event time: Thu Jul 19 2012 21:41:58 GMT+0800
oplog last event time: Thu Jul 19 2012 22:38:33 GMT+0800
now: Thu Jul 19 2012 22:38:38 GMT+0800


oplog的長度至少要能滿足一次完整的從新同步.

當連接到從節點時,可以用printSlaveReplicationInfo得到從節點的一些信息

> db.printSlaveReplicationInfo()
source: 127.0.0.1:10000
syncedTo: Thu Jul 19 2012 22:42:13 GMT+0800
= 7 secs ago (0hrs)//數據的滯后時間為7秒

 

如發現oplog的大小不合適,最簡單的做法就是停掉主節點,刪除local數據庫中的文件,用新的設置(--oplogsize)

重新啟動.為大型的oplog預分配空間很耗時,且可能導致主節點停機時間增加,所以盡可能手動預分配數據文件.

重啟主節點后,所有從節點得用--autoresync重啟,否則需要手動從新同步.

 

16.復制的認證問題

如果在復制中使用了認證,還要做一些配置,似的從節點能訪問主節點的數據.在主節點和從節點上都需要在

local數據庫添加用戶,每個節點的用戶名和口令都是相同的.local數據庫的用戶類似admin數據庫中的用戶,

能夠讀寫整個服務器.

從節點連接主節點時,會用存儲在local.system.users中的用戶進行認證.最此嘗試"refactor"用戶,如沒有此用戶,則用

local.system.users中的第一個可用用戶.所以,按照如下步驟配置主節點和從節點,用戶靠的密碼替換password,

就能配置認證復制了:

use local

addUser("refactor","password")

從節點之后就可以復制主節點了.

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM