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