MongoDB複本集實現及讀寫分離

來源:互聯網
上載者:User

MongoDB複本集實現及讀寫分離

在前面這篇文章“MongoDB的主從模式搭建執行個體”中,我們對如何搭建一個主從結構的Mongodb伺服器環境進行了簡單的介紹。但是對於主從結構,Mongodb官方並不推薦我們使用了,可能是因為主從模式存在以下兩個缺點:

(1)主節點不可用之後,無法自動切換到從節點,無法確保業務訪問的不間斷性;

(2)所有的讀寫操作都是對主節點的,造成主節點的訪問壓力較大;

因此,Mongodb為我們提供了另外一種推薦的使用方法,那就是使用複本集ReplicaSets。在這篇文章中簡單描述一下複本集是如何?的,又是如何解決以上兩個問題的。


首先我們先來搭建一個複本集(因為沒有那麼多伺服器機器,這裡採用在一台機器上,使用不同的連接埠號碼類比不同的機器上的Mongodb執行個體)。

第一步:我們在原生1111、2222和3333三個連接埠上啟動三個不同的Mongodb執行個體;

mongod --port 1111 --dbpath F:/mongodb1/data/db --logpath F:/mongodb1/data/log/mongodb.log --replSet test --logappend
mongod --port 2222 --dbpath F:/mongodb2/data/db --logpath F:/mongodb2/data/log/mongodb.log --replSet test --logappend
mongod --port 3333 --dbpath F:/mongodb3/data/db --logpath F:/mongodb3/data/log/mongodb.log --replSet test --logappend

在這裡我們啟動了三個Mongodb執行個體,並指定了相應的資料目錄和日誌目錄,需要說明的是,這裡需要使用--replSet說明該Mongodb執行個體是複本集中的節點,而該複本集的名稱是test。

第二步:登入到一個執行個體上,編寫指令,將三個不同的Mongodb執行個體結合在一起形成一個完整的複本集;

config_test={"_id":"test",members:[
    {_id:0,host:"127.0.0.1:1111"},
    {_id:1,host:"127.0.0.1:2222"},
    {_id:2,host:"127.0.0.1:3333"},
]};
這裡,members中可以包含多個值,這裡列舉的就是剛才啟動的三個Mongodb執行個體,並且通過_id欄位給複本集起了名字test。

第三步:通過執行下面的命令初始化複本集。

rs.initiate(config_test);

這裡使用上面的配置初始化Mongodb複本集。

通過上面的三步,便可以簡單的搭建起一個由三個Mongodb執行個體構成的名稱為test的複本集了。如果想查看複本集的狀態,可以使用rs.status()命令來進行查看。

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

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

在這裡,需要對返回資訊中的個別欄位進行簡單說明,health表示複本集中該節點是否正常,0表示不正常,1表示正常;state表示節點的身份,0表示非主節點,1表示主節點;stateStr用於對節點身份進行字元描述,PRIMARY表示主節點,SECONDARY表示副節點;name是複本集節點的ip和連接埠資訊,等等。

從返回包資訊中,可以看到關閉1111連接埠後,在複本集節點的狀態中該節點是不可達的,重新選取產生的主節點是3333連接埠上啟動的Mongodb執行個體,至於選取的流程在後面的文章中將會講到,這裡簡單講一點,當主節點掛掉之後,其他節點可以發起選舉行為,只要在選舉過程中某個節點得到複本集節點數一半以上的選票並且沒有節點投反對票,那麼該節點就可以成為主節點。

在1111連接埠上的Mongodb執行個體掛掉之後,3333成為了新的主節點,可以實現自動切換,因此解決了第一個問題。

至於第二個問題,那就是主節點負責所有的讀寫操作造成主節點壓力較大,那麼在複本集中如何解決這個問題了呢?正常情況下,我們在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" , 1111);
   ServerAddress address2 = new ServerAddress("127.0.0.1" , 2222);
   ServerAddress address3 = new ServerAddress("127.0.0.1" , 3333);
   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( "key1", "value1" );
   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" , 1111);
   ServerAddress address2 = new ServerAddress("127.0.0.1" , 2222);
   ServerAddress address3 = new ServerAddress("127.0.0.1" , 3333);
   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( "key1", "value1" );
   ReadPreference preference = ReadPreference.secondary(); 
   DBObject dbObject = coll.findOne(object, null , preference); 
   System. out .println(dbObject); 
  } catch (Exception e) {
   e.printStackTrace(); 
        }
 }
}

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

primary:預設參數,只從主節點上進行讀取操作;
primaryPreferred:大部分從主節點上讀取資料,只有主節點不可用時從secondary節點讀取資料。
secondary:只從secondary節點上進行讀取操作,存在的問題是secondary節點的資料會比primary節點資料“舊”。
secondaryPreferred:優先從secondary節點進行讀取操作,secondary節點不可用時從主節點讀取資料;
nearest:不管是主節點、secondary節點,從網路延遲最低的節點上讀取資料。

這樣便實現了在複本集上的讀寫分離了,也就解決了文章最上面所說的第二個問題了。至於複本集中另一個比較重要的地方,主從資料如何同步?如何選舉產生新的主節點?複本集中的各個節點如何資訊同步?這些問題,將另起一篇文章進行描述,如敢興趣,可以關注,謝謝。^_^

更多MongoDB相關教程見以下內容:

CentOS 編譯安裝 MongoDB與mongoDB的php擴充

CentOS 6 使用 yum 安裝MongoDB及伺服器端配置

Ubuntu 13.04下安裝MongoDB2.4.3

MongoDB入門必讀(概念與實戰並重)

Ubunu 14.04下MongoDB的安裝指南

《MongoDB 權威指南》(MongoDB: The Definitive Guide)英文文字版[PDF]

Nagios監控MongoDB分區叢集服務實戰

基於CentOS 6.5作業系統搭建MongoDB服務

MongoDB 的詳細介紹:請點這裡
MongoDB 的:請點這裡

本文永久更新連結地址:

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.