在之前的《MongoDB分布式部署》中已經(jīng)提到,同一組數(shù)據(jù)庫服務(wù)器上的數(shù)據(jù)是支持復(fù)制的。mongodb支持兩種方式的數(shù)據(jù)復(fù)制,簡單的主從配置和互為主從的配置。MongoDB分布式部署之分片配置可見http://hi.baidu.com/lzpsky/blog/item/644e083d6bbd920cbaa16793.html 一、主從配置(Master Slave)主從數(shù)據(jù)庫需要兩個(gè)數(shù)據(jù)庫節(jié)點(diǎn)即可,一主一從(并不一定非得兩臺(tái)獨(dú)立的服務(wù)器,可使用--dbpath參數(shù)指定數(shù)據(jù)庫目錄)。$ bin/mongod --master [--dbpath /data/masterdb/] 于是,主服務(wù)器進(jìn)程就會(huì)創(chuàng)建一個(gè)local.oplog.$main數(shù)據(jù)集,即"transaction log",以記錄從服務(wù)器需要的操作隊(duì)列信息。配置一個(gè)從數(shù)據(jù)庫節(jié)點(diǎn):$ bin/mongod --slave --source <masterhostname>[:<port>] [--dbpath /data/slavedb/]主節(jié)點(diǎn)的信息會(huì)存放在從節(jié)點(diǎn)的 local.sources數(shù)據(jù)集中,也可以不指定--source參數(shù),而是往local.sources中增加一條包含主節(jié)點(diǎn)信息的記錄。
$ bin/mongo <slavehostname>/local > db.sources.find(); // confirms the collection is empty. then:> db.sources.insert( { host: <masterhostname> } ); host:<masterhostname> 主節(jié)點(diǎn)的ip地址或域名全稱,可跟上:port指定端口。如果指定了only: databasename (optional) ,表示只有指定的數(shù)據(jù)庫才復(fù)制,注:v1.2.1+修復(fù)了only的一個(gè)bug。一個(gè)從節(jié)點(diǎn)可以有多個(gè)主節(jié)點(diǎn),這種情況下,local.sources中會(huì)有多條配置信息。 一臺(tái)服務(wù)器可以同時(shí)即為主也為從。如果一臺(tái)從節(jié)點(diǎn)與主節(jié)點(diǎn)不同步,比如從節(jié)點(diǎn)的數(shù)據(jù)更新遠(yuǎn)遠(yuǎn)跟不上主節(jié)點(diǎn)或者從節(jié)點(diǎn)中斷之后重啟但主節(jié)點(diǎn)中相關(guān)的數(shù)據(jù)更新日志卻不可用了。這種情況下,復(fù)制操作將會(huì)終止,需要管理者的介入,看是否默認(rèn)需要重啟復(fù)制操作。管理者可以使用{resync:1} 命令重啟復(fù)制操作,可選命令行參數(shù) --autoresync可使從節(jié)點(diǎn)在不同步情況發(fā)生10秒鐘之后,自動(dòng)重啟復(fù)制操作。如果指定了--autoresync參數(shù),從節(jié)點(diǎn)在10分鐘以內(nèi)自動(dòng)重新同步數(shù)據(jù)的操作只會(huì)執(zhí)行一次。
--oplogSize命令行參數(shù)(與--master一同使用)配置用于存儲(chǔ)給從節(jié)點(diǎn)可用的更新信息占用的磁盤空間(M為單位),如果不指定這個(gè)參數(shù),默認(rèn)大小為當(dāng)前可用磁盤空間的5%(64位機(jī)器最小值為1G,32位機(jī)器為50M)。安全性方面:$ dbshell <slavehostname>/admin -u <existingadminusername> -p<adminpassword>> use local > db.addUser('repl', <replpassword>);^c $ dbshell <masterhostname>/admin -u <existingadminusername> -p<adminpassword> > use local > db.addUser('repl', <replpassword>);
二、互為主從(Replica Pairs)
數(shù)據(jù)庫自動(dòng)協(xié)調(diào)某個(gè)時(shí)間點(diǎn)上的主從關(guān)系。開始的時(shí)候,數(shù)據(jù)庫會(huì)判斷哪個(gè)是從哪個(gè)是主,一旦主服務(wù)器負(fù)載過高,另一臺(tái)就會(huì)自動(dòng)成為主服務(wù)器。
$ ./mongod --pairwith <remoteserver> --arbiter <arbiterserver>remoteserver組中的其他服務(wù)器host,可加:port指定端口。arbiterserver 仲裁(arbiter )的host,也可指定端口。仲裁是一臺(tái)mongodb服務(wù)器,用于協(xié)助判斷某個(gè)時(shí)間點(diǎn)上的數(shù)據(jù)庫主從關(guān)系。如果同組服務(wù)器在同一個(gè)交換機(jī)或相同的ec2可用區(qū)域內(nèi),就沒必要使用仲裁了。如果同組服務(wù)器之間不能通信,可是使用運(yùn)行在第三方機(jī)器上的仲裁,使用“搶七”方式有效地敲定主服務(wù)器,也可不使用仲裁,這樣所有的服務(wù)器都假定是主服務(wù)器狀態(tài),可通過命令人工檢測當(dāng)前哪臺(tái)數(shù)據(jù)庫是主數(shù)據(jù)庫:$ ./mongo > db.$cmd.findOne({ismaster:1});{ "ismaster" : 0.0 , "remote" : "192.168.58.1:30001" , "ok" : 1.0 } 一致性:故障轉(zhuǎn)移機(jī)制只能夠保障組中的數(shù)據(jù)庫上的數(shù)據(jù)的最終一致性。如果機(jī)器L是主服務(wù)器,然后掛了,那么發(fā)生在它身上的最后幾秒鐘的操作信息就到達(dá)不了機(jī)器R,那么機(jī)器R在機(jī)器L恢復(fù)之前是不能執(zhí)行這些操作的。安全性:同主從的操作相同。數(shù)據(jù)庫服務(wù)器替換。當(dāng)一臺(tái)服務(wù)器失敗了,系統(tǒng)能自動(dòng)在線恢復(fù)。但當(dāng)一臺(tái)機(jī)器徹底掛了,就需要替換機(jī)器,而替換機(jī)器一開始是沒有數(shù)據(jù)的,怎么辦?以下會(huì)解釋如何替換一組服務(wù)器中的一臺(tái)機(jī)器。假設(shè)nodes(n1,n2)中的n2掛了,需要變成nodes(n1,n3)。1、假設(shè)n2徹底掛了下線了,不能在線恢復(fù)。2、需要告訴n1,你的搭檔已經(jīng)不是n2了而是n3。可使用replacepeer 命令,檢測該操作的返回值以確保操作成功。n1> ./mongo n1/admin> db.$cmd.findOne({replacepeer:1});{"info" : "adjust local.sources hostname; db restart now required" "ok" : 1.0} 3、使用以下命令重啟n1。n1> ./mongod --pairwith n3 --arbiter <arbiterserver> 4、啟動(dòng)n3。n3> ./mongod --pairwith n1 --arbiter <arbiterserver> 注意的是,n3在與n1數(shù)據(jù)完全同步之前不能接收作為主節(jié)點(diǎn)的任何操作。如果從節(jié)點(diǎn)設(shè)置了ok標(biāo)志(db.getMongo().setSlaveOk() ),就可以查詢從節(jié)點(diǎn)了。三、配置案例見《MongoDB分布式部署之分片配置》的第六個(gè)模塊——案例部分,有詳解。四、java案例1、鏈接mongodb:ServerAddress right = new ServerAddress("10.13.127.212", 18020);ServerAddress left = new ServerAddress("10.13.127.211", 18020);Mongo mongo = new Mongo(right, left);DB db = mongo.getDB("test");db.authenticate("test", "test".toCharArray());2、插入:BasicDBObject dbObject = new BasicDBObject();dbObject.put("id", i);dbObject.put("time", System.currentTimeMillis());coll.insert(dbObject);3、更新coll.update(new BasicDBObject("_id", id), getDBObjectByLabel(mongoLabel));4、查詢,查詢條件的表達(dá)式文檔:BasicDBObject dbObject = new BasicDBObject();dbObject.put("id", 1); //增加查詢條件BasicDBObject sortObject = new BasicDBObject(LabelConstant.ORDER_BY,LabelConstant.ORDER_DESC);DBCursor dbCursor = coll.find(dbObject); //不分頁不排序//cursor = coll.find(doc).skip((pageNo - 1) * pageSize).limit(pageSize).sort(sortObject); //分頁排序DBObject result = dbCursor.next(); //取數(shù)據(jù)