MongoDB的數(shù)據(jù)復(fù)制分片

個(gè)人博客地址:https://www.aolens.cn/?p=683

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊、虛擬主機(jī)、營銷軟件、網(wǎng)站建設(shè)、沂南網(wǎng)站維護(hù)、網(wǎng)站推廣。


一:MongoDB的簡介:

    MongoDB是一個(gè)高性能,開源,無模式的文檔型數(shù)據(jù)庫,是當(dāng)前NoSql數(shù)據(jù)庫中比較熱門的一種。它在許多場景下可用于替代傳統(tǒng)的關(guān)系型數(shù)據(jù)庫或鍵/值存儲(chǔ)方式。而且可以很容易的和JSON類的數(shù)據(jù)結(jié)合,他不支持事務(wù),但支持自動(dòng)分片功能,這對大數(shù)據(jù)的分布式存儲(chǔ)有著十分重要的作用。

二:MongoDB的索引類型:

    單字段索引:

    組合索引(多字段索引):對多個(gè)key做索引

    多鍵索引:對key和value中的key做索引

    空間索引:基于位置做索引

    文本索引:全文搜索

    hash索引:僅支持精確值查找

    稀疏索引(sparse):不為每一個(gè)值做索引,一般得是順序排放才可以做稀疏索引

三:MongoDB的復(fù)制功能:

    MongoDB有兩種復(fù)制類型:Master/Slave主從和replica set副本集復(fù)制,但是由于MongoDB的特性,主從復(fù)制架構(gòu)已經(jīng)基本放棄,比較常見的就是副本集復(fù)制方式

    replica set的工作特性:

    1,復(fù)制集可以實(shí)現(xiàn)自動(dòng)轉(zhuǎn)移 heartbeat超時(shí),自動(dòng)失效轉(zhuǎn)移(通過選舉方式實(shí)現(xiàn))

    2,至少有3個(gè)節(jié)點(diǎn),且奇數(shù)個(gè)節(jié)點(diǎn),可以使用arbiter來參與選舉

    復(fù)制集中的特殊類型的節(jié)點(diǎn)分類:

    0優(yōu)先級的節(jié)點(diǎn):冷備節(jié)點(diǎn),不會(huì)被選舉成為主節(jié)點(diǎn),但可以參與選舉

    被隱藏的從節(jié)點(diǎn):首先是一個(gè)0優(yōu)先級的從節(jié)點(diǎn),擁有選舉權(quán),不會(huì)被客戶端直接訪問到

    延遲復(fù)制的從節(jié)點(diǎn):是一個(gè)0優(yōu)先級的從節(jié)點(diǎn),不能被選為主節(jié)點(diǎn),且復(fù)制時(shí)間落后與主節(jié)點(diǎn)一個(gè)固定的時(shí)長。

    arbiter:仲裁者,沒有數(shù)據(jù),不可能成為主節(jié)點(diǎn)。

實(shí)驗(yàn)內(nèi)容:

一,實(shí)現(xiàn)MongoDB數(shù)據(jù)的復(fù)制

實(shí)驗(yàn)?zāi)P停?/strong>

MongoDB的數(shù)據(jù)復(fù)制分片

實(shí)驗(yàn)環(huán)境:

node1:172.16.18.1 MongoDB   centos6.5

node2:172.16.18.2 MongoDB   centos6.5

node3:172.16.18.3 MongoDB   centos6.5

實(shí)驗(yàn)內(nèi)容:

首先要確定各節(jié)點(diǎn)的時(shí)間一致

1.1 MongoDB安裝:分別在node1,node2,node3節(jié)點(diǎn)安裝一下三個(gè)包

mogodb安裝需要:一下三個(gè)包

    mongodb-org-shell-2.6.4-1.x86_64.rpm

    mongodb-org-tools-2.6.4-1.x86_64.rpm

    mongodb-org-server-2.6.4-1.x86_64.rpm

編輯服務(wù)器的配置文件,/etc/mongod.conf

logpath=/var/log/mongodb/mongod.log            #日志的路徑
logappend=true                                                 #開啟日志
fork=true                                                            
#port=27017                                                     #默認(rèn)監(jiān)聽的端口
#dbpath=/var/lib/mongo                                   #默認(rèn)的數(shù)據(jù)路徑
dbpath=/mongodb/data                                     #自定義的數(shù)據(jù)路徑
pidfilepath=/var/run/mongodb/mongod.pid
#bind_ip=127.0.0.1                                           #定義綁定IP,也就是監(jiān)聽那些IP可來鏈接服務(wù)器,注銷是允許所有。
httpinterface=true                                              #開放web頁面,
rest=true
replSet=testset
replIndexPrefetch=_id_only

配置好后將配置分別發(fā)送到其他兩個(gè)節(jié)點(diǎn),并創(chuàng)建數(shù)據(jù)目錄,修改權(quán)限

mkdir /mongodb/data/ -pv  
chown -R mongod.mongod /mongodb/

全部啟動(dòng):可能啟動(dòng)會(huì)比較慢,那是因?yàn)橐跏蓟瘮?shù)據(jù)

1.2鏈接到數(shù)據(jù)庫

[root@node2 ~]# mongo    
MongoDB shell version: 2.6.4    
connecting to: test    
> rs.status()    
{    
"startupStatus" : 3,    
"info" : "run rs.initiate(...) if not yet done for the set",    
"ok" : 0,    
"errmsg" : "can't get local.system.replset config from self or any seed (EMPTYCONFIG)"  
}

使用rs.status()查看狀態(tài),有3個(gè)節(jié)點(diǎn),但是都沒有初始化配置。需要運(yùn)行rs.initiate()

1.3運(yùn)行rs.initiate()

> rs.initiate()
{
"info2" : "no configuration explicitly specified -- making one",
"me" : "node2.aolens.com:27017",
"info" : "Config now saved locally. Should come online in about a minute.",
"ok" : 1
}
testset:OTHER> rs.status()
{
"set" : "testset",
"date" : ISODate("2014-10-12T07:51:58Z"),
"myState" : 1,
"members" : [
  {
   "_id" : 0,
   "name" : "node2.aolens.com:27017",
   "health" : 1,
   "state" : 1,
   "stateStr" : "PRIMARY",
   "uptime" : 920,
   "optime" : Timestamp(1413100302, 1),
   "optimeDate" : ISODate("2014-10-12T07:51:42Z"),
   "electionTime" : Timestamp(1413100302, 2),
   "electionDate" : ISODate("2014-10-12T07:51:42Z"),
   "self" : true
  }
],
"ok" : 1
}
testset:PRIMARY>

可以看到添加了一個(gè)節(jié)點(diǎn)node2,也就是自己,且是primary節(jié)點(diǎn)。以及所有的狀態(tài)

1.4添加其他兩個(gè)節(jié)點(diǎn)

testset:PRIMARY> rs.add("node1.aolens.com")
{ "ok" : 1 }
testset:PRIMARY> rs.add("node3.aolens.com")
{ "ok" : 1 }
用rs.status()查看
testset:PRIMARY> rs.status()
{
"set" : "testset",
"date" : ISODate("2014-10-12T08:03:48Z"),
"myState" : 1,
"members" : [
  {
   "_id" : 0,
   "name" : "node2.aolens.com:27017",
   "health" : 1,
   "state" : 1,
   "stateStr" : "PRIMARY",
   "uptime" : 1630,
   "optime" : Timestamp(1413101019, 1),
   "optimeDate" : ISODate("2014-10-12T08:03:39Z"),
   "electionTime" : Timestamp(1413100302, 2),
   "electionDate" : ISODate("2014-10-12T07:51:42Z"),
   "self" : true
  },
  {
   "_id" : 1,
   "name" : "node1.aolens.com:27017",
   "health" : 1,
   "state" : 5,
   "stateStr" : "STARTUP2",
   "uptime" : 17,
   "optime" : Timestamp(0, 0),
   "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
   "lastHeartbeat" : ISODate("2014-10-12T08:03:46Z"),
   "lastHeartbeatRecv" : ISODate("2014-10-12T08:03:47Z"),
   "pingMs" : 224
  },
  {
   "_id" : 2,
   "name" : "node3.aolens.com:27017",
   "health" : 1,
   "state" : 6,
   "stateStr" : "UNKNOWN",
   "uptime" : 8,
   "optime" : Timestamp(0, 0),
   "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
   "lastHeartbeat" : ISODate("2014-10-12T08:03:47Z"),
   "lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
   "pingMs" : 905,
   "lastHeartbeatMessage" : "still initializing"
  }
],
"ok" : 1
}

有沒有發(fā)現(xiàn)新加的這兩個(gè)節(jié)點(diǎn)狀態(tài)不對?沒有關(guān)系,可能是還沒有同步過來,稍等在刷新試試

"name" : "node1.aolens.com:27017",

"stateStr" : "SECONDARY",

"name" : "node3.aolens.com:27017",

"stateStr" : "SECONDARY",

再刷新時(shí)添加的兩個(gè)節(jié)點(diǎn)都成為了secondary。

1.5我們在主節(jié)點(diǎn)來創(chuàng)建一些數(shù)據(jù)

testset:PRIMARY> use test
switched to db test
testset:PRIMARY> for (i=1;i<=1000;i++) db.students.insert({name:"student"+i,age:(i%100)})
WriteResult({ "nInserted" : 1 })
連接到從節(jié)點(diǎn)來看一下
[root@node1 ~]# mongo    
MongoDB shell version: 2.6.4    
connecting to: test    
Welcome to the MongoDB shell.    
For interactive help, type "help".    
For more comprehensive documentation, see    
http://docs.mongodb.org/    
Questions? Try the support group    
http://groups.google.com/group/mongodb-user    
testset:SECONDARY> use test    
switched to db test    
testset:SECONDARY> show collections    
2014-10-11T14:52:57.103+0800 error: { "$err" : "not master and slaveOk=false", "code" : 13435 } at src/mongo/shell/query.js:131    
#提示需要不是主節(jié)點(diǎn),沒有slaveOK不讓查看,那么便在當(dāng)前節(jié)點(diǎn)指定slaveOK,便可以了
testset:SECONDARY> rs.slaveOk()
testset:SECONDARY> show collections
students
system.indexes
可以使用rs.isMaster()查詢主節(jié)點(diǎn)是誰
testset:SECONDARY> rs.isMaster()
{
"setName" : "testset",
"setVersion" : 3,
"ismaster" : false,
"secondary" : true,
"hosts" : [
  "node1.aolens.com:27017",
  "node3.aolens.com:27017",
  "node2.aolens.com:27017"
],
"primary" : "node2.aolens.com:27017",         #主節(jié)點(diǎn)是誰
"me" : "node1.aolens.com:27017",              #自己是誰
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 1000,
"localTime" : ISODate("2014-10-11T07:00:03.533Z"),
"maxWireVersion" : 2,
"minWireVersion" : 0,
"ok" : 1
}

1.6如果主節(jié)點(diǎn)離線,從節(jié)點(diǎn)會(huì)自動(dòng)選出主節(jié)點(diǎn)

testset:PRIMARY> rs.stepDown()
2014-10-12T17:00:12.869+0800 DBClientCursor::init call() failed
2014-10-12T17:00:12.896+0800 Error: error doing query: failed at src/mongo/shell/query.js:81
2014-10-12T17:00:12.914+0800 trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2014-10-12T17:00:12.945+0800 reconnect 127.0.0.1:27017 (127.0.0.1) ok
testset:SECONDARY>

可以看到主節(jié)點(diǎn)的primary變成了secondary

其他兩個(gè)節(jié)點(diǎn)中的一個(gè)變?yōu)橹鞴?jié)點(diǎn),這就是自動(dòng)轉(zhuǎn)移

副本集的重新選舉的條件有:心態(tài)信息,優(yōu)先級,optime,網(wǎng)絡(luò)連接等

1.7還可以修改優(yōu)先級來實(shí)現(xiàn)主從切換

testset:PRIMARY> rs.conf()            #查看配置
{
"_id" : "testset",
"version" : 3,
"members" : [
  {
   "_id" : 0,
   "host" : "node2.aolens.com:27017"
  },
  {
   "_id" : 1,
   "host" : "node1.aolens.com:27017"
  },
  {
   "_id" : 2,
   "host" : "node3.aolens.com:27017"
  }
]
}
testset:PRIMARY> cfg=rs.conf()            #將配置信息保存在變量中
{
"_id" : "testset",
"version" : 3,
"members" : [
  {
   "_id" : 0,
   "host" : "node2.aolens.com:27017"
  },
  {
   "_id" : 1,
   "host" : "node1.aolens.com:27017"
  },
  {
   "_id" : 2,
   "host" : "node3.aolens.com:27017"
  }
]
}
testset:PRIMARY> cfg.members[1].priority=2            #修改id=1的主機(jī)優(yōu)先級為2
2
testset:PRIMARY> rs.reconfig(cfg)                              #應(yīng)用cfg文件
2014-10-12T05:15:59.916-0400 DBClientCursor::init call() failed
2014-10-12T05:15:59.988-0400 trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2014-10-12T05:16:00.015-0400 reconnect 127.0.0.1:27017 (127.0.0.1) ok
reconnected to server after rs command (which is normal)
testset:SECONDARY>                                                    #主動(dòng)變?yōu)閺墓?jié)點(diǎn)
而id=1的是node1.aolens.com主機(jī),自己變?yōu)閜rimary主機(jī)
testset:SECONDARY>
testset:PRIMARY>

1.8,如何要設(shè)定仲裁節(jié)點(diǎn)

rs.addArb(hostportstr)表示將一個(gè)節(jié)點(diǎn)加進(jìn)來時(shí)就是仲裁節(jié)點(diǎn)。

我們移除當(dāng)前的node3節(jié)點(diǎn)

testset:PRIMARY> rs.remove("node3.aolens.com")

刪除/mongodb/data下的數(shù)據(jù),重新初始化,

testset:PRIMARY> rs.addArb("node3.aolens.com")

二,實(shí)現(xiàn)MongoDB數(shù)據(jù)的的切片

MongoDB的分片(sharding):

    為什么要分片:CPU,Memory,IO等無法滿足要求。

    橫行拓展:就需要將數(shù)據(jù)分片放到不同的節(jié)點(diǎn)

    MongoDB的數(shù)據(jù)復(fù)制分片

    為了保證shard的大小均衡:是將主節(jié)點(diǎn)的數(shù)據(jù)按照順序分成大小相同的塊,分別存在不同的sharding節(jié)點(diǎn)上。

分片架構(gòu)中的角色:

    mongos:Router服務(wù)器

    config server:元數(shù)據(jù)服務(wù)器

    shard:數(shù)據(jù)節(jié)點(diǎn),也成mongod實(shí)例

    MongoDB的數(shù)據(jù)復(fù)制分片

分片需要滿足:寫離散,讀集中的思想

實(shí)驗(yàn)環(huán)境:

node1:172.16.18.1 mongos router節(jié)點(diǎn)

node2:172.16.18.2 mongod shard節(jié)點(diǎn)

node3:172.16.18.3 mongod shard節(jié)點(diǎn)

node4:172.16.17.12 config server

實(shí)驗(yàn)?zāi)P停?/p>

MongoDB的數(shù)據(jù)復(fù)制分片

實(shí)驗(yàn)內(nèi)容:

2.1首先來配置config server

其實(shí)config server也就是mongod,只是要指明他就是config server

logpath=/var/log/mongodb/mongod.log
logappend=true
fork=true
#port=27017
dbpath=/mongodb/data
pidfilepath=/var/run/mongodb/mongod.pid
啟動(dòng)config server節(jié)點(diǎn)。會(huì)發(fā)現(xiàn)他監(jiān)聽在27019端口
[root@node3 mongodb-2.6.4]# service mongod start    
Starting mongod: [ OK ]    
[root@node3 mongodb-2.6.4]# ss -tnl    
State Recv-Q Send-Q Local Address:Port Peer Address:Port    
LISTEN 0 128 *:27019 *:*

2.2配置router節(jié)點(diǎn)

安裝mongodb-org-mongos.x86_64程序包

直接啟動(dòng)即可:

[root@node1 ~]# mongos --configdb=172.16.17.12:27019 --fork --logpath=/var/log/mongodb/mongos.log
2014-10-11T20:29:43.617+0800 warning: running with 1 config server should be done only for testing purposes and is not recommended for production
about to fork child process, waiting until server is ready for connections.
forked process: 8766
child process started successfully, parent exiting

啟動(dòng)成功

需要指定config server的地址 --fork后臺運(yùn)行,--logpath指明log位置

2.3配置shard節(jié)點(diǎn),shard節(jié)點(diǎn)就是正常的mongod節(jié)點(diǎn),無需什么多的配置

logpath=/var/log/mongodb/mongod.log
logappend=true
fork=true
#port=27017
dbpath=/mongodb/data
pidfilepath=/var/run/mongodb/mongod.pid

啟動(dòng)node2,node3

2.4鏈接在mongos上查看

[root@node1 ~]# mongo --host 172.16.18.1    MongoDB shell version: 2.6.4    connecting to: 172.16.18.1:27017/test
添加兩個(gè)shard節(jié)點(diǎn):   mongos> sh.addShard("172.16.18.2")
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> sh.addShard("172.16.18.3")
{ "shardAdded" : "shard0001", "ok" : 1 }
mongos> sh.status()
--- Sharding Status ---
  sharding version: {
"_id" : 1,
"version" : 4,
"minCompatibleVersion" : 4,
"currentVersion" : 5,
"clusterId" : ObjectId("543922b81aaf92ac0f9334f8")
}
  shards:
{ "_id" : "shard0000", "host" : "172.16.18.2:27017" }
{ "_id" : "shard0001", "host" : "172.16.18.3:27017" }
  databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }

對數(shù)據(jù)分片是需要分片的一般為大數(shù)據(jù),如果一個(gè)collection中的數(shù)據(jù)很少,就沒有必要做shard,而未做分片的數(shù)據(jù)會(huì)放在主shard上。

下來我們先來啟動(dòng)shard功能

mongos> sh.status()
--- Sharding Status ---
  sharding version: {
"_id" : 1,
"version" : 4,
"minCompatibleVersion" : 4,
"currentVersion" : 5,
"clusterId" : ObjectId("543922b81aaf92ac0f9334f8")
}
  shards:
{ "_id" : "shard0000", "host" : "172.16.18.2:27017" }
{ "_id" : "shard0001", "host" : "172.16.18.3:27017" }
  databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "test", "partitioned" : false, "primary" : "shard0000" }
{ "_id" : "testdb", "partitioned" : true, "primary" : "shard0000" }

下來我們手動(dòng)分片試試

mongos> sh.shardCollection("testdb.students",{"age":1})            #對age來分片
{ "collectionsharded" : "testdb.students", "ok" : 1 }
mongos> sh.status()
--- Sharding Status ---
  sharding version: {
"_id" : 1,
"version" : 4,
"minCompatibleVersion" : 4,
"currentVersion" : 5,
"clusterId" : ObjectId("543922b81aaf92ac0f9334f8")
}
  shards:
{ "_id" : "shard0000", "host" : "172.16.18.2:27017" }
{ "_id" : "shard0001", "host" : "172.16.18.3:27017" }
  databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "test", "partitioned" : false, "primary" : "shard0000" }
{ "_id" : "testdb", "partitioned" : true, "primary" : "shard0000" }
  testdb.students
   shard key: { "age" : 1 }
   chunks:
    shard0000 1
   { "age" : { "$minKey" : 1 } } -->> { "age" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 0)
可是我們此時(shí)沒有數(shù)據(jù),那么便來生成一些數(shù)據(jù)吧
mongos> for (i=1;i<=100000;i++) db.students.insert({name:"student"+i,age:(i%100),addr:"china"})
mongos> sh.status()
--- Sharding Status ---
  sharding version: {
"_id" : 1,
"version" : 4,
"minCompatibleVersion" : 4,
"currentVersion" : 5,
"clusterId" : ObjectId("543922b81aaf92ac0f9334f8")
}
  shards:
{ "_id" : "shard0000", "host" : "172.16.18.2:27017" }
{ "_id" : "shard0001", "host" : "172.16.18.3:27017" }
  databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "test", "partitioned" : false, "primary" : "shard0000" }
{ "_id" : "testdb", "partitioned" : true, "primary" : "shard0000" }
  testdb.students
   shard key: { "age" : 1 }
   chunks:
  shard0001 1
    shard0000 2
   { "age" : { "$minKey" : 1 } } -->> { "age" : 1 } on : shard0001 Timestamp(2, 0)
   { "age" : 1 } -->> { "age" : 99 } on : shard0000 Timestamp(2, 2)
   { "age" : 99 } -->> { "age" : { "$maxKey" : 1 } } on : shard0000 Timestamp(2, 3)

會(huì)發(fā)現(xiàn)把數(shù)據(jù)分到了不同的chunk上

數(shù)據(jù)分片就實(shí)現(xiàn)了,當(dāng)然一般不建議手動(dòng)分片。

總結(jié):mongod在大數(shù)據(jù)處理還有主從復(fù)制上都有著比MySQL更加優(yōu)秀的性能和更加簡單的操作。但由于mongod尚不是很成熟,在實(shí)際的應(yīng)用中還有許多要解決的問題。需要使用著慢慢摸索。

網(wǎng)頁名稱:MongoDB的數(shù)據(jù)復(fù)制分片
網(wǎng)頁路徑:http://bm7419.com/article28/ipohjp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機(jī)、ChatGPT建站公司、服務(wù)器托管、網(wǎng)頁設(shè)計(jì)公司、用戶體驗(yàn)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)