MongoDB在启用复制集(Replica Set)功能后,原先一个简单的索引添加,在之上会变得相对复杂,尤其是在数据量巨大的时候,需要考虑尽可能将性能影响降低到最小。基于此我们需要采取逐个节点创建索引的方式来达成。如下本文描述。
一、复制集索引创建的过程
MongoDB从节点上复制集上索引的创建,通常是在主节点索引创建完成之后。
在分片集群环境中,mongos将发送createindex()命令到每一个shard的主成员节点,
当主副本成员完成索引创建后,辅助副本开始创建索引。
二、如何最小化复制集上索引创建的影响?
确保你的oplog size足够大以允许索引或索引操作完成而不至于从节点有严重的滞后。
在索引创建期间,一个辅助成员脱离复制集,这将在某一个时间仅仅影响复制集的一个成员,而不是同时影响到所有的复制集成员
在2.6版本之前的后台索引创建操作在复制复制集成员上变成前台索引操作。2.6版本后则是后台创建索引。
三、复制集最小化索引创建影响的步骤
--
--
--
..
-- --
-
.
-
四、演示复制集创建索引
//演示环境描述
1、主节点上复制集相关信息
repSetTest:PRIMARY> db.
version()
3.2.11
repSetTest:PRIMARY> db.users.count()
1000000
repSetTest:PRIMARY> db.users.getIndexes()
[
{
"v" :
1,
"key" : {
"_id" :
1
},
"name" :
"_id_",
"ns" :
"test.users"
}
]
repSetTest:PRIMARY> rs.status()
{
"set" :
"repSetTest",
"date" : ISODate(
"2017-03-10T06:43:37.545Z"),
"myState" :
1,
"term" : NumberLong(
1),
"heartbeatIntervalMillis" : NumberLong(
2000),
"members" : [
{
"_id" :
0,
"name" :
"localhost:27000",
"health" :
1,
"state" :
1,
"stateStr" :
"PRIMARY",
.........
},
{
"_id" :
1,
"name" :
"localhost:27001",
"health" :
1,
"state" :
2,
"stateStr" :
"SECONDARY",
........
},
{
"_id" :
2,
"name" :
"localhost:27002",
"health" :
1,
"state" :
2,
"stateStr" :
"SECONDARY",
.......
}
],
"ok" :
1
}
repSetTest:PRIMARY> rs.printReplicationInfo()
configured oplog size:
128MB
log length start
to end: 201secs (0.06hrs)
oplog
first event
time: Fri Mar
10 2017 14:
17:
57 GMT+
0800 (CST)
oplog
last event
time: Fri Mar
10 2017 14:
21:
18 GMT+
0800 (CST)
now: Fri Mar
10 2017 14:
44:
00 GMT+
0800 (CST)
2、从节点
27001上添加索引
MongoDB
shell version:
3.2.11
connecting
to: localhost:
27001/test
repSetTest:SECONDARY> use admin
switched
to db admin
repSetTest:SECONDARY> db.shutdownServer()
server should be down...
>
MongoDB
shell version:
3.2.11
connecting
to: localhost:
27100/test
> db.users.count()
1000000
> db.users.find({},{
_id:
0}).limit(
1)
{
"i" :
0,
"username" :
"user0",
"age" :
109,
"created" : ISODate(
"2017-03-10T06:17:19.168Z") }
> db.users.createIndex({username:
1,created:
1})
{
"createdCollectionAutomatically" :
false,
"numIndexesBefore" :
1,
"numIndexesAfter" :
2,
"ok" :
1
}
MongoDB
shell version:
3.2.11
connecting
to: localhost:
27000/test
repSetTest:PRIMARY>
load(
'filling200w.js')
> db.stats()
{
"db" :
"test",
"collections" :
3,
"objects" :
1039732,
"avgObjSize" :
89.7096626823066,
"dataSize" :
93274007,
"storageSize" :
29040640,
"numExtents" :
0,
"indexes" :
5,
"indexSize" :
28250112,
"ok" :
1
}
> use admin
switched
to db admin
> db.shutdownServer()
>
MongoDB
shell version:
3.2.11
connecting
to: localhost:
27001/test
repSetTest:SECONDARY> rs.slaveOk()
repSetTest:SECONDARY> db.users.count()
1000038
repSetTest:SECONDARY> db.users.count()
1000040
repSetTest:SECONDARY> db.stats()
{
"db" :
"test",
"collections" :
3,
"objects" :
1039773,
"avgObjSize" :
89.70963469911221,
"dataSize" :
93277656,
"storageSize" :
29040640,
"numExtents" :
0,
"indexes" :
5,
"indexSize" :
28291072,
"ok" :
1
}
3、从节点
27002上添加索引
repSetTest:SECONDARY> use admin
repSetTest:SECONDARY> db.shutdownServer()
>
> db.users.count()
1000054
> db.users.getIndexes()
[
{
"v" :
1,
"key" : {
"_id" :
1
},
"name" :
"_id_",
"ns" :
"test.users"
}
]
> db.users.createIndex({username:
1,created:
1})
{
"createdCollectionAutomatically" :
false,
"numIndexesBefore" :
1,
"numIndexesAfter" :
2,
"ok" :
1
}
> use admin
> db.shutdownServer()
>
[root@ydq05 ~]
MongoDB
shell version:
3.2.11
connecting
to: localhost:
27002/test
repSetTest:SECONDARY> rs.status()
{
"set" :
"repSetTest",
"date" : ISODate(
"2017-03-10T08:16:29.440Z"),
"myState" :
2,
"term" : NumberLong(
1),
"syncingTo" :
"localhost:27001",
"heartbeatIntervalMillis" : NumberLong(
2000),
"members" : [
{
"_id" :
0,
"name" :
"localhost:27000",
"health" :
1,
"state" :
1,
"stateStr" :
"PRIMARY",
"uptime" :
22,
......
},
{
"_id" :
1,
"name" :
"localhost:27001",
"health" :
1,
"state" :
2,
"stateStr" :
"SECONDARY",
..........
},
{
"_id" :
2,
"name" :
"localhost:27002",
"health" :
1,
"state" :
2,
"stateStr" :
"SECONDARY",
....
}
],
"ok" :
1
}
4、主从节点切换
repSetTest:PRIMARY> db.users.count()
1000129
repSetTest:PRIMARY> use admin
switched
to db admin
repSetTest:PRIMARY> db.shutdownServer()
server should be down...
repSetTest:PRIMARY>
load(
'filling200w.js')
2017-
03-
10T16:
17:
31.513+
0800 I NETWORK [thread1] DBClientCursor::init call() failed
2017-
03-
10T16:
17:
31.514+
0800 E QUERY [thread1] Error: Error: error doing query: failed :
DBCollection.prototype.insert@src/mongo/
shell/collection.js:
358:
23
@filling200w.js:
2:
1
@(
shell):
1:
1
repSetTest:SECONDARY> rs.status()
{
"set" :
"repSetTest",
"date" : ISODate(
"2017-03-10T08:18:29.368Z"),
"myState" :
2,
"term" : NumberLong(
2),
"syncingTo" :
"localhost:27001",
"heartbeatIntervalMillis" : NumberLong(
2000),
"members" : [
{
"_id" :
0,
"name" :
"localhost:27000",
"health" :
0,
"state" :
8,
"stateStr" :
"(not reachable/healthy)"
"uptime" :
0,
"optime" : {
"ts" : Timestamp(
0,
0),
"t" : NumberLong(-
1)
},
"optimeDate" : ISODate(
"1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate(
"2017-03-10T08:18:27.674Z"),
"lastHeartbeatRecv" : ISODate(
"2017-03-10T08:17:28.709Z"),
"pingMs" : NumberLong(
0),
"lastHeartbeatMessage" :
"Connection refused",
"configVersion" : -
1
},
{
"_id" :
1,
"name" :
"localhost:27001",
"health" :
1,
"state" :
1,
"stateStr" :
"PRIMARY",
.....
},
{
"_id" :
2,
"name" :
"localhost:27002",
"health" :
1,
"state" :
2,
"stateStr" :
"SECONDARY",
...
}
],
"ok" :
1
}
[root@ydq05 ~]
MongoDB
shell version:
3.2.11
connecting
to: localhost:
27001/test
repSetTest:PRIMARY> db.users.count()
1000131
5、原主节点添加索引
MongoDB
shell version:
3.2.11
connecting
to: localhost:
27300/test
repSetTest:SECONDARY> rs.slaveOk()
repSetTest:SECONDARY> db.users.count()
1000131
> db.users.getIndexes()
[
{
"v" :
1,
"key" : {
"_id" :
1
},
"name" :
"_id_",
"ns" :
"test.users"
}
]
> db.users.createIndex({username:
1,created:
1})
{
"createdCollectionAutomatically" :
false,
"numIndexesBefore" :
1,
"numIndexesAfter" :
2,
"ok" :
1
}
> use admin
> db.shutdownServer()
[root@ydq05 ~]
>
6、后记
a、本次演示模拟了依旧有客户端对原集合进行操作,真实生产环境应尽量在业务低峰期操作
b、在发生主从切换时,使用rs.stepDown()平滑切换,本次操作未按此方式
c、发生切换期间可以采用VIP漂移或者暂停业务
d、索引添加期间应考虑有启用从库读的问题
转载请注明原文地址: https://ju.6miu.com/read-23533.html