副本集
副本集原理
Primary 节点将数据修改操作记录到本地的 oplog(操作日志,在 local 库下)中,Secondary 节点定期到 Primary 节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证 Secondary 与 Primary 数据一致。
在 MongoDB 副本集中,Secondary 会不间断的通过心跳来探测 Primary 是否正常,当 Primary 不可用时,各 Secondary 之间会触发选举操作,通过优先级来选举出一个 Secondary 做为新的 Primary,这个过程是无需人工干预的。
副本集特性
- 多个 MongoDB 实例建立的集群
- 任何节点都可以作为 Primary
- 所有写操作都走 Primary
- 自动故障转移
- 自动恢复
环境:
192.168.1.7 MongoDB_node1
192.168.1.8 MongoDB_node2
192.168.1.9 MongoDB_node3
各实例配置文件:
mongodb.conf:
systemLog:
destination: file
logAppend: true
path: /data/mongodb/27017/mongodb.log
storage:
dbPath: /data/mongodb/27017/
journal:
enabled: true
processManagement:
fork: true
pidFilePath: /data/mongodb/27017/mongodb.pid
timeZoneInfo: /usr/share/zoneinfo
net:
port: 27017
bindIp: 0.0.0.0 ##方便各实例互相访问
replication: ##指定副本集名称,同一个副本集名称要一样
replSetName: test
开通防火墙端口
firewall-cmd --add-port=27017/tcp ##三台实例均打开
开启服务:mongod -f mongodb.conf
三台实例验证相互登录:
mongo --host 192.168.1.7 --port 27017
mongo --host 192.168.1.8 --port 27017
mongo --host 192.168.1.9 --port 27017
初始化集群,在node1上mongo登录到shell
定义变量,定义id,id为副本集名称
定义members数组,数组中是各实例ip地址与端口
> config={_id:"test",members:[
{_id:0,host:"192.168.1.7:27017"},
{_id:1,host:"192.168.1.8:27017"},
{_id:2,host:"192.168.1.9:27017"}]
}
打开 admin 库,使用 rs.initiate 方法,引用刚刚定义的变量 config,来初始化集群
> use admin
switched to db admin
> rs.initiate(config)
test:PRIMARY> ##初始化完成后终端提示符回变成PRIMARY,其余实例为SECONDARY
#初始化完成后,其余实例需声明自己为从节点才可查看数据
test:SECONDARY> rs.slaveOk() ##node_2
test:SECONDARY> rs.slaveOk() ##node_3
#查看延迟情况: rs.printSlaveReplicationInfo()
test:SECONDARY> rs.printSlaveReplicationInfo()
source: 192.168.1.8:27017
syncedTo: Tue Apr 21 2020 19:05:10 GMT+0800 (CST)
0 secs (0 hrs) behind the primary
source: 192.168.1.9:27017
syncedTo: Tue Apr 21 2020 19:05:10 GMT+0800 (CST)
0 secs (0 hrs) behind the primary
#查看集群状态:rs.status()
验证集群复制
#PRIMARY node1
test:PRIMARY> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test:PRIMARY> use test
switched to db test
test:PRIMARY> db.test1.insert({test:1})
WriteResult({ "nInserted" : 1 })
test:PRIMARY> db.test1.find()
{ "_id" : ObjectId("5e9ed3d0dcc1ba7f6b92c48f"), "test" : 1 }
#SECONDARY node_2
test:SECONDARY> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
test:SECONDARY> use test
switched to db test
test:SECONDARY> db.test1.find()
{ "_id" : ObjectId("5e9ed3d0dcc1ba7f6b92c48f"), "test" : 1 }
#SECONDARY node_3
test:SECONDARY> use test
switched to db test
test:SECONDARY> db.test1.find()
{ "_id" : ObjectId("5e9ed3d0dcc1ba7f6b92c48f"), "test" : 1 }
优先级配置
默认优先级为1,一旦 Primary 故障,各 Secondary 会根据优先级来选举一个新的 Primary
#只能在PRIMARY上更改优先级设置
test:PRIMARY> conf.members[0].priority=10
10
test:PRIMARY> conf.members[1].priority=50
50
test:PRIMARY> conf.members[2].priority=20
20
test:PRIMARY> rs.reconfig(conf) ##更新优先级设置
test:PRIMARY> rs.config().members ##查看各实例优先级
#查看各实例终端命令符变化
test:SECONDARY> ##node1
test:PRIMARY> ##node2
test:SECONDARY> ##node3
当PRIMARY故障挂掉时,副本集会根据优先级推举出PRIMARY
#node2:
test:PRIMARY> use admin
switched to db admin
test:PRIMARY> db.shutdownServer()
#node3优先级为20,从SECONDARY变成ORIMARY
test:PRIMARY>
注:
挑选其中一台 Secondary 升级为 Primary 的条件是剩下的集群台数>=2,
如果集群只剩下一个实例的话,会抛出异常
当挂掉的实例重新开启时因为优先级最高会直接变回PRIMARY
副本集伸缩(增加删除)
##增加实例时,配置文件中的副本集名称要保持一致 replSetName: test
MongoDB 副本集里添加实例和移除实例都非常方便,往 MongoDB 副本集添加实例数据能够自动同步,
无需人工干预
先删除挂掉实例
##不能删除PRIMARY
test:PRIMARY> use admin
switched to db admin
test:PRIMARY> rs.remove("192.168.1.8:27017")
再添加回来
test:PRIMARY> use admin
switched to db admin
test:PRIMARY> rs.add("192.168.1.8:27017")
test:PRIMARY> rs.config() ##查看各实例信息,发现nonde2的id为3,优先级为1(添加实例默认为1)
MongoDB数据备份与恢复
备份语法:>mongodump -h dbhost -d dbname -o dbdirectory
实例:
创建两个库分别有一个集合
创建备份文件夹
全部备份:
[root@mongodb_node1 ~]# mongodump -h 127.0.0.1:27017 -o /data/mongodb/27017/all/
[root@mongodb_node1 ~]# ls /data/mongodb/27017/all/
admin mytest test
[root@mongodb_node1 ~]# ls /data/mongodb/27017/all/mytest/
test2.bson test2.metadata.json
[root@mongodb_node1 ~]# ls /data/mongodb/27017/all/test/
test1.bson test1.metadata.json
单库备份:
[root@mongodb_node1 ~]# mongodump -h 127.0.0.1:27017 -d mytest -o /data/mongodb/27017/db/
2020-04-21T21:03:11.486+0800 writing mytest.test2 to
2020-04-21T21:03:11.487+0800 done dumping mytest.test2 (1 document)
#单集合备份 -d指定数据库 -c指定集合
恢复数据,删除全部库
> use mytest
switched to db mytest
> db.dropDatabase()
{ "dropped" : "mytest", "ok" : 1 }
> use test
switched to db test
> db.dropDatabase()
{ "dropped" : "test", "ok" : 1 }
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
全库恢复:
[root@mongodb_node1 ~]# mongorestore -h 127.0.0.1:27017 /data/mongodb/27017/all/
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
mytest 0.000GB
test 0.000GB
> use mytest
switched to db mytest
> db.test2.find()
{ "_id" : ObjectId("5e9eee07290f67743da90180"), "name" : "li" }
再次删除全库
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
单库恢复:
[root@mongodb_node1 ~]# mongorestore -h 127.0.0.1:27017 -d mytest /data/mongodb/27017/db/mytest/
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
mytest 0.000GB
> use mytest
switched to db mytest
> db.test2.find()
{ "_id" : ObjectId("5e9eee07290f67743da90180"), "name" : "li" }
#单集合恢复-d指定数据库 -c指定集合