mongodb中的副本集搭建實踐


准備運行1個主節點,2個從節點,從節點中其中是一個是仲裁節點(Arb)。

sudo mongod --replSet application --dbpath /data/node1/ --port 9927 --oplogSize 1024
sudo mongod --replSet application --dbpath /data/node2/ --port 9928 --oplogSize 1024
sudo mongod --replSet application --dbpath /data/arbiter/ --port 9929 --oplogSize 1024

其中application是副本集的名稱,節點必須相同,–dbpath指定數據庫儲存路徑,–port指定偵聽端口,–oplogSize指定數據同步之前的緩存的空間大小,暫時指定1G。選擇9927端口的實例為主節點,進入9927的shell:

mongo localhost:9927

初始化副本集需要配置表,申明配置表如下:

config = {_id: "application", members: []}

注意_id和副本集啟動的共享名稱一致。下面來逐步添加節點的數據信息:

config.members.push({_id: 0, host: "localhost:9927"})
config.members.push({_id: 1, host: "localhost:9928"})
config.members.push({_id: 2, host: "localhost:9929", arbiterOnly: true})

也可以使用rs.add和rs.addArb函數來實現同樣的操作。然后需要用這個表作為參數初始化副本集,在9927端口的shell執行:

> rs.initiate(config)
{
  "info" : "Config now saved locally.  Should come online in about a minute.",
  "ok" : 1
}

返回ok為1表示初始化成功,三個節點互相檢測通信,需要1分鍾左右(反應夠慢的 ^-),可以查看三個終端窗口的信息確認,完成通信后,在9927端口的shell回車執行命令確認配置:

> rs.isMaster()
{
  "setName" : "application",
  "ismaster" : true,
  "secondary" : false,
  "hosts" : [
      "localhost:9927",
      "localhost:9928"
  ],
  "arbiters" : [
      "localhost:9929"
  ],
  "primary" : "localhost:9927",
  "me" : "localhost:9927",
  "maxBsonObjectSize" : 16777216,
  "localTime" : ISODate("2013-01-26T13:34:03.378Z"),
  "ok" : 1
}

注意到9927端口的實例ismaster是true,secondary為false,hosts有2個實例,arbiter有1個元素,primary關鍵key表示了主節點,通信完成幾次回車后可以看到9927的端口的實例shell的提示符已經改變,更改為application:PRIMARY,查看更詳細的信息:

application:PRIMARY> rs.status()
{
  "set" : "application",
  "date" : ISODate("2013-01-26T13:34:35Z"),
  "myState" : 1,
  "members" : [
      {
          "_id" : 0,
          "name" : "localhost:9927",
          "health" : 1,
          "state" : 1,
          "stateStr" : "PRIMARY",
          "uptime" : 140,
          "optime" : Timestamp(1359207200000, 1),
          "optimeDate" : ISODate("2013-01-26T13:33:20Z"),
          "self" : true
      },
      {
          "_id" : 1,
          "name" : "localhost:9928",
          "health" : 1,
          "state" : 2,
          "stateStr" : "SECONDARY",
          "uptime" : 63,
          "optime" : Timestamp(1359207200000, 1),
          "optimeDate" : ISODate("2013-01-26T13:33:20Z"),
          "lastHeartbeat" : ISODate("2013-01-26T13:34:34Z"),
          "pingMs" : 0
      },
      {
          "_id" : 2,
          "name" : "localhost:9929",
          "health" : 1,
          "state" : 7,
          "stateStr" : "ARBITER",
          "uptime" : 63,
          "lastHeartbeat" : ISODate("2013-01-26T13:34:34Z"),
          "pingMs" : 0
      }
  ],
  "ok" : 1
}

顯示了每個節點的健康狀況,名稱,啟動的時間,節點的類型等。查看當前副本集的配置表:

application:PRIMARY> rs.conf()
{
  "_id" : "application",
  "version" : 1,
  "members" : [
      {
          "_id" : 0,
          "host" : "localhost:9927"
      },
      {
          "_id" : 1,
          "host" : "localhost:9928"
      },
      {
          "_id" : 2,
          "host" : "localhost:9929",
          "arbiterOnly" : true
      }
  ]
}

插入測試數據:

application:PRIMARY> db.users.insert({username: "visionwang", age: 26})

進入9928從節點,執行查看集合:

application:SECONDARY> show collections
application:SECONDARY> show collections
Sat Jan 26 21:39:40 uncaught exception: error: { "$err" : "not master and slaveOk=false", "code" : 13435 }

發現shell拋出了異常,顯示slaveOK為false,當前副本集需要明確從節點參數,執行函數:

application:SECONDARY> rs.slaveOk()
application:SECONDARY> show collections
system.indexes
users

查詢測試數據:

application:SECONDARY> db.users.find()
{ "_id" : ObjectId("5103dbc8f556a05a96a28e69"), "username" : "visionwang", "age" : 26 }

插入數據沒有拋出異常,但是顯示not master,表示當前從節點是只讀的:

application:SECONDARY> db.users.insert({username: "nl", age: 25})
not master

切換到9927主節點,使用系統空間庫查詢副本集信息:

application:PRIMARY> db.system.replset.findOne()
{
  "_id" : "application",
  "version" : 1,
  "members" : [
      {
          "_id" : 0,
          "host" : "localhost:9927"
      },
      {
          "_id" : 1,
          "host" : "localhost:9928"
      },
      {
          "_id" : 2,
          "host" : "localhost:9929",
          "arbiterOnly" : true
      }
  ]
}
application:PRIMARY> db.getReplicationInfo()
{
  "logSizeMB" : 1024,
  "usedMB" : 0.01,
  "timeDiff" : 169,
  "timeDiffHours" : 0.05,
  "tFirst" : "Sat Jan 26 2013 21:33:20 GMT+0800 (CDT)",
  "tLast" : "Sat Jan 26 2013 21:36:09 GMT+0800 (CDT)",
  "now" : "Sat Jan 26 2013 21:48:07 GMT+0800 (CDT)"
}

進入9929端口,可以看到仲裁節點的提示符號:

mongo localhost:9929
application:ARBITER> 

執行故障轉移測試,可以ctrl+c掉9927的主節點,觀察終端信息提示,9927處於down狀態,9928從節點自舉為主節點,回車后發現shell提示符號已經更改為application:PRIMARY,再將9927上線,添加為從節點,再ctrl+c掉9928節點,經過少許時間,9927端口又恢復成主節點,再將9928上線,系統恢復到初始的副本集,仲裁節點的作用是協調leader選舉,監測系統運行狀態,提供節點互相通訊的數據信息。

mongodb也支持簡單的主從復制,但是有了強大的副本集,幾乎找不到什么理由使用簡單的主從復制策略,甚至mongodb的分片(auto-sharding)也是使用副本集實現。

51CTO也有一個windows上面的版本http://database.51cto.com/art/201301/379033.htm。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM