MongoDB集羣運維筆記

 

前面的文章介紹了MongoDB副本集和分片集羣的作法,下面對MongoDB集羣的平常維護操做進行小總結:node

        MongDB副本集故障轉移功能得益於它的選舉機制。選舉機制採用了Bully算法,能夠很方便從分佈式節點中選出主節點。Bully算法是一種協調者(主節點)競選算法,主要思想是集羣的每一個成員均可以聲明它是主節點並通知其餘節點。別的節點能夠選擇接受這個聲稱或是拒絕並進入主節點競爭。被其餘全部節點接受的節點才能成爲主節點。節點按照一些屬性來判斷誰應該勝出。這個屬性能夠是一個靜態ID,也能夠是更新的度量像最近一次事務ID(最新的節點會勝出)。
算法

1)MongoDB集羣的節點數量
       官方推薦MongoDB副本集的成員數量最好爲奇數,且選舉要求參與的節點數量必須大於成員數的一半。假設MongoDB集羣有3個節點,那麼只要有2個節點活着就能夠選舉;若是有5個,那麼活3個節點就能夠選舉;若是有7個節點,那麼活4個就能夠選舉.....
MongoDB集羣最多容許12個副本集節點,其中最多7個節點參與選舉。這是爲了減小心跳請求的網絡流量和選舉話費的時間,心跳每2秒發送一次。
MongoDB集羣最多12個副本集節點,是由於不必一份數據複製那麼多份,備份太多反而增長了網絡負載和拖慢了集羣性能;而最多7個節點參與選舉是由於內部選舉機制
節點數量太多就會致使1分鐘內還選不出主節點,凡事只要適當就好。sql

2)MongoDB心跳
       整個MongoDB集羣須要保持必定的通訊才能知道哪些節點活着哪些節點掛掉。MongoDB節點會向副本集中的其餘節點每兩秒就會發送一次pings包,若是其餘節點在10秒
鍾以內沒有返回就標示爲不能訪問。每一個節點內部都會維護一個狀態映射表,代表當前每一個節點是什麼角色、日誌時間戳等關鍵信息。若是是主節點,除了維護映射
表外還須要檢查本身可否和集羣中內大部分節點通信,若是不能則把本身降級爲secondary只讀節點。mongodb

3)MongoDB同步
       MongoDB副本集同步分爲初始化同步和keep複製。初始化同步指全量從主節點同步數據,若是主節點數據量比較大同步時間會比較長。而keep複製指初始化同步事後,
節點之間的實時同步通常是增量同步。初始化同步不僅是在第一次纔會被處罰,有如下兩種狀況會觸發:
       [1]  secondary第一次加入,這個是確定的。
       [2]  secondary落後的數據量超過了oplog的大小,這樣也會被全量複製。數據庫

=============================================================================================
何爲oplog?
       oplog(應用日誌)保存了數據的操做記錄,oplog主要用於副本,secondary複製oplog並把裏面的操做在secondary執行一遍。可是oplog也是mongodb的一個集合,保存在local.oplog.rs裏;然而這個oplog是一個capped collection,也就是固定大小的集合,新數據加入超過集合的大小會覆蓋,因此這裏須要注意,跨IDC的複製要設置合適的oplogSize,避免在生產環境常常產生全量複製。oplogSize能夠經過--oplogSize設置大小,對於Linux 和Windows 64位,oplog size默認爲剩餘磁盤空間的5%centos

       在mongodb主從結構中,主節點的操做記錄成爲oplog(operation log)。oplog存儲在一個系統數據庫local的集合oplog.$main中,這個集合的每一個文檔都表明主節點上執行的一個操做。從服務器會按期從主服務器中獲取oplog記錄,而後在本機上執行!對於存儲oplog的集合,MongoDB採用的是固定集合,也就是說隨着操做過多,新的操做會覆蓋舊的操做!主節點經過--oplogSize設置oplog的大小(主節點操做記錄存儲到local的oplog中)
=============================================================================================數組

       MongoDB同步也並不是只能從主節點同步,假設集羣中3個節點,節點1是主節點在IDC1,節點二、節點3在IDC2,初始化節點二、節點3會從節點1同步數據。後面節點二、節點3會使用就近原則從當前IDC的副本集中進行復制,只要有一個節點從IDC1的節點1複製數據。設置mongodb、同步還要注意如下幾點:
       [1] secondary不會從delayed(延遲)和hidden(隱藏)成員上覆制數據。
       [2] 要是須要同步,兩個成員的buildindexes必需要相同不管是不是true和false。
       [3] buildindexes主要用來設置是否這個節點的數據用於查詢,默認爲true。
       [4] 若是同步操做30秒都沒有反應,則會從新選擇一個節點進行同步。緩存

4)Mongodb主節點的讀寫壓力過大如何解決?
       在系統早期,數據量還小的時候不會引發太大的問題,可是隨着數據量持續增多,後續早晚會出現一臺機器硬件瓶頸問題的。而MongoDB主打的就是海量數據架構,它不能解決海量數據怎麼行! mongodb的"分片"就是用來解決這個問題的。安全

       傳統數據庫怎麼作海量數據讀寫?其實一句話歸納:分而治之。以下TaoBao早期的一個架構圖:bash

      上圖中有個TDDL,是TaoBao的一個數據訪問層組件,它主要的做用是SQL解析、路由處理。根據應用的請求的功能解析當前訪問的sql判斷是在哪一個業務數據庫、哪一個表訪問查詢並返回數據結果。具體如圖:

       說了這麼多傳統數據庫的架構,那NoSQL怎麼去作到了這些呢?MySQL要作到自動擴展須要加一個數據訪問層用程序去擴展,數據庫的增長、刪除、備份還須要程序去控制。一但數據庫的節點一多,要維護起來也是很是頭疼的。不過MongoDB全部的這一切經過它本身的內部機制就能夠搞定的了。以下圖看看MongoDB經過哪些機制實現路由、分片:

從圖中能夠看到有四個組件:mongos、config server、shard、replica set
      mongos,數據庫集羣請求的入口,全部的請求都經過mongos進行協調,不須要在應用程序添加一個路由選擇器,mongos本身就是一個請求分發中心,它負責把對應的數據請求請求轉發到對應的shard服務器上。在生產環境一般有多mongos做爲請求的入口,防止其中一個掛掉全部的mongodb請求都沒有辦法操做。

      config server,顧名思義爲配置服務器,存儲全部數據庫元信息(路由、分片)的配置。mongos自己沒有物理存儲分片服務器和數據路由信息,只是緩存在內存裏,配置服務器則實際存儲這些數據。mongos第一次啓動或者關掉重啓就會從 config server 加載配置信息,之後若是配置服務器信息變化會通知到全部的 mongos 更新本身的狀態,這樣      mongos 就能繼續準確路由。在生產環境一般有多個 config server 配置服務器,由於它存儲了分片路由的元數據,這個可不能丟失!就算掛掉其中一臺,只要還有存貨, mongodb集羣就不會掛掉。

      shard,這就是傳說中的分片了。上面提到一個機器就算能力再大也有天花板,就像軍隊打仗同樣,一我的再厲害喝血瓶也拼不過對方的一個師。俗話說三個臭皮匠頂個諸葛亮,這個時候團隊的力量就凸顯出來了。在互聯網也是這樣,一臺普通的機器作不了的多臺機器來作,以下圖:

      一臺機器的一個數據表 Collection1 存儲了 1T 數據,壓力太大了!在分給4個機器後,每一個機器都是256G,則分攤了集中在一臺機器的壓力。也許有人問一臺機器硬盤加大一點不就能夠了,爲何要分給四臺機器呢?不要光想到存儲空間,實際運行的數據庫還有硬盤的讀寫、網絡的IO、CPU和內存的瓶頸。在mongodb集羣只要設置好了分片規則,經過mongos操做數據庫就能自動把對應的數據操做請求轉發到對應的分片機器上。在生產環境中分片的片鍵可要好好設置,這個影響到了怎麼把數據均勻分到多個分片機器上,不要出現其中一臺機器分了1T,其餘機器沒有分到的狀況,這樣還不如不分片!

     replica set(副本集),其實上圖4個分片若是沒有 replica set 是個不完整架構,假設其中的一個分片掛掉那四分之一的數據就丟失了,因此在高可用性的分片架構還須要對於每個分片構建 replica set 副本集保證分片的可靠性生產環境一般是 2個副本 + 1個仲裁(即一主一從一仲裁)

5)MongoDB 複製集節點增長移除及節點屬性配置
複製集(replica Set)或者副本集是MongoDB的核心高可用特性之一,它基於主節點的oplog日誌持續傳送到輔助節點,並重放得以實現主從節點一致。再結合心跳機制,當感知到主節點不可訪問或宕機的情形下,輔助節點經過選舉機制來從剩餘的輔助節點中推選一個新的主節點從而實現自動切換。對於一個已經存在的MongoDB Replica Set集羣,能夠對其進行節點的增長,刪除,以及修改節點屬性等等。

1)查看當前版本環境
repSetTest:PRIMARY> db.version()
3.2.11

注意:利用rs.add和rs.remove是不用rs.reconfig來使用配置生效的。

2)刪除節點
repSetTest:PRIMARY> rs.remove("192.168.10.220:27000")
{ "ok" : 1 }

移除節點後的狀態信息
repSetTest:PRIMARY> rs.status()     

移除後查看配置文件
repSetTest:PRIMARY> rs.config()
---------------------------------------------------------------------
repmore:PRIMARY> config = {_id:"repmore",members:[{_id:0,host:'192.168.10.220:27017',priority :2}]};     //刪除節點  
repmore:PRIMARY> rs.reconfig(config);   //使配置生效  
repmore:PRIMARY> rs.status();   //查看節點狀態  
---------------------------------------------------------------------

3)增長節點
repSetTest:PRIMARY> rs.add("192.168.10.220:27000")
repSetTest:PRIMARY> rs.status()
repSetTest:PRIMARY> rs.config()
---------------------------------------------------------------------
或者使用下面方法添加節點:
repmore:PRIMARY> config = {_id:"repmore",members:[{_id:0,host:'192.168.10.220:27017',priority :2},{_id:1,host:'192.168.10.220:27018',priority:1}]};   //添加節點  
repmore:PRIMARY> rs.reconfig(config);    //使配置生效  
repmore:PRIMARY> rs.status();            //查看節點狀態

注意:新增節點的replSet要和其餘節點要同樣
---------------------------------------------------------------------

4)啓用Arbiter節點
repSetTest:PRIMARY> rs.remove("192.168.10.220:27000")
repSetTest:PRIMARY> rs.add({host:"192.168.10.220:27000",arbiterOnly:true})

對於Arbiter也可使用rs.addArb函數來添加
> rs.addArb("192.168.10.220:27000")

6)MongoDB複製集狀態查看

複製集狀態查詢命令
1)複製集狀態查詢:rs.status()
2)查看oplog狀態: rs.printReplicationInfo()
3)查看複製延遲:  rs.printSlaveReplicationInfo()
4)查看服務狀態詳情:   db.serverStatus()

====================================================================
1)rs.status()
self:只會出如今執行rs.status()命令的成員裏
uptime:從本節點 網絡可達到當前所經歷的時間
lastHeartbeat:當前服務器最後一次收到其心中的時間
Optime & optimeDate:命令發出時oplog所記錄的操做時間戳
pingMs: 網絡延遲
syncingTo: 複製源
stateStr:

可提供服務的狀態:primary, secondary, arbiter
即將提供服務的狀態:startup, startup2, recovering
不可提供服務狀態:down,unknow,removed,rollback,fatal

2)rs.printReplicationInfo()
log length start to end: 當oplog寫滿時能夠理解爲時間窗口
oplog last event time: 最後一個操做發生的時間

3).rs.printSlaveReplicationInfo()
複製進度:synedTo
落後主庫的時間:X secs(X hrs)behind the primary

4).db.serverStatus()
可使用以下命令查找須要用到的信息
db.serverStatus.opcounterRepl
db.serverStatus.repl

5).經常使用監控項目:
QPS: 每秒查詢數量
I/O: 讀寫性能
Memory: 內存使用
Connections: 鏈接數
Page Faults: 缺頁中斷
Index hit: 索引命中率
Bakground flush: 後臺刷新
Queue: 隊列

7)MongoDB複製集經常使用監控工具

1) mongostat
-h, --host   主機名或 主機名:端口
--port     端口號
-u ,--uername  用戶名(驗證)
-p ,--password   密碼(驗證)
--authenticationDatabase   從哪一個庫進行驗證
--discover   發現集羣某個其餘節點

[root@centos6-vm01 ~]# mongostat -h 192.168.10.220:27017  
[root@centos6-vm01 ~]# mongostat -h 192.168.10.220:27017  --discover  

mongostat重點關注的字段:
getmore 大量的排序操做在進行
faults 須要的數據不在內存中
locked db 鎖比例最高的庫
index miss 索引未命中
qr|qw 讀寫產生隊列,供求失衡

2) mongostop:與mongostat基本同樣
-h, --host   主機名或 主機名:端口
--port     端口號
-u ,--uername  用戶名(驗證)
-p ,--password   密碼(驗證)
--authenticationDatabase   從哪一個庫進行驗證

8)對於Secondary來講有幾個比較重要的屬性:Priority優先級、Vote投票節點、Hidden節點、Delayed節點

設定節點的優先級別(Priority)
Priority=0 即優先級爲0的節點。字面上來講,權限爲0。擁有最低的權限。已然是Secondary了,權限還最低,啥影響呢?以前說過,mongoDB的副本集中是有投票機制的,若是一個Primary不可達,那麼全部的Secondary會聯合起來投票選舉,選出心目中的新的Primary。由於只有Primary才能接收Writes的操做,因此Primary在一個mongoDB的集羣中是必須的。下圖展現了一個在兩個IDC中存放Primary,Secondary,以及一個Priority=0的Secondary的場景(關於這個存放方式以及奇數偶數。

優先級爲0的節點的特色

1)此節點喪失了當選Primary的機會。永遠不會上位。
2)此節點正常參與Primary產生的oplog的讀取,進行數據備份和命令執行。
3)此節點正常參與客戶端對於數據的讀取,進行擔當負載均衡的工做。
4)此節點雖然不能當選Primary可是卻能夠投票,很民主。

Priority=0在mongoDB中的解釋就是一個Standby,可投票不可參選,又幹活又負載。有點像日本議會黨派中剛入黨派的小嘍囉,能夠參與本身黨派黨首的選舉,還要幹好多活,外面民衆開罵還得擋着,但就是不可能當選黨首。

1)優先級用於肯定一個傾向成爲主節點的程度。取值範圍爲0-100
2)Priority 0節點的選舉優先級爲0,不會被選舉爲Primary,這樣的成員稱爲被動成員
3)對於跨機房複製集的情形,如A,B機房,最好將『大多數』節點部署在首選機房,以確保能選擇合適的Primary
4)對於Priority爲0節點的狀況,一般做爲一個standby,或因爲硬件配置較差,設置爲0以使用不可能成爲主

以下示例,在新增節點的時候設定該節點的優先級別
repSetTest:PRIMARY> rs.add({"_id":3,"host":"localhost:27000","priority":1.5})

也能夠經過下面的方式修改優先級別
repSetTest:PRIMARY> var config=rs.config()
repSetTest:PRIMARY> config.members[2].priority=2
2
repSetTest:PRIMARY> rs.reconfig(config)
{ "ok" : 1 }

投票節點(Vote)

1)投票節點不保存數據副本,不可能成爲主節點。
2)Mongodb 3.0裏,複製集成員最多50個,參與Primary選舉投票的成員最多7個。
3)對於超出7個的其餘成員(Vote0)的vote屬性必須設置爲0,即不參與投票。

 

隱藏節點(Hidden)
字面上來講,隱藏。這個隱藏式對客戶端的隱藏,客戶端若是要讀取Secondary的數據,永遠沒法讀取Hidden節點的數據,由於設置了Hidden的這個節點對於客戶端是透明的,不可見。可是,對於本身的Secondary的羣體和Primary來講都是可見的,因此,Hidden依然能夠投票,依然要按照oplog進行命令的複製,只是,不參與負載了。Hidden屬性的前提是必須是一個Priority=0的節點,因此會具有一些優先級=0的特色,具體以下。

Hidden節點的特色

1)此節點喪失了當選Primary的機會。永遠不會上位。
2)此節點正常參與Primary產生的oplog的讀取,進行數據備份和命令執行。
3)此節點正常參與客戶端對於數據的讀取,進行擔當負載均衡的工做。
4)此節點不參與客戶端對於數據的讀取,不進行負載均衡
5)此節點雖然不能當選Primary可是卻能夠投票,也很民主。

第3條特徵體現出它與Priority=0的不一樣地方,第4條特徵表現出它比0優先級多出來的特性。若是節點是Hidden,它不參與負載,那麼空閒出來的時間能夠作一些賦予給它的特殊任務,好比數據備份等等。到應用場景的時候會有用處。

1)Hidden節點不能被選爲主(Priority爲0),而且對Driver不可見。
2)因Hidden節點不會接受Driver的請求,可以使用Hidden節點作一些數據備份、離線計算的任務,不會影響複製集的服務
3)隱藏節點成員建議老是將其優先級設置爲0(priority 0)
4)因爲對Driver不可見,所以不會做爲read preference節點,隱藏節點能夠做爲投票節點
5)在分片集羣當中,mongos不會同隱藏節點交互

> cfg = rs.conf()
> cfg.members[2].priority = 0
> cfg.members[2].hidden = true
> rs.reconfig(cfg)

查看設置爲隱藏階段後的屬性
repSetTest:SECONDARY> db.isMaster()
{
"hosts" : [
       "localhost:27000",
       "localhost:27001"
                    ],
                    "setName" : "repSetTest",
                    "setVersion" : 2,
                    "ismaster" : false,
                    "secondary" : true,
                    "primary" : "localhost:27000",
                    "passive" : true,
                    "hidden" : true,     //此處代表當前節點爲隱藏節點
                    "me" : "localhost:27002",
                    "maxBsonObjectSize" : 16777216,
                    "maxMessageSizeBytes" : 48000000,
                    "maxWriteBatchSize" : 1000,
                    "localTime" : ISODate("2017-03-06T10:15:48.257Z"),
                    "maxWireVersion" : 4,
                    "minWireVersion" : 0,
                    "ok" : 1
}               

延遲節點(Delayed)
字面上來講,遲延。遲延表明此節點的數據與Primary的數據有必定的遲延,經過設定一個遲延的屬性來肯定。假設,Primary的數據是10:00的最新數據,咱們設置了一個3600秒的遲延參數,那麼這個帶有遲延的節點的數據或者說命令執行狀況(在oplog中)應該只到9:00爲止。與主節點有1小時的遲延。有些人可能會問,咱們設計分佈式數據庫要的就是數據可以儘可能避免遲延來達到一致,這樣才能更好的提供服務,爲何要刻意製造遲延呢?試想這個場景:一個豬同樣的隊友在mongoDB的Replica集羣上面執行了一個Drop操做,這個操做幹掉了你的Primary的Collection,這個Drop同時被記錄到oplog中去,其餘的Secondary看到這個oplog後爭相執行,各自幹掉了本身的Collection,你苦心存儲的數據就這麼消失了。。。再怎麼抽這個隊友沒用啊。因此,主動的過失避免就顯得格外重要。若是你有一個Delayed節點,有一個1000秒的遲延,那麼在你發現這個miss以後還有足夠的時間能夠響應去不讓這個Delayed節點執行錯誤的command,從而挽回你的損失。具體以下。

Delayed節點的特色

1)此節點必須是一個Priority=0且爲Hidden的節點,由於Hidden必須是Priority=0的,因此此節點必須是Hidden的。
2)此節點雖然又遲延又Hidden可是仍是能夠投票,也很民主。

Delayed節點的最大做用是用來容人爲的災,豬同樣的操做,驢同樣的動做,在Delayed節點能夠把損失降到最低。固然,若是你在Delayed時間通過後發現了錯誤,那麼只能"呵呵"了。Delayed的時間設定必定要大於響應時間,好比從Primary的oplog寫到Secondary須要1秒,那麼Delayed必須大於等於1秒,小於1秒的的話只能是一個不可及狀態。

延遲節點包含複製集的部分數據,是複製集數據的子集
延遲節點上的數據一般落後於Primary一段時間(可配置,好比1個小時)。
當人爲錯誤或者無效的數據寫入Primary時,可經過Delayed節點的數據進行回滾

延遲節點的要求:
1)優先級別爲0(priority 0),避免參與primary選舉
2)應當設置爲隱藏節點(以免應用程序查詢延遲節點)
3)能夠做爲一個投票節點,設置 members[n].votes 值爲1

延遲節點注意事項:       
1)延遲時間應當等於和大於維護窗口持續期
2)應當小於oplog容納數據的時間窗口 

repSetTest:SECONDARY> cfg = rs.conf()
repSetTest:SECONDARY> cfg.members[2].priority = 0
repSetTest:SECONDARY> cfg.members[2].hidden = true
repSetTest:SECONDARY> cfg.members[2].slaveDelay = 3600
repSetTest:SECONDARY> rs.reconfig(cfg)

repSetTest:SECONDARY> db.isMaster()
{
                    "hosts" : [
                            "localhost:27000",
                            "localhost:27001"
                    ],
                    "setName" : "repSetTest",
                    "setVersion" : 3,
                    "ismaster" : false,
                    "secondary" : true,
                    "primary" : "localhost:27000",
                    "passive" : true,
                    "hidden" : true,
                    "slaveDelay" : 3600,    //此處表面當前節點具備延遲屬性,爲延遲節點
                    "me" : "localhost:27002",
                    "maxBsonObjectSize" : 16777216,
                    "maxMessageSizeBytes" : 48000000,
                    "maxWriteBatchSize" : 1000,
                    "localTime" : ISODate("2017-03-06T10:19:57.148Z"),
                    "maxWireVersion" : 4,
                    "minWireVersion" : 0,
                    "ok" : 1
}

mongodb副本集修改配置問題

因ip地址被佔用,須要從新設置ip地址,這時須要修改副本集中的IP地址配置:
1)查看配置rs.config();須要找到primary主機,在該主節點服務器上纔有權限修改配置
2)rs.remove("ip:port") 移除原配置文件中的已經變動地址的主機
3)rs.add("ip:port")  添加新的地址主機
4)設置priority優先級
> var config = rs.config()
> config.members[2].priority=2
> rs.reconfig(config)         //從新更新配置

9)其餘維護說明

1、新增副本集成員
1)登陸primary
2)
>use admin 
>rs.add("new_node:port") 
或者
>rs.add({"_id":4,"host":"new_node:port","priority":1,"hidden":false})   
3)
>use admin
>rs.addArb("new_node:port") 
或者 
>rs.addArb({"_id":5,"host":"new_node:port"})
或者
>rs.add({'_id':5,"host":"new_node:port","arbiterOnly":true})

仲裁者惟一的做用就是參與選舉,仲裁者並不保存數據,也不會爲客戶端提供服務。成員一旦以仲裁者的身份加入副本集中,它就永遠只能是仲裁者,
沒法將仲裁者從新配置爲非仲裁者,反之亦然。最多隻能有一個仲裁者每一個副本集中。

舒適提示:
若是複製集中 priority=1 (默認),調用rs.add("new_node:port") 該命令 會產生 主從切換 即選舉操做;
若是複製集中 priority=1 (默認),直接調用rs.remove("new_node:port") 該命令 也會產生 主從切換 ;
 

2、刪除副本集成員
1)登陸要移除的目標mongodb實例;
2)利用shutdownServer()命令關閉實例;即 db.shutdownServer()
3)登陸複製集的primary;
4)
primary>use admin
primary>rs.remove("del_node:port");
 

3、修改爲員的優先級及隱藏性
1)登陸primary
2)
>use admin 
>conf=rs.conf()
>conf.members[1].priority=[0-1000]
>conf.members[1].hidden=true      #priority必須爲0
>conf.members[9].tags={"dc":"tags_name1"} 
>rs.reconfig(conf);      # 強制從新配置 rs.reconfig(conf,{"force":true})

成員的屬性有下列選項
  [, arbiterOnly : true]
      [, buildIndexes : <bool>]
      [, hidden : true]
      [, priority: <priority>]
      [, tags: {loc1 : desc1, loc2 : desc2, ..., locN : descN}]
      [, slaveDelay : ]#秒爲單位。
      [, votes : 

若是該成員要設置爲 隱藏(hidden:true) 或延遲(slaveDelay:30) 則其優先級priority必須設置爲 0;
也就是說 隱藏成員和延遲成員及buildIndexs:false的成員 的優先級別必定必須是0 即priority=0.
優先級爲0的成員不能發起選舉操做。
只要優先級>0即便該成員不具備投票資格,也能夠成爲主節點。
若是某個節點的索引結構和其餘節點上的索引結構不一致,則該節點就永遠不會變爲主節點。
優先級用於表示一個成員渴望成爲主節點的程度。優先級的取值範圍是[0-100],默認爲1。優先級爲0的成員永遠不能成爲主節點。
使用rs.status()和rs.config()可以看到隱藏成員,隱藏成員只對rs.isMaster()不可見。客戶端鏈接到副本集時,會調用rs.isMaster()
來查看可用成員。將隱藏成員設定爲非隱藏成員,只需將配置中的hidden設定爲false,或刪除hidden選項。
每一個成員能夠擁有多個標籤tags {「dc":"tags_name2",qty:"tag_name3"}
votes:0 表明阻止這些成員在選舉中投主動票,可是他們仍然能夠投否決票。
 
修改副本集成員配置時的限制:
1)不能修改_id;
2)不能講接收rs.reconfig命令的成員的優先級設置爲 0;
3)不能將仲裁者成員變爲非仲裁者成員,反正亦然;
4)不能講 buildIndexes:false 改成 true;
 
 
4、查看副本集成員數據同步(延遲)狀況
>db.printReplicationInfo();
>db.printSlaveReplicationInfo();#最好在secondary上執行
>rs.printReplicationInfo()
>rs.printSlaveReplicationInfo()
>use local>db.slaves.find()

在主節點上跟蹤延遲:
local.slaves該集合保存着全部正從當前成員進行數據同步的成員,以及每一個成員的數據新舊程度。
登陸主節點
>use local
>db.slaves.find()、
查看其中每一個成員對應的"syncedTo":{"t":9999999,"i":32} 部分便可知道數據的同步程度。
"_id"字段的值是每一個當前成員服務器標識符。能夠到每一個成員的local.me.find()查看本服務器標識符。

1)
若是多臺服務器擁有相同的_id標識符,則依次登陸每臺服務器成員,刪除local.me集合(local.me.dorp()),而後重啓mongodb,
重啓mongod後,mongod會使用新的「_id」從新生成local.me集合。
 
2)
若是服務器的地址改變但_id沒有變,主機名變了,該狀況會在本地數據庫的日誌中看到重複鍵異常(duplicate key exception)。
解決方法是:刪除local.slaves集合便可,不須要重啓mongod。
 
由於mongod不會清理local.slaves集合,故里面的數據可能不許確或過於老舊,可將整個集合刪除。當有新的服務器將當前成員做爲
複製源時,該集合會從新生成。若是在主節點中看到了某個特定的服務器在該集合中有多個文檔,即表示備份節點之間發生了複製鏈,
該狀況不影響數據同步,只是把每一個備份節點的同步源告訴主節點。
 
 
刪除local.me集合,須要從新啓動mongod,mongod啓動時會使用新的 _id從新生成local.me集合。
 
刪除local.slaves集合,不用重啓mongod。該集合中的數據是記錄該成員被做爲同步源的服務器的數據。該集合用於報告副本集狀態。
刪除後不久若是有新的節點成員將該服務器節點做爲複製源,該集合就會從新生成。
 

5、主節點降爲secondary
>use admin
>rs.stepDown(60)#單位爲 秒
 

6、鎖定指定節點在指定時間內不能成爲主節點(阻止選舉)
>rs.freeze(120)#單位爲 秒
釋放阻止
>rs.freeze(0)

 
7、強制節點進入維護模式(recovering)
能夠經過執行replSetMaintenanceMode命令強制一個成員進入維護模式。
例如自動檢測成員落後主節點指定時間,則將其轉入維護模式:
>function maybeMaintenanceMode(){
var local=db.getSisterDB("local");
if (!local.isMaster().secondary)
{return;
)
var last=local.oplog.rs.find().sort({"$natural":-1}).next();
var lasttime=last['ts']['t'];
if (lasttime<(new date()).getTime()-30)
{db.adminCommand({"replSetMaintenanceMode":true});
}
};

將成員從維護模式轉入正常模式。即恢復:
>db.adminCommand({"replSetMaintenanceMode":false});
 

8、阻止建立索引(不可再修改成能夠建立索引,故慎重考慮)
一般會在備份節點的延遲節點上設置阻止建立索引。由於該節點一般只是起到備份數據做用。設置選項 buildIndexs:false便可。該選項是永久性的。
若是要將不建立索引的成員修改成能夠建立索引的成員,那麼必須將這個成員從副本集中移除,再刪除它上的全部數據,最後再將其從新添加到副本集中。
而且容許其從新進行數據同步。該選項也要求成員的優先級爲 0.
 

9、指定複製源(複製鏈) 查看複製圖譜
使用db.adminCommand({"replSetGetStatus":1})['syncingTo'] 能夠查看複製圖譜(每一個節點的同步源);
在備份節點上執行 rs.status()['sysncingTo'] 一樣能夠查看複製圖譜(同步源);
mongodb是根據ping時間來選擇同步源的,會選擇一個離本身最近並且數據比本身新的成員做爲同步源。
可使用replSetSyncFrom 命令來指定複製源或使用輔助函數rs.sysncFrom()來修改複製源。
db.adminCommand({"replSetSyncFrom":"server_name:port"});
 
副本集默認狀況下是容許複製鏈存在的,由於這樣能夠減小網絡流量。但也有可能
花費是時間更長,由於複製鏈越長,將數據同步到所有服務器的時間有可能就越長(好比每一個備份節點都比前一個備份節點稍微舊點,這樣就得
從主節點複製數據)。

解決方法:
1)手動改變複製源
登陸備份節點:
>use admin
>db.adminCommand({"replSetSyncFrom":"新複製源"})
或者
>rs.syncFrom("新複製源")
副本集中的成員會自動選擇其餘成員做爲複製源。這樣就會產生複製鏈。
若是一個備份節點從另外一個備份節點(而非主節點)複製數據時,就會造成複製鏈。
複製鏈是能夠被禁用的,這樣就能夠強制要求全部備份節點都從主節點複製數據。
 
禁用複製鏈:即禁止備份節點從另外一個備份節點複製數據。
>var config=rs.config()
>config.settings=config.settings ||{}
>config.settings.chainingAllowed=false
>rs.reconfig(config);
 

10、強制修改副本集成員
>var config=rs.config()
>config.member[n].host=...
>config.member[n].priority=...
.....
>rs.reconfig(config,{"force":true})
 

11、修改Oplog集合的大小
若是是主節點,則先將primary 降爲 secondary。最後確保沒有其餘secondary 從該節點複製數據。rs.status()
1)關閉該mongod服務 use admin >db.adminCommand({shutdownServer:1});
2)以單機方式重啓該mongod(註釋掉 配置文件中的 replSet    shardsvr ,修改端口號)
3)將local.oplog.rs中的最後一條 insert 操做記錄保存到臨時集合中
> use local
>var cursor=db.oplog.rs.find({"op":"i"});
>var lastinsert=cursor.sort({$natural:-1}).limit(1).next();
>db.templastop.save(lastinsert);
>db.templastop.findOne()#確保寫入
4)將oplog.rs 刪除: db.oplog.rs.drop();
5)建立一個新的oplog.rs集合: db.createCollection("oplog.rs":{"capped":true,"size":10240});
6)將臨時集合中的最後一條insert操做記錄寫回新建立的oplog.rs:
>var temp=db.templastop.findOne();
>db.oplog.rs.insert(temp);
>db.oplog.rs.findOne() #確保寫回,不然 該節點從新加入副本集後會刪除該節點上全部數據,而後從新同步全部數據。
7)最後將該節點以副本集成員的身份從新啓動便可。
 

12、爲複製集成員設置選項
即當運行rs.initiate(replSetcfg) 或運行 rs.add(membercfg)選項時,須要提供描述複製集成員的特定配置結構:
{
_id:replSetName,
members:
[
{_id:<number>,host:<hostname|ip[:port]>,
[priority:<priority>,]#默認值爲1.0.即選項的值是浮點型
[hidden:true,]#該元素將從db.isMaster()的輸出中隱藏該節點。
[arbiterOnly:true,]#默認值爲 false
[votes:<n>,]#默認值爲1 。改選項的值爲整形
[tags:{documents},]
[slaveDelay:<seconds>,]
[buildIndexes:true,]#默認值爲 false。該選項用於禁止建立索引。
}],
settings:{
[chainingAllowed:<boolen>,]#指定該成員是否容許從其餘輔助服務器複製數據。默認值爲 true
[getLastErrorModes:<modes>,]#模式:用於自定義寫顧慮設置
[getLastErrorDefaults:<lasterrdefaults>,]#默認值:用於自定義寫顧慮設置。
}
}
以上是複製集的完整的配置結構。最高級的配置結構包括3級:
_id、members、settings。
_id是複製集的名稱,與建立複製集成員時時候用的 --replSet命令選項時提供的名稱同樣。
members是數組,由一個描述每一個成員的集合組成;這是添加單個服務器到集合中時,應該在rs.add()命令中提供的成員機構;
settings也是數組,該settings數組包含應用到整個複製集的選項。這些選項能夠設置複製集成員間如何通訊。
 

十3、Rollback
mongodb只支持小於300M的數據量回滾,若是大於300M的數據須要回滾或要回滾的操做在30分鐘以上,只能是手動去回滾。會在mongodb日誌中報如下錯誤:
[replica set sync] replSet syncThread: 13410 replSet too much data to roll back
經量避免讓rollback發生。方法是:使用 複製的 寫顧慮(Write Concern)規則來阻止回滾的發生。
若是發生了回滾操做,則會在mongodb數據文件目錄下產生一個以database.collection.timestamp.bson的文件。查看該文件的內容用 bsondump 工具來查看。
 

十4、讀偏好設置(ReadPreferred)
讀取偏好是指選擇從哪一個複製集成員讀取數據的方式。能夠爲驅動指定5中模式來設置讀取偏好。
readPreference=primary|primaryPreferred|secondary|secondaryPreferred|nearest
setReadPreferred()命令設置讀取偏好。
 
primary:只從主服務器上讀取數據。若是用戶顯式指定使用標籤讀取偏好,該讀取偏好將被阻塞。這也是默認的讀取偏好。
primaryPreferred:讀取將被重定向至主服務器;若是沒有可用的主服務器,那麼讀取將被重定向至某個輔助服務器;
secondary:讀取將被重定向至輔助服務器節點。若是沒有輔助服務器節點,該選項將會產生異常;
secondaryPreferred:讀取將被重定向至輔助服務器;若是沒有輔助服務器,那麼讀取將被重定向至主服務器。該選項對應舊的「slaveOK」方法;
nearest:從最近的節點讀取數據,不論它是主服務器仍是輔助服務器。該選項經過網絡延遲決定使用哪一個節點服務器。
 

十5、寫顧慮設置(Write Concern)
寫顧慮相似讀取偏好,經過寫顧慮選項能夠指定在寫操做被確認完成前,數據必須被安全提交到多少個節點。
寫顧慮的模式決定了寫操做時如何持久化數據。參數「w」會強制 getLastError等待,一直到給定數據的成員都執行完了最後的寫入操做。w的值是包含主節點的。
寫顧慮的5中模式:
w=0或不肯定:單向寫操做。寫操做執行後,不須要確認提交狀態。 
w=1或確認:寫操做必須等到主服務器的確認。這是默認行爲。
w=n或複製集確認:主服務器必須確認該寫操做。而且n-1個成員必須從主服務器複製該寫入操做。該選項更強大,可是會引發延遲。
w=majority:寫操做必須被主服務器確認,同時也須要集合中的大多數成員都確認該操做。而w=n可能會由於系統中斷或複製延遲引發問題。
j=true日誌:能夠與w=寫顧慮一塊兒共同指定寫入操做必須被寫入到日誌中,只有這樣纔算是確認完成。
wtimeout:避免getLastError一直等待下去,該值是命令的超時時間值,若是超過這個時間尚未返回,就會返回失敗。該值的單位是毫秒。若是返回失敗,
值在規定的時間內沒有將寫入操做複製到"w"個成員。
該操做只對該鏈接起做用,其餘鏈接不受該鏈接的"w"值限制。
db.products.insert(
{ item : "envelopes" , qty : 100 , type : "Clasp" },
{ writeConcern : { w : 2 , wtimeout : 5000 } }
)
wtimeout#表明5秒超時
 
修改默認寫顧慮
cfg = rs.conf()
cfg.settings = {}
cfg.settings.getLastErrorDefaults = { w: "majority" , wtimeout: 5000 }
rs.reconfig(cfg)
 
設置寫等待
db.runCommand({"getLastError":1,w:"majority"})
或
db.runCommand({"getLastError":1,"w":"majority","wtimeout":10000})
即,表示寫入操做被複制到了多數個節點上(majority 或 數字),這時的 w會強制 getLastError等待,一直到給定數量的成員執行完了最後的寫入操做。
    而wtimeout是指超過這個時間沒有返回則返回失敗提示(即沒法在指定時間內將寫入操做複製到w個成員中),getLastError並不表明寫操做失敗了,
    而是表明在指定給定wtimeout時間內沒有將寫入操做複製到指定的w個成員中。w是限制(控制)寫入 速度,只會阻塞這個鏈接上的操做,其餘鏈接上
    的操做不受影響。
 

十6、讀取偏好和寫顧慮中使用標籤(tags)
 

十7、選舉機制
1)自身是否可以與主節點連通;
2)但願被選件爲主節點的備份節點的數據是否最新;
3)有沒有其餘更高優先級的成員能夠被選舉爲主節點;
4)若是被選舉爲主節點的成員可以獲得副本集中「大多數」成員的投票,則它會成爲主節點,若是「大多數」成員中只有一個否決了本次選舉,則本次選舉
失敗即就會取消。一張否決票至關於10000張同意票。
5)但願成爲主節點的成員必須使用複製將本身的數據更新爲最新;
 

十8、數據初始化過程
1)首先作一些記錄前的準備工做:選擇一個成員做爲同步源,在local.me集合中爲本身建立一個標識符,刪除索引已存在的數據庫,以一個全新的狀態
開始進行同步;該過程當中,全部的數據都會被刪除。
2)而後克隆,就是將同步源的全部記錄所有複製到本地。
3)而後就進入oplog同步的第一步,克隆過程當中的全部操做都會被記錄到oplog中。
4)接下來就是oplog同步過程的第二步,用於將第一個oplog同步中的操做記錄下來。
5)截止當前,本地的數據應該與主節點在某個時間點的數據集徹底一致了,能夠開始建立索引了。
6)若當前節點的數據仍然落後同步源,那麼oplog同步過程的最後一步就是將建立索引期間的全部操做所有同步過出來,防止該成員成爲備份節點。
7)如今當前成員已經完成了初始化數據的同步,切換到普通狀態,這時該節點就能夠成爲備份節點了。
 
十9、mongodb3.0 建議開啓的設置
# echo never > /sys/kernel/mm/transparent_hugepage/enabled
# echo never > /sys/kernel/mm/transparent_hugepage/defrag
執行上面兩命令後只是當前起做用。若是重啓mongod服務後 就失效。永久起效則
寫入到 /etc/rc.local
即 
 
二10、修改服務器hostname名
1)首先修改 secondary 服務器的 hostname;而後 stop secondary;
2)重啓 secondary 以修改後的新hostname;
3)登陸 primary ;
4)用rs.reconfig()命令修改 複製集的配置信息;
>conf=rs.conf()
>conf.members[x].host='new_address:27017'
>rs.reconfig(conf);
 
二11、生成 keyfile文件
# openssl rand -base64 666 > /opt/mongo/conf/MongoReplSet_KeyFile
# chown mongod.mongod /opt/mongo/conf/MongoReplSet_KeyFile
# chmod 600 /opt/mongo/conf/MongoReplSet_KeyFile
相關文章
相關標籤/搜索