Mongodb複本集
一、簡介:
簡單來說,複本集(Replica Set)就是有自動故障恢複功能的主從叢集。主從叢集和複本集最為明顯的區別是複本集沒有固定的“主節點”:整個叢集會選舉出一個“主節點”,當其不能工作時則變更到其他節點。然而,二者看上去非常相似:複本集總會有一個活躍節點(primary)和一個或多個備份節點(secondary)。
複本集最美妙的地方就是所有東西都是自動化的。首先他為你做了很多管理工作,自動提升備份節點為活躍節點,其次,對開發人員而言也非常易用:僅需要為複本集指定一下伺服器,驅動程式就會自動找到伺服器,在當前活躍節點死機時自動處理故障恢複這類事情。
當活躍節點掛了,備份節點自動成為活躍節點。
當活躍節點又恢複了,由於已經有活躍節點了,自動變為備份節點。 二、複本集中的節點
1. Standard: 常規節點,儲存了完整資料副本,參與投票,可能成為活躍節點,優先權非0.
2. Passive: 儲存了完整資料副本,參與投票,不能成為活躍節點。優先權為0.
3. Arbiter:仲裁者,只參與投票,不接受複製的資料,也不能成為活躍節點。
如果活躍節點壞了,其他節點會選出一個新的活躍節點來。選舉過程可以由任何非活躍節點發起。新的活躍節點由複本集中的大多數選舉產生。仲裁節點也會參與投票,避免出現僵局。新的活躍節點將是優先順序最高的節點,優先順序相同則資料較新的獲勝。
活躍節點使用心跳來跟蹤叢集中有多少節點對其可見。如果不夠半數,活躍節點會自動降級為備份節點。這樣就能防止活躍節點一直不放權。
不論活躍節點何時變化,新活躍節點的資料就被假定為系統的最新資料。其他節點的操作會復原,即便之前的活躍節點恢複了工作。 選舉:
在以下幾種情景發生的時候,複本集通過“選舉”來決定複本集中的primary節點:
· 當第一次初始化一個複本集的時候;
· primary幾點steps down的時候,出現這種情況可能是因為執行了replSetStepDown命令,或者是叢集中出現了更適合當primary的節點,比如當primary節點和叢集中其他大部分節點無法通訊的時候,當primarysteps down的時候,它會關閉所有用戶端的串連。
· 當叢集中一個secondary節點無法和primary節點建立串連的時候也會導致一次election發生。
· 一次failover。
· 執行rs.conf()命令。
在一次選舉中包括hidden節點、仲裁者甚至正處於recovering狀態的節點都具有“投票權”。預設配置中所有參與選舉的節點具有相等的權利,當然在一些特定情況下,應明確的指定某些secondary會優先成為primary,比如一個遠在千裡之外異地機房的節點就不應該成為primary節點,選舉的權重通過設定priority來調節,預設該值都是1,在前面簡單複本集的搭建中已經介紹過了如何修改該值。
叢集中任何一個節點都可以否決選舉,即使它是non-voting member:
· 如果發起選舉的節點不具有選舉權(priority為0的成員);
· 發起選舉的節點資料落後太多;
· 發起選舉的節點的priority值比叢集中其他某一個節點的小;
· 如果當前的primary節點比發起選舉的節點擁有更新或同等新的資料(也就“optime”值相等或更大)。
· 當前的primary節點會否決,如果它擁有比發起選舉的節點更新或相同新的資料。
首先擷取最多選票的成員(實際上要超過半數)才會成為primary節點,這也說明了為什麼當有兩個節點的叢集中primary節點宕機後,剩下的只能成為secondary,當primary宕掉,此時複本集只剩下一個secondary,它只有1票,不超過總節點數的半數,它不會選舉自己為primary。 讀擴充:
ReadReferences:
應用程式驅動通過read reference來設定如何對複本集進行讀取操作,預設的,用戶端驅動所有的讀操作都是直接存取primary節點的,從而保證了資料的嚴格一致性。
但有時為了緩解主節點的壓力,我們可能需要直接從secondary節點讀取,只需要保證最終一致性就可以了。
MongoDB 2.0之後支援五種的readpreference模式:
primary:預設,只從主節點上進行讀取操作;
primaryPreferred:在絕大部分的情形都是從主節點上讀取資料的,只有當主節點停用時候,比如在進行failover的10秒或更長的時間內會從secondary節點讀取資料。
警告:2.2版本之前的MongoDB對ReadPreference支援的還不完全,如果用戶端驅動採用primaryPreferred實際上讀取操作都會被路由到secondary節點。
secondary:只從secondary節點上進行讀取操作,存在的問題是secondary節點的資料會比primary節點資料“舊”。
secondaryPreferred:優先從secondary節點進行讀取操作;
nearest:既有可能從primary,也有可能從secondary節點讀取,這個決策是通過一個叫memberselection過程處理的。
MongoDB允許在不同的粒度上指定這些模式:串連、資料庫、集合甚至單次的操作。不同語言的驅動基本都支援這些粒度。 同步
從節點第一次啟動時,會對主節點資料進行完整的同步.從節點複製主節點上的每個文檔,很耗資源.同步完成後,
從節點開始查詢主節點的oplog並執行這些操作,以保證資料是最新的.
如果從節點的操作和主節點的相差很遠,從節點就跟不上同步了.跟不上同步的從節點無法一直追趕主節點.因為
主節點oplog的所有操作太新了.從節點發生了宕機或著疲於應付讀取時會出現這個情況,也會在執行完完整同步以後
反生類似的事,因為只要同步的時間太長,同步完成時,oplog可能已經操作了很多.
從節點跟不上同步時,複製就會停下來,從節點需要重新做完整的同步.可以用{"resync":1}命令手動執行從新同步,
也可以在啟動從節點時使用--autoresync選項讓其自動重新同步,重新同步的代價很高,應盡量避免,方法是配置
足夠大的oplog,配置足夠大的oplog能存放相當長的時間操作記錄.大的oplog會佔用更多的磁碟空間,則需要權衡一下.
預設的oplog大小是剩餘磁碟空間的5%.
三、執行個體
準備:
兩台伺服器:
192.168.229.80:80伺服器作為節點1,目錄如下
/export/servers/dbs/node1/
192.168.192.75:75伺服器作為節點2,目錄如下
啟動node1節點:80:
-bash-3.2# ./bin/mongod --dbpath ./data/node1 --logpath ./data/node1/node1.log --port 10001 --replSet test/192.168.192.75:10002 |
啟動node2節點:75:
[root@localhost mongodb-linux-x86_64-2.0.4]# ./bin/mongod --dbpath ./data/node2/ --port 10002 --replSet test/ |
通過192.168.192.68連結到一台伺服器:
./bin/mongo 192.168.229.80:10001/admin |
初始化複本集:
db.runCommand({ "replSetInitiate":{ "_id":"test", "members":[ { "_id":1, "host":"192.168.229.80:10001" , "priority":3 }, { "_id":2, "host":"192.168.192.75:10002", "priority":2 } ] } }); |
結果如圖:提示ok:1即成功,間有幾次報錯是磁碟滿了,清除後ok
查看複本集狀態:
查看是否為主節點:看到ismaster:true
切換到75上查看:ismaster:false
往主庫插入資料:
去從庫查看:
發現查不到資料,這是正常的,因為SECONDARY是不允許讀寫的,在寫多讀少的應用中,使用Replica Sets來實現讀寫分離。通過在串連時指定或者在主庫指定slaveOk,由Secondary來分擔讀的壓力,Primary只承擔寫操作。
對於replica set 中的secondary 節點預設是不可讀的,分別從從庫和主庫設定setSlaveOk即可。
參考:
http://www.cnblogs.com/refactor/archive/2012/08/13/2600140.html