21.33 mongodb副本集介绍
MongoDB副本集:
早期版本使用master-slave,一主一从和MySQL类似,但slave在此架构中为只读,当主库宕机后,从库不能自动切换为主
目前已经淘汰master-slave模式,改为副本集,这种模式下有一个主(primary),和多个从(secondary),只读。支持给它们设置权重,当主宕掉后,权重最高的从切换为主
在此架构中还可以建立一个仲裁(arbiter)的角色,它只负责裁决,而不存储数据
再此架构中读写数据都是在主上,要想实现负载均衡的目的需要手动指定读库的目标server
副本集架构图:
副本集primary宕机示意图:
21.34 mongodb副本集搭建
三台机器: 192.168.133.130(primary) 192.168.133.132(secondary) 192.168.133.133(secondary)
编辑三台机器的配置文件,更改或增加:
replication://把此行前面的#删除
##oplog大小
oplogSizeMB: 20//前面有两个空格
##复制集名称
replSetName: aminglinux//前面有两个空格
分别重启三台机器服务
连接主,在主上运行命令mongo
>use admin
>config={_id:"aminglinux",members:[{_id:0,host:"192.168.133.130:27017"},{_id:1,host:"192.168.133.132:27017"},{_id:2,host:"192.168.133.133:27017"}]}
>rs.initiate(config)
rs.status() //查看状态
如果两个从上的状态为"stateStr" : "STARTUP", 则需要进行如下操作
> var config={_id:"aminglinux",members:[{_id:0,host:"192.168.133.130:27017"},{_id:1,host:"192.168.133.132:27017"},{_id:2,host:"192.168.133.133:27017"}]}
>rs.reconfig(config)
此时再次查看rs.status()会发现从的状态变为SECONDARY
> use admin
switched to db admin
> config={_id:"aminglinux",members:[{_id:0,host:"192.168.60.11:27017"},{_id:1,host:"192.168.60.12:27017"},{_id:2,host:"192.168.60.13:27017"}]}
{
"_id" : "aminglinux",
"members" : [
{
"_id" : 0,
"host" : "192.168.60.11:27017"
},
{
"_id" : 1,
"host" : "192.168.60.12:27017"
},
{
"_id" : 2,
"host" : "192.168.60.13:27017"
}
]
}
>
> rs.initiate(config)
{ "ok" : 1 } ##是1 就对了;
aminglinux:PRIMARY> rs.status() ##查看状态;
{
"set" : "aminglinux",
"date" : ISODate("2017-10-19T19:41:16.726Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1508442074, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1508442074, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1508442074, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "192.168.60.11:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 2851,
"optime" : {
"ts" : Timestamp(1508442074, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-10-19T19:41:14Z"),
"electionTime" : Timestamp(1508439306, 1),
"electionDate" : ISODate("2017-10-19T18:55:06Z"),
"configVersion" : 6,
"self" : true
},
{
"_id" : 2,
"name" : "192.168.60.12:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 75,
"optime" : {
"ts" : Timestamp(1508442074, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1508442074, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-10-19T19:41:14Z"),
"optimeDurableDate" : ISODate("2017-10-19T19:41:14Z"),
"lastHeartbeat" : ISODate("2017-10-19T19:41:16.633Z"),
"lastHeartbeatRecv" : ISODate("2017-10-19T19:41:14.635Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "192.168.60.11:27017",
"configVersion" : 6
},
{
"_id" : 3,
"name" : "192.168.60.13:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 0,
"optime" : {
"ts" : Timestamp(1508442074, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1508442074, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-10-19T19:41:14Z"),
"optimeDurableDate" : ISODate("2017-10-19T19:41:14Z"),
"lastHeartbeat" : ISODate("2017-10-19T19:41:16.630Z"),
"lastHeartbeatRecv" : ISODate("2017-10-19T19:41:16.645Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "192.168.60.11:27017",
"configVersion" : 6
}
],
"ok" : 1
}
21.35 mongodb副本集测试
MongoDB副本集测试:
主上建库,建集合
>use mydb
>db.acc.insert({AccountID:1,UserName:"123",password:"123456"})
>show dbs
从上查看
>show dbs
若出现错误Error: listDatabases failed:{ "note" : "from execCommand", "ok" : 0, "errmsg" : "not master" },需要执行
>rs.slaveok()
aminglinux:PRIMARY> use mysql ##在从上面创建mysql
switched to db mysql
aminglinux:PRIMARY> db.acc.insert({AccountID:1,UserName:"123",password:"123456"})
##创建一个集合acc,并插入数据
WriteResult({ "nInserted" : 1 })
aminglinux:PRIMARY> show dbs;
db1 0.000GB
local 0.000GB
mysql 0.000GB
##接下来我们等了60.12secondary查看同步
aminglinux:SECONDARY> show dbs
2017-10-19T20:47:39.795+0800 E QUERY [thread1] Error: listDatabases failed:{
"ok" : 0,
"errmsg" : "not master and slaveOk=false", ##这里无法查看
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:769:19
shellHelper@src/mongo/shell/utils.js:659:15
@(shellhelp2):1:1
aminglinux:SECONDARY> rs.slaveOk() ##执行这个,让slave可以查看;
aminglinux:SECONDARY> show dbs
db1 0.000GB
local 0.000GB
mysql 0.000GB
副本集更改权重模拟主宕机:
默认三台机器权重都为1,如果任何一个权重设置为比其他的高,则该台机器马上切换为primary角色,所以我们预设三台机器的权重分别为:130:3,132:2,133:1
在主上执行
cfg = rs.conf()
cfg.members[0].priority = 3
cfg.members[1].priority = 2
cfg.members[2].priority = 1
rs.reconfig(cfg)
这样的话,第二个节点将会成为候选主节点。
主上执行 iptables -I INPUT -p tcp --dport 27017 -j DROP
aminglinux:PRIMARY> rs.config() ##查看配置,priority是其权重
{
"_id" : "aminglinux",
"version" : 6,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "192.168.60.11:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "192.168.60.12:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 3,
"host" : "192.168.60.13:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : 60000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("59e8f4ffee48611ad04ee633")
}
}
[root@Dasoncheng ~]# iptables -I INPUT -p tcp --dport 27017 -j DROP
##在primary上面执行这条命令,drop掉27017端口的通信;在其他副本集查看状态
aminglinux:PRIMARY> rs.status() ##60.12已经成为primary了;
{
"set" : "aminglinux",
"date" : ISODate("2017-10-19T13:04:55.021Z"),
"myState" : 1,
"term" : NumberLong(2),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1508443618, 5),
"t" : NumberLong(2)
},
"appliedOpTime" : {
"ts" : Timestamp(1508443618, 5),
"t" : NumberLong(2)
},
"durableOpTime" : {
"ts" : Timestamp(1508443618, 5),
"t" : NumberLong(2)
}
},
"members" : [
{
"_id" : 0,
"name" : "192.168.60.11:27017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDurable" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2017-10-19T13:04:50.892Z"),
"lastHeartbeatRecv" : ISODate("2017-10-19T13:04:54.910Z"),
"pingMs" : NumberLong(1),
"lastHeartbeatMessage" : "Couldn't get a connection within the time limit",
"configVersion" : -1
},
{
"_id" : 2,
"name" : "192.168.60.12:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 6295,
"optime" : {
"ts" : Timestamp(1508443618, 5),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2017-10-19T20:06:58Z"),
"electionTime" : Timestamp(1508443618, 2),
"electionDate" : ISODate("2017-10-19T20:06:58Z"),
"configVersion" : 6,
"self" : true
},
{
"_id" : 3,
"name" : "192.168.60.13:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 1591,
"optime" : {
"ts" : Timestamp(1508443618, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1508443618, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-10-19T20:06:58Z"),
"optimeDurableDate" : ISODate("2017-10-19T20:06:58Z"),
"lastHeartbeat" : ISODate("2017-10-19T13:04:53.973Z"),
"lastHeartbeatRecv" : ISODate("2017-10-19T13:04:53.173Z"),
"pingMs" : NumberLong(1),
"syncingTo" : "192.168.60.11:27017",
"configVersion" : 6
}
],
"ok" : 1
}
##在这里呢,因为权重都为1 所有选择primary具有随机性;我们这里设置权重来指定
aminglinux:PRIMARY> cfg=rs.conf() ##设置一个变量,下面为设置权重
aminglinux:PRIMARY> cfg.members[0].priority = 3
3
aminglinux:PRIMARY> cfg.members[1].priority = 2
2
aminglinux:PRIMARY> cfg.members[2].priority = 1
1
aminglinux:PRIMARY> rs.reconfig(cfg) ##重新加载配置
{ "ok" : 1 }
2017-10-19T21:10:12.635+0800 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2017-10-19T21:10:12.638+0800 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) ok
aminglinux:SECONDARY> rs.config() ##我们可以看到,60.12已经变成secondary了;
{
"_id" : "aminglinux",
"version" : 7,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "192.168.60.11:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 3,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "192.168.60.12:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 2,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 3,
"host" : "192.168.60.13:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : 60000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("59e8f4ffee48611ad04ee633")
}
}
小提示:这是副本集的操作; rs.slaveOk();--sencondary机器授权查询
rs.isMaster()--查看副本集状态
rs.status()--查看副本集状态
rs.remove("localhost:20001");--删除节点 在主服务器执行
rs.add("localhost:20001");--增加节点
rs.initiate(config_rs1);--Initializes a new replica set.
rs.reconfig(config_rs1);--Re-configures a replica set by applying a new replica set configuration object.
rs.的命令官网
http://docs.mongodb.org/manual/reference/method/js-replication/
Replica Set官网说明:
http://docs.mongodb.org/manual/core/replica-set-architecture-three-members/