再看MongoDB副本集

壹頁書發表於2014-06-05
因為MongoDB使用記憶體對映檔案,所以必須使用64位版本。
官方下載地址如下:
實驗環境使用的Mongodb版本為mongodb-linux-x86_64-2.6.0
由三臺虛擬機器搭建,配置為單核,1G記憶體。
實驗環境如下:

MongoDB的副本集不同於以往的主從模式。
在叢集Master故障的時候,副本集可以自動投票,選舉出新的Master,並引導其餘的Slave伺服器連線新的Master,
而這個過程對於應用是透明的。可以說MongoDB的副本集是自帶故障轉移功能的主從複製。

1 相對於傳統主從模式的優勢
傳統的主從模式,需要手工指定叢集中的Master。
如果Master發生故障,一般都是人工介入,指定新的Master。
這個過程對於應用一般不是透明的,往往伴隨著應用重新修改配置檔案,重啟應用伺服器等。

而MongoDB副本集,叢集中的任何節點都可能成為Master節點。
一旦Master節點故障,則會在其餘節點中選舉出一個新的Master節點。
並引導剩餘節點連線到新的Master節點。這個過程對於應用是透明的。


2 Bully選舉演算法
Bully演算法是一種協調者(主節點)競選演算法,主要思想是叢集的每個成員都可以宣告它是主節點並通知其他節點。
別的節點可以選擇接受這個聲稱或是拒絕並進入主節點競爭。被其他所有節點接受的節點才能成為主節點。
節點按照一些屬性來判斷誰應該勝出。這個屬性可以是一個靜態ID,也可以是更新的度量像最近一次事務ID(最新的節點會勝出)
他的選舉過程大致如下:
? 得到每個伺服器節點的最後操作時間戳。每個mongodb都有oplog機制會記錄本機的操作,方便和主伺服器進行對比資料是否同步還可以用於錯誤恢復。
? 如果叢集中大部分伺服器down機了,保留活著的節點都為 secondary狀態並停止,不選舉了。
? 如果叢集中選舉出來的主節點或者所有從節點最後一次同步時間看起來很舊了,停止選舉等待人來操作。
? 如果上面都沒有問題就選擇最後操作時間戳最新(保證資料是最新的)的伺服器節點作為主節點。

選舉的觸發條件
初始化一個副本集時。
副本集和主節點斷開連線,可能是網路問題。
主節點掛掉。
人為介入,比如修改節點優先順序等

選舉還有個前提條件,參與選舉的節點數量必須大於副本集總節點數量的一半,如果已經小於一半了所有節點保持只讀狀態。

3 搭建副本集叢集
每個虛擬機器都使用如下的配置檔案啟動例項:
dbpath        =/home/lihuilin/mongodata
smallfiles      =true
replSet        =mvbox
然後在任意一臺虛擬機器登陸mongo,輸入如下設定
config = { _id:"mvbox", members:[
{_id:0,host:"192.168.1.1:27017"},
{_id:1,host:"192.168.1.2:27017"},
{_id:2,host:"192.168.1.3:27017"}]
}
rs.initiate(config);
可以看到副本集已經生效

可以使用rs.status()檢視叢集狀態,或者rs.isMaster()


4 更改節點優先順序
修改節點的優先順序可以觸發重新選舉,這樣可以人工指定主節點。
使用如下命令,在主節點登入,將192.168.1.3提升為Master。
rs.conf();
cfg=rs.conf();
cfg.members[0].priority=1
cfg.members[1].priority=1
cfg.members[2].priority=10
rs.reconfig(cfg);
需要注意的是,修改節點優先順序需要登入Master節點執行。否則報錯。

再次檢視叢集狀態,可以看到192.168.1.3已經作為Master執行


5 節點型別
MongoDB的節點型別有主節點(Master),副本節點(Slave或者稱為Secondary),仲裁節點,Secondary-Only節點,Hidden節點,Delayed節點和Non-Voting節點。

仲裁節點不儲存資料,只是負責故障轉移的群體投票,這樣就少了資料複製的壓力。

Secondary-Only:不能成為primary節點,只能作為secondary副本節點,防止一些效能不高的節點成為主節點。

Hidden:這類節點是不能夠被客戶端制定IP引用,也不能被設定為主節點,但是可以投票,一般用於備份資料。

Delayed:可以指定一個時間延遲從primary節點同步資料。主要用於備份資料,如果實時同步,誤刪除資料馬上同步到從節點。所以延遲複製主要用於避免使用者錯誤。

Non-Voting:沒有選舉權的secondary節點,純粹的備份資料節點。

6 設定隱藏節點(Hidden)
隱藏節點可以在選舉中投票,但是不能被客戶端引用,也不能成為主節點。也就是說這個節點不能用於讀寫分離的場景。
將192.168.1.3設定為隱藏節點。
注意,只有優先順序為0的成員才能設定為隱藏節點。
如果設定優先順序不為0的節點為隱藏節點,則報錯如下


使用如下命令設定隱藏節點
cfg=rs.conf();
cfg.members[0].priority=10
cfg.members[1].priority=1
cfg.members[2].priority=0
cfg.members[2].hidden=1
rs.reconfig(cfg);
設定完成之後,使用rs.status()檢視該節點還是SECONDARY狀態。
但是透過rs.isMaster()和rs.conf()可以看到這個節點的變化。
rs.isMaster()的hosts中192.168.1.3節點已經不可見

並且rs.conf()顯示該節點狀態為hidden


7 設定仲裁節點
仲裁節點不儲存資料,只是用於投票。所以仲裁節點對於伺服器負載很低。
節點一旦以仲裁者的身份加入叢集,他就只能是仲裁者,無法將仲裁者配置為非仲裁者,反之也是一樣。
另外一個叢集最多隻能使用一個仲裁者,額外的仲裁者拖累選舉新Master節點的速度,同時也不能提供更好的資料安全性。
初始化叢集時,設定仲裁者的配置如下
config = { _id:"mvbox", members:[
{_id:0,host:"192.168.1.1:27017"},
{_id:1,host:"192.168.1.2:27017",arbiterOnly:true},
{_id:2,host:"192.168.1.3:27017"}]
}
使用仲裁者主要是因為MongoDB副本集需要奇數成員,而又沒有足夠伺服器的情況。在伺服器充足的情況下,不應該使用仲裁者節點。

8 設定延遲複製節點
MongoDB官方沒有增量備份方案,只有一個匯出的工具mongodump。
他不能像資料庫一樣,透過binlog或者歸檔日誌將資料推到事故發生的前一刻。
假設每天凌晨2點使用mongodump備份,而下午5點發生事故,資料庫損毀,則凌晨2點到下午5點的資料全部都會丟失。
雖然副本集可以一定程度避免這個問題,但是預設情況下不能避免人為的失誤。
比如沒有指定篩選條件刪除了全部的資料。副本節點會應用這個命令,刪除所有副本節點的資料。
在這個場景下,可以使用延遲節點,它會延遲應用複製。
如果主節點發生了人為的失誤,而這個操作因為延遲的原因,還沒有應用在延遲節點。
這個時候,修改延遲節點的優先順序為最高階,使他成為新的Master伺服器。

延遲節點的優先順序必須為0.這個和hidden節點是一樣的。
設定192.168.1.2為延遲節點
cfg=rs.conf();
cfg.members[1].priority=0
cfg.members[1].slaveDelay=3600
rs.reconfig(cfg);
slaveDelay的單位是秒
在192.168.1.1主節點刪除一個集合所有資料,模擬人為失誤。


在192.168.1.3檢視,發現資料已經全部丟失。

而在192.168.1.2延遲節點,可以看到因為延遲複製的緣故,資料還在。

這個時候千萬不要提升延遲節點的優先順序。因為這樣他會立即應用原主節點的所有操作,併成為新的主節點。這樣誤操作就同步到了延遲節點。
首先,關閉副本集中其他的成員,除了延遲節點。
刪除其他成員資料目錄中的所有資料。確保每個其他成員的資料目錄都是空的(除了延遲節點)
重啟其他成員,他們會自動從延遲節點中恢復資料。

9 設定Secondary-Only節點
Priority為0的節點永遠不能成為主節點,所以設定Secondary-only節點只需要將其priority設定為0.

10 設定Non-Voting節點
假設設定192.168.1.1不能投票,則使用如下命令
cfg=rs.conf();
cfg.members[0].votes=0;
rs.reconfig(cfg);

11 副本整合員狀態
副本整合員狀態指的是rs.status()的stateStr欄位

STARTUP:剛加入到複製集中,配置還未載入

STARTUP2:配置已載入完,初始化狀態

RECOVERING:正在恢復,不適用讀

ARBITER: 仲裁者

DOWN:節點不可到達

UNKNOWN:未獲取其他節點狀態而不知是什麼狀態,一般發生在只有兩個成員的架構,腦裂

REMOVED:移除複製集

ROLLBACK:資料回滾,在回滾結束時,轉移到RECOVERING或SECONDARY狀態

FATAL:出錯。檢視日誌grep “replSet FATAL”找出錯原因,重新做同步

PRIMARY:主節點

SECONDARY:備份節點

12 讀寫分離
如果Master節點讀寫壓力過大,可以考慮讀寫分離的方案。




不過需要考慮一種場景,就是主伺服器的寫入壓力非常的大,所以副本節點複製的寫入壓力同樣很大。
這時副本節點如果讀取壓力也很大的話,根據MongoDB庫級別讀寫鎖的機制,
很可能複製寫入程式拿不到寫鎖,從而導致副本節點與主節點有較大延遲。

如果進行讀寫分離,首先需要在副本節點宣告其為slave,

然後在JAVA程式中進行設定

其中的ReadRreference有幾種設定,


primary:預設引數,只從主節點上進行讀取操作;

primaryPreferred:大部分從主節點上讀取資料,只有主節點不可用時從secondary節點讀取資料。

secondary:只從secondary節點上進行讀取操作,存在的問題是secondary節點的資料會比primary節點資料“舊”。

secondaryPreferred:優先從secondary節點進行讀取操作,secondary節點不可用時從主節點讀取資料;

nearest:不管是主節點、secondary節點,從網路延遲最低的節點上讀取資料。

參考:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-1176553/,如需轉載,請註明出處,否則將追究法律責任。

相關文章