1. 程式人生 > >十分鐘搞定mongodb副本集

十分鐘搞定mongodb副本集

Java mongodb

mongodb副本集配置

最近項目中用到了mongodb,由於是用mongodb來記錄一些程序的日誌信息和日常的統計,為了增加應用的可靠性,一直在找mongodb集群的一些資料,下面是對最近做的一個小案例過程進行了一下總結記錄。

一.先介紹一下副本集是什麽?

副本集(復制)是將數據同步到多臺服務器的過程,提供的數據的冗余備份,並且在多個服務器上存儲數據的副本,提高了數據的可用性,也降低了數據的損壞風險,提高的安全性,並且可以實現故障的自動的切換恢復。

二.副本集的組成結構是什麽?

一個副本集的最小結構有用三個成員。一個三個成員的副本集可以有三個成員保存數據,或者有兩個保存,一個為監督者。即一個主節點(Primary),一個從節點(Secondary),一個監督者(Arbiter),監督者不存儲數據,監督者的作用主要是當主節點不可用時從從節點中選中主節點。如下圖:

技術分享圖片

請點擊此處輸入圖片描述

三.下面我們就按步驟小試牛刀一下?

第一步:

我們在本機的1001、1002和1003三個端口上啟動三個不同的Mongodb實例; mongod --port 1001 --dbpath F:/mongos/mongodb1/data --logpath F:/mongos/mongodb1/log/mongodb.log --pidfilepath F:/mongos/mongodb1/mongodb1.pid <br> --replSet test --logappend --directoryperdb

mongod --port 1002 --dbpath F:/mongos/mongodb2/data --logpath F:/mongos/mongodb2/log/mongodb.log --pidfilepath F:/mongos/mongodb2/mongodb2.pid <br> --replSet test --logappend --directoryperdb

mongod --port 1003 --dbpath F:/mongos/mongodb3/data --logpath F:/mongos/mongodb3/log/mongodb.log --pidfilepath F:/mongos/mongodb3/mongodb3.pid <br> --replSet test --logappend --directoryperdb

到這裏,members中可以包含多個值,這裏列舉的就是剛才啟動的三個Mongodb實例,並且通過_id字段給副本集起了名字test。

第三步:

通過執行下面的命令初始化副本集。

1

rs.initiate(config_test);

下面的命令可以查看副本集的狀態。

1

rs.status();

到這裏搭建起一個由三個Mongodb實例構成的名稱為test的副本集了。

副本集現在搭建起來了,那麽這個副本集能不能解決我們上面主從模式的兩個問題呢?

我們首先從第一個問題開始看,我們將1001端口的Mongodb服務器給關閉,然後我們使用rs.status()命令來查看下,如下所示:

技術分享圖片

請點擊此處輸入圖片描述

從返回包信息中,可以看到關閉1001端口後,在副本集節點的狀態中該節點是不可達的,重新選取產生的主節點是1002端口上啟動的Mongodb實例,選舉過程是這樣的,當主節點掛掉之後,其他節點可以發起選舉行為,只要在選舉過程中某個節點得到副本集節點數一半以上的選票並且沒有節點投反對票,那麽該節點就可以成為主節點。(參數註釋請看開始位置)在1001端口上的Mongodb實例掛掉之後,1002成為了新的主節點,可以實現故障自動切換。

至於第二個問題,那就是主節點負責所有的讀寫操作造成主節點壓力較大,那麽在副本集中如何解決這個問題了呢?正常情況下,我們在Java中訪問副本集是這樣的,如下所示:

public class TestMongoDBReplSet {  
   public static void main(String[] args)  {  
       try {  
           List<ServerAddress> addresses = new ArrayList<ServerAddress>();    
           ServerAddress address1 = new ServerAddress("127.0.0.1",1001);  
           ServerAddress address2 = new ServerAddress("127.0.0.1",1002);  
           ServerAddress address3 = new ServerAddress("127.0.0.1",1003);  
           addresses.add(address1);    
           addresses.add(address2);  
           addresses.add(address3);  
           MongoClient client = new MongoClient(addresses);  
           DB db = client.getDB( "testdb");  
           DBCollection coll = db.getCollection( "testdb");  
           // 插入  
           BasicDBObject object = new BasicDBObject();    
           object.append("userid","001");  
           coll.insert(object);  
           DBCursor dbCursor = coll.find();  
           while (dbCursor.hasNext()) {  
               DBObject dbObject = dbCursor.next();    
               System. out.println(dbObject.toString());  
           }  
       } catch (Exception e) {  
           e.printStackTrace();    
       }  
   }  
}


但是上面不能做到在副本集中讀寫壓力分散,在代碼層面我們可以設置再訪問副本集的時候只從副節點上讀取數據。為了在副本集上實現讀寫分離,我們需要實現以下兩步:

(1)在副本節點上設置setSlaveOk;

(2)代碼層面,在讀操作過程中設置從副本節點讀取數據,如下所示:

public class TestMongoDBReplSet {

public static void main(String[] args) {

try {

List<ServerAddress> addresses = new ArrayList<ServerAddress>();

ServerAddress address1 = new ServerAddress("127.0.0.1",1001);

ServerAddress address2 = new ServerAddress("127.0.0.1",1002);

ServerAddress address3 = new ServerAddress("127.0.0.1",1003);

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("userid","001");

ReadPreference preference = ReadPreference.secondary();

DBObject dbObject = coll.findOne(object, null , preference);

System. out .println(dbObject);

} catch (Exception e) {

e.printStackTrace();

}

}

}

上面代碼中的讀參數除了secondary以外,還有其他幾個參數可以使用,他們的含義分別如下所示:

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

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

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

nearest:不管是主節點、secondary節點,從網絡延遲最低的節點上讀取數據。

四.最後對使用到的參數進行了一下總結方便以後記憶和復習?

dbpath:數據存放目錄

logpath:日誌存放路徑

pidfilepath:進程文件,方便停止mongodb

directoryperdb:為每一個數據庫按照數據庫名建立文件夾存放

logappend:以追加的方式記錄日誌

replSet:replica set的名字

bind_ip:mongodb所綁定的ip地址

port:mongodb進程所使用的端口號,默認為27017

oplogSize:mongodb操作日誌文件的最大大小。單位為Mb,默認為硬盤剩余空間的5%

fork:以後臺方式運行進程

noprealloc:不預先分配存儲

priority:優先級,返回時0-100,數組越大,優先級越高,默認是1,0不進行選舉

如果你在Java開發工作中遇到困難,或者學習遇到瓶頸,歡迎加入我們Java總群:309603235,解決各種坑 爹的Java問題,群內有Java技術大牛,為您解決Java工作、學習中遇到的問題,歡迎菜鳥,老鳥入坑。


十分鐘搞定mongodb副本集