三個節點有一個節點掛掉也不會影響應用程序客戶端對整個副本集的讀寫!
- public class TestMongoDBReplSet { public static void main(String[] args)
- { try { List<ServerAddress> addresses = new ArrayList<ServerAddress>();
- ServerAddress address1 = new ServerAddress("192.168.1.136" , 27017); ServerAddress
- address2 = new ServerAddress("192.168.1.137" , 27017); ServerAddress address3
- = new ServerAddress("192.168.1.138" , 27017); addresses.add(address1);
- addresses.add(address2); addresses.add(address3); MongoClient client =
- new MongoClient(addresses); DB db = client.getDB( "test"); DBCollection
- coll = db.getCollection( "testdb"); // 插入 BasicDBObject object = new BasicDBObject();
- object.append( "test2", "testval2" ); coll.insert(object); DBCursor dbCursor
- = coll.find(); while (dbCursor.hasNext()) { DBObject dbObject = dbCursor.next();
- System. out.println(dbObject.toString()); } } catch (Exception e) { e.printStackTrace();
- } } }
目前看起來支持完美的故障轉移了,這個架構是不是比較完美了?其實還有很多地方可以優化,比如開頭的第二個問題:主節點的讀寫壓力過大如何解決?常見的解決方案是讀寫分離,mongodb副本集的讀寫分離如何做呢?
看圖說話:
常規寫操作來說並沒有讀操作多,所以一台主節點負責寫,兩台副本節點負責讀。
1、設置讀寫分離需要先在副本節點SECONDARY 設置 setSlaveOk。
2、在程序中設置副本節點負責讀操作,如下代碼:
- public class TestMongoDBReplSetReadSplit {
- public static void main(String[] args) {
- try {
- List<ServerAddress> addresses = new ArrayList<ServerAddress>();
- ServerAddress address1 = new ServerAddress("192.168.1.136" , 27017);
- ServerAddress address2 = new ServerAddress("192.168.1.137" , 27017);
- ServerAddress address3 = new ServerAddress("192.168.1.138" , 27017);
- addresses.add(address1);
- addresses.add(address2);
- addresses.add(address3);
- MongoClient client = new MongoClient(addresses);
- DB db = client.getDB( "test" );
- DBCollection coll = db.getCollection( "testdb" );
- BasicDBObject object = new BasicDBObject();
- object.append( "test2" , "testval2" );
- //讀操作從副本節點讀取
- ReadPreference preference = ReadPreference. secondary();
- DBObject dbObject = coll.findOne(object, null , preference);
- System. out .println(dbObject);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
讀參數除了secondary一共還有五個參數:primary、primaryPreferred、secondary、secondaryPreferred、nearest。
primary:默認參數,只從主節點上進行讀取操作;
primaryPreferred:大部分從主節點上讀取數據,只有主節點不可用時從secondary節點讀取數據。
secondary:只從secondary節點上進行讀取操作,存在的問題是secondary節點的數據會比primary節點數據“舊”。
secondaryPreferred:優先從secondary節點進行讀取操作,secondary節點不可用時從主節點讀取數據;
nearest:不管是主節點、secondary節點,從網絡延遲最低的節點上讀取數據。
好,讀寫分離做好我們可以數據分流,減輕壓力解決了“主節點的讀寫壓力過大如何解決?”這個問題。不過當我們的副本節點增多時,主節點的復制壓力會加大有什么辦法解決嗎?mongodb早就有了相應的解決方案。
其中的仲裁節點不存儲數據,只是負責故障轉移的群體投票,這樣就少了數據復制的壓力。是不是想得 很周到啊,一看mongodb的開發兄弟熟知大數據架構體系,其實不只是主節點、副本節點、仲裁節點,還有Secondary-Only、Hidden、 Delayed、Non-Voting。
Secondary-Only:不能成為primary節點,只能作為secondary副本節點,防止一些性能不高的節點成為主節點。
Hidden:這類節點是不能夠被客戶端制定IP引用,也不能被設置為主節點,但是可以投票,一般用於備份數據。
Delayed:可以指定一個時間延遲從primary節點同步數據。主要用於備份數據,如果實時同步,誤刪除數據馬上同步到從節點,恢復又恢復不了。
Non-Voting:沒有選舉權的secondary節點,純粹的備份數據節點。
到此整個mongodb副本集搞定了兩個問題:
- 主節點掛了能否自動切換連接?目前需要手工切換。
- 主節點的讀寫壓力過大如何解決?
還有這兩個問題后續解決:
- 從節點每個上面的數據都是對數據庫全量拷貝,從節點壓力會不會過大?
- 數據壓力大到機器支撐不了的時候能否做到自動擴展?
做了副本集發現又一些問題:
- 副本集故障轉移,主節點是如何選舉的?能否手動干涉下架某一台主節點。
- 官方說副本集數量最好是奇數,為什么?
- mongodb副本集是如何同步的?如果同步不及時會出現什么情況?會不會出現不一致性?
- mongodb的故障轉移會不會無故自動發生?什么條件會觸發?頻繁觸發可能會帶來系統負載加重