Mongodb复制集及复制集管理
摘要
mongodb复制集简介:
在Mongodb中,如果只有一份数据集,万一出现某些意外,那么数据将会出现损坏或丢失。为了解决这个问题,Mongodb提供了复制集,来抵抗这种数据丢失的风险。
什么是复制集呢?复制集(replication)就是多台服务器维护相同的数据副本,以提高服务器的可用性。复制集分为一个主数据集(primary),和多个从数据集(secondary)。以2个从数据集为例,来说明主从数据集之间的关系。如下图:
一、Mongodb复制集部署
1.1、四个数据集及对应配置文件名
1 20.0.0.10:27017;/etc/mongod.conf
2 20.0.0.10:27018;/etc/mongod2.conf
3 20.0.0.10:27019;/etc/mongod3.conf
4 20.0.0.10:27020;/etc/mongod4.conf
1.2、创建多实例
1 [root@server1 ~]# mkdir -p /data/mongodb/mongodb{2,3,4} #创建数据目录
2 [root@server1 ~]# cd /data/mongodb/
3 [root@server1 mongodb]# ls
4 mongodb2 mongodb3 mongodb4
5 [root@server1 mongodb]# mkdir logs
6 [root@server1 mongodb]# cd logs/
7 [root@server1 logs]# touch mongodb{2,3,4}.log #创建日志文件
8 [root@server1 logs]# ls
9 mongodb2.log mongodb3.log mongodb4.log
10 [root@server1 logs]# chmod 777 *.log #赋予权限
11 [root@server1 logs]# ll
12 总用量 0
13 -rwxrwxrwx. 1 root root 0 9月 10 09:52 mongodb2.log
14 -rwxrwxrwx. 1 root root 0 9月 10 09:52 mongodb3.log
15 -rwxrwxrwx. 1 root root 0 9月 10 09:52 mongodb4.log
1.3、修改配置文件
1 配置文件中开启复制集功能,设置复制集名字
2 [root@server1 etc]# vim /etc/mongod.conf
3 replication:
4 replSetName: fuzhi #注意:不能用Tab分割
5 [root@server1t etc]# mongod -f /etc/mongod.conf --shutdown #关闭实例
6 killing process with pid: 8526
7 [root@server1 etc]# mongod -f /etc/mongod.conf #启动实例
8 [root@server1 etc]# cp -p /etc/mongod.conf /etc/mongod2.conf
9 [root@server1 etc]# cp -p /etc/mongod.conf /etc/mongod3.conf
10 [root@server1 etc]# cp -p /etc/mongod.conf /etc/mongod4.conf
11 [root@server1 etc]# vim /etc/mongod2.conf #mongod3.conf和mongod4.conf也要修改
12 ...省略内容
13 path: /data/mongodb/logs/mongodb2.log #更改日志文件位置
14 dbPath: /data/mongodb/mongodb2 #更改数据文件位置
15 ...省略内容
16
17 [root@server1 etc]# mongod -f /etc/mongod2.conf
18 [root@server1 etc]# mongod -f /etc/mongod3.conf
19 [root@server1 etc]# mongod -f /etc/mongod4.conf
1.4、配置三个节点的复制集,主为PRIMARY,从为SECONDARY
1 [root@server1 etc]# mongo
2 cfg={"_id":"fuzhi","members":[{"_id":0,"host":"20.0.0.10:27017"},{"_id":1,"host":"20.0.0.10:27018"},{"_id":2,"host":"20.0.0.10:27019"}]}
3 rs.initiate(cfg) #初始化配置复制集(保证从节点没有数据)
4 rs.status() #查看复制集状态
1.5、添加节点
1 fuzhi:PRIMARY> rs.add("20.0.0.10:27020")
1.6、删除节点
1 fuzhi:PRIMARY> rs.remove("20.0.0.10:27020")
二、复制集中故障自动切换主实例
2.1、查看进程
4个实例都正常运行,27017端口的实例是主(PRIMARY)
1 [root@server1 ~]# ps aux | grep mongod
2 root 35630 0.4 2.5 1599480 98372 ? Sl 10:28 0:13 mongod -f /etc/mongod.conf
3 root 35956 0.3 2.5 1570544 97168 ? Sl 10:48 0:06 mongod -f /etc/mongod3.conf
4 root 36051 0.2 2.1 1467692 81344 ? Sl 10:50 0:05 mongod -f /etc/mongod4.conf
5 root 36464 0.4 2.3 1504440 90328 ? Sl 11:09 0:03 mongod -f /etc/mongod2.conf
2.2、复制集自动切换
1 [root@server1 ~]# kill -9 35630 #将20.0.0.10:27017实例进程杀死模拟故障
2 [root@server1 ~]# mongo --port 27018
3 fuzhi:SECONDARY> rs.status() #20.0.0.10:27019实例自动变为PRIMARY了
4 "_id" : 2,
5 "name" : "20.0.0.10:27019",
6 "health" : 1,
7 "state" : 1,
8 "stateStr" : "PRIMARY",
9 "uptime" : 442,
10 "optime" : {
2.3、复制集手动切换
在上面复制集自动切换实验基础上继续进行手动切换实验,这时的主为27019端口的实例
1 [root@server1 ~]# mongo --port 27019
2 fuzhi:PRIMARY> rs.freeze(30) #暂停30s不参加选举
3
4 fuzhi:PRIMARY> rs.stepDown(60,30) #交出主节点位置,维持从节点状态不少于60s,等待30s使主节点和从节点日志同步
5 fuzhi:SECONDARY> rs.status() #查看群集状态,这时20.0.0.10:27019已经变为SECONDARY了
6 {
7 "_id" : 1,
8 "name" : "20.0.0.10:27018",
9 "health" : 1,
10 "state" : 1,
11 "stateStr" : "PRIMARY", #20.0.0.10:27018变为PRIMARY了
12 "uptime" : 785,
13 "optime" : {
14 "ts" : Timestamp(1599708679, 1),
15 "t" : NumberLong(3)
16 },
三、复制集如何选举
MongoDB复制集的节点是通过选举产生主节点的。
复制的原理:复制是基于操作日志oplog,相当于MySQL的二进制日志,只记录发生改变的记录。复制将主节点的oplog日志同步并应用到其他从节点的过程
3.1、选举的原理
节点类型分为标准节点,被动节点,仲裁节点。
①只有标准节点可能被选为活跃(primary)节点,有选举权。被动节点有完整副本,不可能成为活跃节点,有选举权。仲裁节点不复制数据,不可能成为活跃节点,只有选举权。
②标准节点与被动节点的区别:priority值高者是标准节点,低者则为被动节点。
③选举规则是票数高者获胜,priority是优先权为0-1000的值,相当于额外增加0-1000的票数。选举结果:票数高者获胜:若票数相同,数据新者获胜
标准节点名称: hosts,优先级高的
被动节点名称:passives,优先级低的
仲裁节点名称:“arbiterOnly”:true
3.2、选举原理验证
部署四个节点身份如下:
标准节点:20.0.0.10:27017和20.0.0.10:27018
被动节点:20.0.0.10:27019
仲裁节点:20.0.0.10:27020
1 [root@server1 etc]# mongo
2
3 > cfg={"_id":"fuzhi","members":[{"_id":0,"host":"20.0.0.10:27017","priority":100},{"_id":1,"host":"20.0.0.10:27018","priority":100},{"_id":2,"host":"20.0.0.10:27019","priority":0},{"_id":3,"host":"20.0.0.10:27020","arbiterOnly":true}]} #人为指定优先级决定节点身份
4 {
5 "_id" : "fuzhi",
6 "members" : [
7 {
8 "_id" : 0,
9 "host" : "20.0.0.10:27017",
10 "priority" : 100
11 },
12 {
13 "_id" : 1,
14 "host" : "20.0.0.10:27018",
15 "priority" : 100
16 },
17 {
18 "_id" : 2,
19 "host" : "20.0.0.10:27019",
20 "priority" : 0
21 },
22 {
23 "_id" : 3,
24 "host" : "20.0.0.10:27020",
25 "arbiterOnly" : true
26 }
27 ]
28 }
29 > rs.initiate(cfg) #复制集初始化配置
30 {
31 "ok" : 1,
32 "operationTime" : Timestamp(1599825165, 1),
33 "$clusterTime" : {
34 "clusterTime" : Timestamp(1599825165, 1),
35 "signature" : {
36 "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
37 "keyId" : NumberLong(0)
38 }
39 }
40 }
41 fuzhi:PRIMARY> rs.isMaster() #查看选举后的结果
42 {
43 "hosts" : [
44 "20.0.0.10:27017",
45 "20.0.0.10:27018"
46 ],
47 "passives" : [
48 "20.0.0.10:27019"
49 ],
50 "arbiters" : [
51 "20.0.0.10:27020"
52 ],
53 "setName" : "fuzhi",
54 "setVersion" : 1,
55 "ismaster" : true,
56 "secondary" : false,
57 "primary" : "20.0.0.10:27017",
58 "me" : "20.0.0.10:27017",
3.3、如何允许从节点读取复制集中的数据
1 [root@server1 etc]# mongo --port 27018
2 fuzhi:SECONDARY> show dbs
3 _getErrorWithCode@src/mongo/shell/utils.js:25:13
4 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:67:1
5 shellHelper.show@src/mongo/shell/utils.js:860:19
6 shellHelper@src/mongo/shell/utils.js:750:15
7 @(shellhelp2):1:1
8 fuzhi:SECONDARY> rs.slaveOk() #允许从节点读取数据
9 fuzhi:SECONDARY> show dbs #这时就能读取数据集中的数据了
10 ...省略内容
11 chen 0.000GB
12 config 0.000GB
13 local 0.000GB
14 school 0.000GB
3.4、如何查看复制状态信息
1 fuzhi:SECONDARY> rs.help() #可以查看rs.命令的用法
2 ...省略内容
3 rs.printReplicationInfo() check oplog size and time range
4 rs.printSlaveReplicationInfo() check replica set members and replication lag
5 db.isMaster() check who is primary
6
7 reconfiguration helpers disconnect from the database so the shell will display
8 an error, even if the command succeeds.
9 fuzhi:SECONDARY> rs.printReplicationInfo() #查看复制集信息
10 configured oplog size: 14806.75146484375MB #日志文件大小
11 log length start to end: 1069secs (0.3hrs)
12 oplog first event time: Sat Dec 12 2020 19:52:45 GMT+0800 (CST)
13 oplog last event time: Sat Dec 12 2020 20:10:34 GMT+0800 (CST)
14 now: Sat Dec 12 2020 20:10:34 GMT+0800 (CST)
15 fuzhi:SECONDARY> rs.printSlaveReplicationInfo() #查看从数据集信息
16 source: 20.0.0.10:27018
17 syncedTo: Sat Dec 12 2020 20:10:54 GMT+0800 (CST)
18 0 secs (0 hrs) behind the primary
19 source: 20.0.0.10:27019
20 syncedTo: Sat Dec 12 2020 20:10:54 GMT+0800 (CST)
21 0 secs (0 hrs) behind the primary
22 注意:仲裁节点不会数据复制
2.4、更改oplog(日志文件)大小
①关闭服务,准备脱离复制集变为单实例
1 [root@server1 etc]# mongo --port 27018
2 fuzhi:SECONDARY> use admin
3 switched to db admin
4 fuzhi:SECONDARY> db.shutdownServer()
5 server should be down...
②注释replication:相关参数,并修改端口号为27028
1 [root@server1 etc]# vim /etc/mongod2.conf
2 port: 27028
3 #replication:
4 #replSetName: fuzhi
③以单实例模式启动
1 [root@server1 etc]# mongod -f /etc/mongod2.conf
④完整性备份当前节点的原来的所有oplog记录
1 [root@server1 etc]# mongodump --port 27028 --db local --collection 'oplog.rs'
2 2020-12-12T20:24:45.971+0800 writing local.oplog.rs to
3 2020-12-12T20:24:45.972+0800 done dumping local.oplog.rs (150 documents)
⑤进入节点删除原来的日志文件,并定义日志文件大小,建立新的日志文件
1 [root@server1 etc]# mongo --port 27028
2 > use local
3 switched to db local
4 > show tables
5 me
6 oplog.rs
7 replset.election
8 > db.oplog.rs.drop() #删除原来的日志文件
9 true
10 > db.runCommand({create:"oplog.rs",capped:true,size:(2*1024*1024*1024)})
11 #定义日志文件大小为2048MB,建立新的日志文件
12 { "ok" : 1 }
13 > use admin
14 switched to db admin
15 > db.shutdownServer() #关闭服务
16 server should be down...
⑥修改配置文件,重新启动服务,回到复制集,到此日志文件大小修改完成
1 [root@server1 etc]# vim /etc/mongod2.conf
2 port: 27018
3 replication:
4 replSetName: fuzhi
5 oplogSizeMB: 2048
6 [root@server1 etc]# mongod -f /etc/mongod2.conf
7 #主节点让出主的身份
8 fuzhi:PRIMARY> rs.stepDown()
四、部署认证复制集
4.1、部署四个节点如下
1 20.0.0.10:27017
2 20.0.0.10:27018
3 20.0.0.10:27019
4 20.0.0.10:27020
4.2、创建认证用户
1 [root@server1 etc]# mongo
2 fuzhi:PRIMARY> use admin
3 switched to db admin
4 fuzhi:PRIMARY> db.createUser({"user":"root","pwd":"123","roles":["root"]})
5 Successfully added user: { "user" : "root", "roles" : [ "root" ] }
6 fuzhi:PRIMARY> exit
4.3、复制集中四个实例的配置文件中加入密码文件参数
1 [root@server1 etc]# vim /etc/mongod.conf
2 security:
3 keyFile: /usr/bin/mykey1
4 clusterAuthMode: keyFile
5 [root@server1 etc]# vim /etc/mongod2.conf
6 security:
7 keyFile: /usr/bin/mykey2
8 clusterAuthMode: keyFile
9 [root@server1 etc]# vim /etc/mongod3.conf
10 security:
11 keyFile: /usr/bin/mykey3
12 clusterAuthMode: keyFile
13 [root@server1 etc]# vim /etc/mongod4.conf
14 security:
15 keyFile: /usr/bin/mykey4
16 clusterAuthMode: keyFile
4.4、创建密钥文件并修改权限为600
1 [root@server1 etc]# cd /usr/bin/
2 [root@server1 bin]# echo "my keys" > mykey1
3 [root@server1 bin]# echo "my keys" > mykey2
4 [root@server1 bin]# echo "my keys" > mykey3
5 [root@server1 bin]# echo "my keys" > mykey4
6 [root@server1 bin]# chmod 600 mykey*
4.5、对四个实例依次重启
1 [root@server1 logs]# mongod -f /etc/mongod.conf --shutdown
2 [root@server1 logs]# mongod -f /etc/mongod.conf
3 [root@server1 logs]# mongod -f /etc/mongod2.conf --shutdown
4 [root@server1 logs]# mongod -f /etc/mongod2.conf
5 [root@server1 logs]# mongod -f /etc/mongod3.conf --shutdown
6 [root@server1 logs]# mongod -f /etc/mongod3.conf
7 [root@server1 logs]# mongod -f /etc/mongod4.conf --shutdown
8 [root@server1 logs]# mongod -f /etc/mongod4.conf
4.6、这时复制集中的所有实例(包括主实例)必须通过身份认证才能查看数据
1 [root@server1 logs]# mongo --port 27018
2 fuzhi:PRIMARY> show dbs #未身份认证无法查看数据
3 2020-09-11T22:16:38.181+0800 E QUERY [thread1] Error: listDatabases failed:{
4 ...省略内容
5 _getErrorWithCode@src/mongo/shell/utils.js:25:13
6 Mongo.prototype.getDBs@src/mongo/shell/mongo.js:67:1
7 shellHelper.show@src/mongo/shell/utils.js:860:19
8 shellHelper@src/mongo/shell/utils.js:750:15
9 @(shellhelp2):1:1
10 fuzhi:PRIMARY> use admin
11 switched to db admin
12 fuzhi:PRIMARY> db.auth("root":"123") #进行身份认证
13 2020-09-11T22:17:30.274+0800 E QUERY [thread1] SyntaxError: missing ) after argument list @(shell):1:14
14 fuzhi:PRIMARY> db.auth("root","123")
15 1
16 fuzhi:PRIMARY> show dbs
17 abc 0.000GB
18 admin 0.000GB
19 chen 0.000GB
20 config 0.000GB
21 local 0.000GB