什么是复制集?
- 复制集(replica sets)是额外的数据副本,是跨多个服务器同步数据的过程,复制集提供了冗余并增加了数据可用性,通过复制集可以对硬件故障和中断服务进行恢复。
复制集的优势
- 让数据更安全。
- 高数据可用性。
- 灾难恢复。
- 无停机维护(如备份、索引重建、故障转移)
- 读缩放(额外的副本读取)
- 副本集对应用程序是透明的。
复制集概述
- MongoDB复制集是额外的数据副本,复制集提供了冗余和增加数据可用性。
- MongoDB的复制集至少需要两个节点,其中主节点负责处理客户端请求,从节点负责复制主节点上的数据。
- MongoDB复制集可以实现群集的高可用,当主节点出现故障时会自动切换。
- 复制是基于操作日志oplog,相当于MySQL中的二进制日志,只记录发生改变的记录。复制是将主节点的oplog日志同步并应用到其他节点的过程。
- 节点类型分为标准节点、被动节点、仲裁节点。只有标准节点可能被选举为活跃(主)节点。
- 尽量保证主节点的oplog足够大,能够存放相当长时间的操作记录。
复制集服务配置
1、创建多实例
mkdir -p /data/mongodb/mongodb{2,3,4} //创建数据目录
mkdir logs
touch logs/mongodb{2,3,4}.log //创建日志文件
cd logs/
chmod 777 *.log //赋予权限
- 修改多实例配置文件
vim /etc/mongod2.conf
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /data/mongodb/logs/mongodb2.log //日志文件存放位置
# Where and how to store data.
storage:
dbPath: /data/mongodb/mongodb2 //数据文件存放位置
journal:
enabled: true
# engine:
# mmapv1:
# wiredTiger:
# how the process runs
processManagement:
fork: true # fork and run in background
pidFilePath: /var/run/mongodb/mongod.pid # location of pidfile
timeZoneInfo: /usr/share/zoneinfo
# network interfaces
net:
port: 27018 //监听端口及IP地址
bindIp: 0.0.0.0 # Listen to local interface only, comment to listen on all interfaces.
#security:
#operationProfiling:
replication:
replSetName: abc //打开主从复制集功能,每个节点都要配置相同名称
2、配置三个节点的复制集
- 如上创建多实例完成后,修改完成配置文件后,依次重启每个服务。
mongod -f /etc/mongod.conf --shutdown
mongod -f /etc/mongod.conf
mongod -f /etc/mongod2.conf
mongod -f /etc/mongod3.conf
mongod -f /etc/mongod4.conf
- 进入主节点配置复制集
mongo
> show dbs //查看数据库
> rs.status() //查看复制集状态
> cfg={"_id":"abc","members":[{"_id":0,"host":"192.168.144.112:27017"},{"_id":1,"host":"192.168.144.112:27018"},{"_id":2,"host":"192.168.144.112:27019"}]} //配置复制集节点IP
> rs.initiate(cfg) //初始化配置时保证从节点没有数据
> rs.status() //此时再查看复制集状态
- 当能够看到如图状态,可以看到各节点状态代表复制集配置完成。
3、复制集的节点添加和删除
abc:PRIMARY> rs.add("192.168.144.112:27020") //添加节点
abc:PRIMARY> rs.remove("192.168.144.112:27020") //删除节点
> rs.status()
4、故障转移切换
自动切换
ps aux | grep mongod
- 模拟故障,复制集完成自动切换
kill -9 46374
手动切换
abc:PRIMARY> rs.freeze(30) //暂停30s不参与选举
abc:PRIMARY> rs.stepDown(60,30) //交出主节点位置,维持从节点状态不少于60秒,等待30秒使主节点和从节点日志同步
MongoDB复制选举
1、复制原理
- 复制是基于操作日志oplog,相当于MySQL中的二进制日志,只记录发生改变的记录,复制是将主节点的oplog日志同步并应用到其他从节点的过程。
2、选举的原理
-
节点类型分为:标准(host)节点、被动(passive)和仲裁(arbiter)节点。
- (1)只有标准节点可以被选举为活跃(primary)节点,有选举权,被动节点有完整副本,不可能成为活跃节点,有选举权,仲裁节点不复制数据,不可能成为活跃节点,只有选举权。
- 标准节点与被动节点的区别:priority优先级值高者是标准节点,低着则为被动节点。
- 选举规则是票数高者获胜,priority是优先权为0~100的值,相当于额外增加的0~100的票数。
复制选举配置
- 如上一小节,打开配置文件中复制功能:
replication:
replSetName: abc
选举节点设置
mongo //进入数据库
cfg={"_id":"abc","members":[{"_id":0,"host":"192.168.144.112:27017","priority":100},{"_id":1,"host":"192.168.144.112:27018","priority":100},{"_id":2,"host":"192.168.144.112:27019","priority":0},{"_id":3,"host":"192.168.144.112:27020","arbiterOnly":true}]}
//设置节点IP端口以及节点类型
> rs.initiate(cfg) //初始化数据库
> rs.isMaster() //查看状态
- 在主节点所有的修改操作将会被记录在oplog日志中,下面将模拟修改操作,以及查看oplog日志记录。
abc:PRIMARY> use kgc //创建数据库
abc:PRIMARY> db.t1.insert({"id":1,"name":"tom"}) //创建集合t1并插入数据
abc:PRIMARY> db.t1.insert({"id":2,"name":"jerry"})
abc:PRIMARY> db.t1.find() //查看集合数据
abc:PRIMARY> db.t1.update({"id":2},{$set:{"name":"jack"}}) //修改集合数据
abc:PRIMARY> db.t1.remove({"id":1}) //删除数据
abc:PRIMARY> use local //进入oplog所在数据库
abc:PRIMARY> show collections //查看所有集合
oplog.rs //oplog集合
abc:PRIMARY> db.oplog.rs.find()
//查看日志记录所有操作,此时从节点会从oplog中同步数据
模拟标准节点故障
- 当标准节点1选举为primary时,为了模拟故障,直接选择关闭节点1
mongod -f /etc/mongod.conf --shutdown
- 进入节点2,查看节点2状态
- 此时会选举第二个标准节点为主节点
mongo --port 27018
- 当继续模拟标准节点2故障时,此时两个标准节点都不能工作,此时进入被动节点三,发现被动节点三不能成为主节点
mongo --port 27019
允许从节点读取数据
-
在标准节点上写入数据,其他节点上也会同步复制,如何从从节点上读取数据?
- 进入从节点数据库
[root@localhost]# mongo --port 27018
abc:SECONDARY> show dbs //此时从节点不允许读取数据
abc:SECONDARY> rs.slaveOk() //允许默认从节点读取数据
abc:SECONDARY> show dbs //再次查看时就可以了
查看复制状态信息
abc:SECONDARY> rs.help() //查看命令帮助手册
abc:SECONDARY> rs.printReplicationInfo()
configured oplog size: 990MB
log length start to end: 1544secs (0.43hrs)
oplog first event time: Mon Jul 16 2018 05:49:12 GMT+0800 (CST)
oplog last event time: Mon Jul 16 2018 06:14:56 GMT+0800 (CST)
now: Mon Jul 16 2018 06:14:59 GMT+0800 (CST)
abc:SECONDARY> rs.printSlaveReplicationInfo()
source: 192.168.235.200:27018
syncedTo: Mon Jul 16 2018 06:16:16 GMT+0800 (CST)
0 secs (0 hrs) behind the primary
source: 192.168.235.200:27019
syncedTo: Mon Jul 16 2018 06:16:16 GMT+0800 (CST)
0 secs (0 hrs) behind the primary
abc:ARBITER> rs.printReplicationInfo()
cannot provide replication status from an arbiter.
//会发现仲裁节点并不具备数据复制
更改oplog日志大小
- oplog即operation log的简写,存储在local数据库中。oplog中新操作会自动替换旧的操作,以保证oplog不会超过预设的大小。默认情况下,oplog大小会占用64位的实例5%的磁盘空间。
- 在MongoDB复制的过程中,主节点应用业务操作修改到数据库中,然后记录这些操作到oplog中,从节点复制这些oplog,然后应用这些修改、这些操作是异步的,如果从节点的操作已经被主节点落下很远,oplog日志在从节点上还没执行完,oplog可能已经轮滚一圈了,从节点跟不上同步,复制就会停下,从节点需要重新做完整的同步,为了避免这种情况,尽量保证主节点的oplog足够大,能够存放相当长时间的操作记录。
查看当前oplog日志文件大小
abc:PRIMARY> db.printReplicationInfo()
configured oplog size: 1613.301513671875MB //默认大小
log length start to end: 18650secs (5.18hrs)
oplog first event time: Tue Jul 17 2018 11:08:30 GMT+0800 (CST)
oplog last event time: Tue Jul 17 2018 16:19:20 GMT+0800 (CST)
now: Tue Jul 17 2018 16:19:21 GMT+0800 (CST)
离线升级,更改oplog日志大小
- 针对于主节点服务器oplog日志大小,如果主节点服务器存在于复制集当中,我们需要先将主节点服务关闭,然后再在配置文件中关闭replication复制相关选项,并且修改端口号,因为如果端口号不改,当服务启动时,还是会被加入到复制集队列。将其服务作为单实例启动。
mongo
abc:PRIMARY> use admin
switched to db admin
abc:PRIMARY> db.shutdownServer()
也可以采用mongod -f /etc/mongod.conf --shutdown 方式关闭服务
vim /etc/mongod.conf
- 注销replication:相关启动参数,并修改port端口号27027
...
# network interfaces
net:
port: 27027 //修改端口
bindIp: 0.0.0.0 # Listen to local interface only, comment to listen on all interfaces.
#security:
#operationProfiling:
#replication: //注释复制功能
# replSetName: abc
...
- 主节点的单实例启动
mongo -f /etc/mongod.conf
- 备份当前oplog日志
mongodump --port 27027 --db local --collection 'oplog.rs' //全备份当前节点oplog记录
- 进入当前节点MongoDB
mongo --port 27027
> use local //进入local数据库
> db.oplog.rs.drop() //删除oplog原有集合
> db.runCommand( { create: "oplog.rs", capped: true, size: (2 * 1024 * 1024 * 1024) } ) //重建oplog,并指定大小
> use admin
> db.shutdownServer() //关闭服务
- 把配置文件修改回来
...
# network interfaces
net:
port: 27017 //端口修改回原有端口
bindIp: 0.0.0.0 # Listen to local interface only, comment to listen on all interfaces.
#security:
#operationProfiling:
replication: //取消注释复制功能
replSetName: abc
oplogSizeMB:2048 //添加指定oplog日志大小
...
- 启动节点服务
mongod -f /etc/mongod.conf
mongo --port 27017
abc:SECONDARY> db.printReplicationInfo()
configured oplog size: 2048MB //oplog日志大小已经改变
log length start to end: 30secs (0.01hrs)
oplog first event time: Tue Jul 17 2018 17:33:18 GMT+0800 (CST)
oplog last event time: Tue Jul 17 2018 17:33:48 GMT+0800 (CST)
now: Tue Jul 17 2018 17:33:54 GMT+0800 (CST)
abc:SECONDARY>
部署认证复制
mongo
-
进入primary
kgcrs:PRIMARY> use admin kgcrs:PRIMARY> db.createUser({"user":"root","pwd":"123","roles":["root"]}) //创建管理用户,并且使用管理用户认证
- 在每个实例配置文件中打开认证功能
[root@localhost]# vim /etc/mongod.conf
[root@localhost]# vim /etc/mongod2.conf
[root@localhost]# vim /etc/mongod3.conf
[root@localhost]# vim /etc/mongod4.conf
...
security:
keyFile: /usr/bin/kgcrskey1
clusterAuthMode: keyFile
...
cd /usr/bin/
-
创建认证文件,并且输入统一认证密匙
[root@localhost bin]# echo "kgcrs key"> kgcrskey1 [root@localhost bin]# echo "kgcrs key"> kgcrskey2 [root@localhost bin]# echo "kgcrs key"> kgcrskey3 [root@localhost bin]# echo "kgcrs key"> kgcrskey4 [root@localhost bin]# chmod 600 kgcrskey{1..4} //设置权限,只有属主可以查看
- 重启四个实例
进入primary
kgcrs:PRIMARY> show dbs //无法查看数据库
kgcrs:PRIMARY> rs.status() ///无法查看复制集
kgcrs:PRIMARY> use admin //身份登录验证
kgcrs:PRIMARY> db.auth("root","123")
kgcrs:PRIMARY> rs.status() //可以查看数据库
kgcrs:PRIMARY> show dbs //可以查看复制集