MongoDB 副本集(replica Set)
Mongodb(M)表示主节点,Mongodb(S)表示备节点,Mongodb(A)表示仲裁节点。主备节点存储数据,仲裁节点不存储数据。客户端同时连接主节点与备节点,不连接仲裁节点。
仲裁节点是一种特殊的节点,它本身并不存储数据,主要的作用是决定哪一个备节点在主节点挂掉之后提升为主节点,所以客户端不需要连接此节点。
在MongoDB副本集中,主节点负责处理客户端的读写请求,备份节点则负责映射主节点的数据。
备份节点的工作原理过程可以大致描述为,备份节点定期轮询主节点上的数据操作,然后对自己的数据副本进行这些操作,从而保证跟主节点的数据同步。
至于主节点上的所有 数据库状态改变 的操作,都会存放在一张特定的系统表中。备份节点则是根据这些数据进行自己的数据更新。
oplog
上面提到的 数据库状态改变 的操作,称为oplog(operation log,主节点操作记录)。oplog存储在local数据库的" oplog.rs"表中。副本集中备份节点异步的从主节点同步oplog,然后重新执行它记录的操作,以此达到了数据同步的作用。
node1 mongodb.config配置
- dbpath=/usr/data/mongodb/relpset/node1/data/db
- logpath=/usr/data/mongodb/relpset/node1/log/mongodb.log
- logappend=true
- fork=true
- bind_ip=192.168.1.1
- port=27021
- replSet=myset
node2 mongodb.config配置
- dbpath=/usr/data/mongodb/relpset/node2/data/db
- logpath=/usr/data/mongodb/relpset/node2/log/mongodb.log
- logappend=true
- fork=true
- bind_ip=192.168.1.1
- port=27022
- replSet=myset
node3 mongodb.config配置
- dbpath=/usr/data/mongodb/relpset/node3/data/db
- logpath=/usr/data/mongodb/relpset/node3/log/mongodb.log
- logappend=true
- fork=true
- bind_ip=192.168.1.1
- port=27023
- replSet=myset
启动node1、node2、node3
连接node1 mongo --host 192.168.1.1 -port 27021
> rs.status()
{
"info" : "run rs.initiate(...) if not yet done for the set",
"ok" : 0,
"errmsg" : "no replset config has been received",
"code" : 94
}
初始化副本集配置—仲裁节点配置模式 priority权重,权重大的是主节点
> rs.initiate({"_id":"myset",members:[{"_id":1,"host":"192.168.1.1:27021",priority:4},{"_id":2,"host":"192.168.1.1:27022",priority:1},{"_id":3,"host":"192.168.1.1:27023",arbiterOnly:true}]})
{ "ok" : 1 }
myset:OTHER> rs.status()
{
"set" : "myset",
"date" : ISODate("2016-11-22T03:27:37.333Z"),
"myState" : 1,
"members" : [
{
"_id" : 1,
"name" : "192.168.1.1:27021",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1574,
"optime" : Timestamp(1479784992, 1),
"optimeDate" : ISODate("2016-11-22T03:23:12Z"),
"electionTime" : Timestamp(1479784996, 1),
"electionDate" : ISODate("2016-11-22T03:23:16Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 2,
"name" : "192.168.1.1:27022",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 264,
"optime" : Timestamp(1479784992, 1),
"optimeDate" : ISODate("2016-11-22T03:23:12Z"),
"lastHeartbeat" : ISODate("2016-11-22T03:27:36.724Z"),
"lastHeartbeatRecv" : ISODate("2016-11-22T03:27:36.726Z"),
"pingMs" : 0,
"lastHeartbeatMessage" : "could not find member to sync from",
"configVersion" : 1
},
{
"_id" : 3,
"name" : "192.168.1.1:27023",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 264,
"lastHeartbeat" : ISODate("2016-11-22T03:27:36.726Z"),
"lastHeartbeatRecv" : ISODate("2016-11-22T03:27:36.726Z"),
"pingMs" : 0,
"configVersion" : 1
}
],
"ok" : 1
}
连接效果如下,代表副本集创建成功
连接node1 mongo --host 192.168.1.1 -port 27021
- myset:PRIMARY> db.zhangsan.insert({"id":i,"name":"zhangsan"+1})
连接node2 mongo --host 192.168.1.1 -port 27022
- myset:SECONDARY> show dbs
- 2016-11-22T11:38:38.215+0800 E QUERY Error: listDatabases failed:{ "note" : "from execCommand", "ok" : 0, "errmsg" : "not master" }
- myset:SECONDARY> rs.slaveOk()
- myset:SECONDARY> show dbs
- local 1.078GB
- test 0.078GB
- myset:SECONDARY> show collections
- system.indexes
- zhangsan
- myset:SECONDARY> db.zhangsan.find()
- { "_id" : ObjectId("5833bd834f0add422410ee18"), "id" : 0, "name" : "zhangsan1" }
连接node3 mongo --host 192.168.1.1 -port 27023
myset:ARBITER>
node1 可写可读 node2 不可写可读 node3 不可读不可写
node1挂了
- 仲裁节点node3会把从node2切换成主
- node1重启之后,node3会根据权重把node1切换成主,node2为从
初始化副本集配置—无仲裁节点配置模式
- > rs.initiate({"_id":"myset1",members:[{"_id":1,"host":"192.168.1.1:27024"},{"_id":2,"host":"192.168.1.1:27025"},{"_id":3,"host":"192.168.1.1:27026"}]})
node4主 挂了
- 主从会自动切换,会从node5,node6中选择一个作为主
- node4重启之后,node4会变成从节点
实际工作中,无仲裁节点配置用的多,有仲裁的话,仲裁挂掉,就没法切换主从了
杀掉主进程观察效果:netstat -antp | grep mon
增加节点
rs.add(“192.168.1.1:27024”)
删除节点
rs.remove(“192.168.1.1:27024”)