MongoDB 副本集和C#交互,簡單測試html
primary節點宕機:java
模擬primary節點宕機的狀況,這時查看監控:mongodb
能夠看到37018已經成了primary節點。主界面宕機致使了整個集羣發生一次election,實現了failover。等37017恢復了會自動成爲secondary節點:shell
全部secondary節點宕機:app
當全部secondary宕機,或者副本集中只剩下一臺機器的時候,那麼剩下的機器只能成爲secondary節點,也就意味着整個集羣智能進行讀操做而不能進行寫操做:maven
當集羣從故障中恢復過來後,仍然的primary節點仍然是primary節點。測試
注意:當某個節點宕機後從新啓動該節點會有一段的時間(時間長短視集羣的數據量和宕機時間而定)致使整個集羣中全部節點都成爲secondary而沒法進行寫操做(若是應用程序沒有設置相應的ReadReference也可能不能進行讀取操做)。spa
所以官方推薦的最小的副本集也應該具有一個primary節點和兩個secondary節點。兩個節點的副本集不具有真正的故障轉移能力。3d
副本集搭建好了,基本的故障轉移能力也驗證過了,那麼應用程序如何訪問呢?下面分別介紹下C#和Java驅動如何訪問mongodb副本集。rest
C#:
C#驅動下載地址http://driver-downloads.mongodb.org/dotnet/index.html,我使用的最新版本1.8.2。
下面是訪問副本集基本的代碼:
MongoClientSettings set = new MongoClientSettings();
List<MongoServerAddress> servers = new List<MongoServerAddress>();
servers.Add(new MongoServerAddress("192.168.129.129", 37017));
servers.Add(new MongoServerAddress("192.168.129.129", 37018));
servers.Add(new MongoServerAddress("192.168.129.129", 37019));
set.Servers = servers;
//設置副本集名稱
set.ReplicaSetName = "rs0";
//設置超時時間爲3秒
set.ConnectTimeout = new TimeSpan(0, 0, 0, 3, 0);
MongoClient client = new MongoClient(set);
MongoServer server = client.GetServer();
MongoDatabase db = server.GetDatabase("test");
MongoCollection coll = db.GetCollection("test");
//插入
BsonDocument bd = new BsonDocument();
bd.Add("name", "zhanjindong");
bd.Add("age", 23);
bd.Add("sex", "男D");
coll.Insert(bd);
//讀取
QueryDocument qd = new QueryDocument();
qd.Add("name", "zhanjindong");
qd.Add("age", 23);
qd.Add("sex", "男D");
BsonDocument rd = coll.FindOneAs<BsonDocument>(qd);
Console.WriteLine(rd.ToString());
當kill掉一個節點(secondary或primary)的時候,讀取和寫入的操做都是正常的,說明副本集的failover起做用了。但kill模擬兩個節點宕機的時候,發現上面的代碼在讀取的時候會報下面的錯誤:
這是由於默認的C#驅動的ReadPreference是Primary,也就是說讀寫操做都是在主節點上的,那麼當集羣中只剩下一個節點的時候,按照前面所說該節點必定是secondary節點,這樣讀取操做也是無法進行的(經過mongo shell固然是能夠的)。解決方法就是設置驅動的ReadPreferenceMode:
set.ReadPreference = new ReadPreference(ReadPreferenceMode.PrimaryPreferred);
將ReadPreferenceMode設置成Secondary或SecondaryPreferred。後面讀寫分離一節對ReadPreference會有詳細的說明。
ReadPreferenceMode參數:
primary:默認,只從主節點上進行讀取操做;
primaryPreferred:在絕大部分的情形都是從主節點上讀取數據的,只有當主節點不可用的時候,好比在進行failover的10秒或更長的時間內會從secondary節點讀取數據。
警告:2.2版本以前的MongoDB對Read Preference支持的還不徹底,若是客戶端驅動採用primaryPreferred實際上讀取操做都會被路由到secondary節點。
secondary:只從secondary節點上進行讀取操做,存在的問題是secondary節點的數據會比primary節點數據「舊」。
secondaryPreferred:優先從secondary節點進行讀取操做;
nearest:既有可能從primary,也有可能從secondary節點讀取,這個決策是經過一個叫member selection過程處理的。
Java:
Java驅動下載地址:http://central.maven.org/maven2/org/mongodb/mongo-java-driver/
我用的是最新版本mongo-java-driver-2.11.2.jar。
下面是Java訪問MongoDB副本集的基本代碼:
List<ServerAddress> addresses = new ArrayList<ServerAddress>(); ServerAddress address1 = new ServerAddress("192.168.129.129", 37017); ServerAddress address2 = new ServerAddress("192.168.129.129", 37018); ServerAddress address3 = new ServerAddress("192.168.129.129", 37018); addresses.add(address1); addresses.add(address2); addresses.add(address3); MongoClient client = new MongoClient(addresses); DB db = client.getDB("test"); DBCollection coll = db.getCollection("test"); // 插入 BasicDBObject object = new BasicDBObject(); object.append("name", "zhanjindong"); object.append("age", 23); object.append("sex", "男"); coll.insert(object); BasicDBObject qobj = new BasicDBObject(); qobj.append("name", "zhanjindong"); qobj.append("age", 23); qobj.append("sex", "男"); DBObject robj = coll.findOne(qobj); System.out.println(robj.toString());
和C#同樣若是想從secondary節點進行讀取操做也是須要設置ReadPreference:
ReadPreference preference = ReadPreference.secondary(); DBObject robj = coll.findOne(qobj, qobj, preference);
不一樣的是Java驅動發現副本集中某個成員鏈接不了會發出警告信息:
並且發現若是讀取不到的話Java驅動會進行不停的重試。
注:設置驅動的ReadReference也能夠經過MongoDB鏈接字符串配置:mongodb://example1.com,example2.com,example3.com/?readPreference=secondary。經過鏈接字符串指定的read preference是針對整個鏈接。