mongodb复制原理及其操作

一、mongodb复制(副本集)
MongoDB复制是将数据同步在多个服务器的过程。
复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。
复制还允许从硬件故障和服务中断中恢复数据。

二、mongodb复制原理

mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。
mongodb各个节点常见的搭配方式为:一主一从、一主多从。
主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。
MongoDB复制结构图如下所示:

以上结构图中,Mongodb复制集(副本集replica set)由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写入Primary,Secondary通过oplog来同步Primary的数据,保证主节点和从节点数据的一致性,复制集在完成主从复制的基础上,通过心跳机制,一旦primary节点出现宕机,则触发选举一个新的主节点,剩下的secondary节点指向新的primary,时间应该在10-30s内完成感知primary节点故障,实现高可用数据库集群

副本集特征:
? N 个节点的集群
? 任何节点可作为主节点
? 所有写入操作都在主节点上
? 自动故障转移
? 自动恢复

三、mongodb副本集设置

1、首先创建数据目录和日志目录
mkdir -p /data/mongodb/mongodb{1,2,3,4} #创建数据目录

mkdir -p /data/logs/ #创建日志目录

cd /data/logs/
touch mongodb{1,2,3,4}.log #创建日志文件

chmod 777 ./*.log #修改目录权限

2、复制etc/mongod.conf配置文件并开启复制集#replication:去掉#号在下一行加入replSetName: kgcrs 复制集名称为kgcrs

cp -p /etc/mongod.conf /etc/mongod1.conf
cp -p /etc/mongod1.conf /etc/mongod2.conf
cp -p /etc/mongod1.conf /etc/mongod3.conf
cp -p /etc/mongod1.conf /etc/mongod4.conf

vi /etc/mongod1.conf

net:
bind_ip=0.0.0.0
port=27017
storage:
dbpath=/data/mongodb/mongodb1/

path=/data/logs/mongodb1.log
logappend=true
fork=true

replication:
replSetName: kgcrs

3、开启节点
mongod -f /etc/mongod1.conf
mongod -f /etc/mongod2.conf
mongod -f /etc/mongod3.conf
mongod -f /etc/mongod4.conf

4、配置复制集

进入mongodb数据库中:
mongo --port 27017

#定义四个标准节点
cfg={"_id":“kgcrs”,“members”:[{"_id":0,“host”:“127.0.0.1:27017”},{"_id":1,“host”:“127.0.0.1:27018”},{"_id":2,“host”:“127.0.0.1:27019”},{"_id":3,“host”:“127.0.0.1:27020”}]}

#初始化复制集,配置时保证从节点没有数据
rs.initiate(cfg)

#查看复制集状态(rs复制集的简称)
rs.status()
{
“set” : “kgcrs”,
“date” : ISODate(“2019-01-18T00:48:33.956Z”),
“myState” : 1,
“term” : NumberLong(1),
“syncingTo” : “”,
},
“syncSourceHost” : “”,
“syncSourceId” : -1,
“heartbeatIntervalMillis” : NumberLong(2000), # 心跳间隔时间
“optimes” : {
“lastCommittedOpTime” : {
“ts” : Timestamp(1547772512, 1),
“t” : NumberLong(1)
},
“readConcernMajorityOpTime” : {
“ts” : Timestamp(1547772512, 1),
“t” : NumberLong(1)
},
“appliedOpTime” : {
“ts” : Timestamp(1547772512, 1),
“t” : NumberLong(1)
},
“durableOpTime” : {
“ts” : Timestamp(1547772512, 1),
“t” : NumberLong(1)
}
},
“lastStableCheckpointTimestamp” : Timestamp(1547772510, 1),
“members” : [
{
“_id” : 0,
“name” : “127.0.0.1:27017”,
“health” : 1,
“state” : 1,
“stateStr” : “PRIMARY”,
“uptime” : 92,
“optime” : {
“ts” : Timestamp(1547772512, 1),
“t” : NumberLong(1)
},
“optimeDate” : ISODate(“2019-01-18T00:48:32Z”),
“syncingTo” : “”,
“syncSourceHost” : “”,
“syncSourceId” : -1,
“infoMessage” : “could not find member to sync from”,
“electionTime” : Timestamp(1547772509, 1),
“electionDate” : ISODate(“2019-01-18T00:48:29Z”),
“configVersion” : 1,
“self” : true,
“lastHeartbeatMessage” : “”
},
以上是主节点信息:

{
“_id” : 2,
“name” : “127.0.0.1:27019”,
“health” : 1,
“state” : 2,
“stateStr” : “SECONDARY”,
“uptime” : 15,
“optime” : {
“ts” : Timestamp(1547772512, 1),
“t” : NumberLong(1)
},
“optimeDurable” : {
“ts” : Timestamp(1547772512, 1),
“t” : NumberLong(1)
},
“optimeDate” : ISODate(“2019-01-18T00:48:32Z”),
“optimeDurableDate” : ISODate(“2019-01-18T00:48:32Z”),
“lastHeartbeat” : ISODate(“2019-01-18T00:48:33.582Z”), #当前节点最后一次收到其他成员心跳的时间,如果网络故障等可能这个时间会大于2秒
“lastHeartbeatRecv” : ISODate(“2019-01-18T00:48:32.195Z”), #当前节点收到该成员的最后一个心跳
“pingMs” : NumberLong(0), #当前节点到该成员的回路时长
“lastHeartbeatMessage” : “”,
“syncingTo” : “127.0.0.1:27017”,
“syncSourceHost” : “127.0.0.1:27017”,
“syncSourceId” : 0,
“infoMessage” : “”,
“configVersion” : 1
}

#添加节点
rs.add(“IP地址:端口号”)
rs.add(“127.0.0.1:27020”)
#删除节点
rs.remove(“IP地址:端口号”)
rs.remove(“127.0.0.1:27020”)

5、测试故障转移切换
ps aux | grep mongo
kill掉一个进程把主节点down掉

(1)在从的mongodb查看
mongo --port 27018
kgcrs:SECONDARY> rs.isMaster() #查看主从

(2)手动切换
在主的mongodb上操作
kgcrs:PRIMARY> rs.freeze(30)

#交出主节点位置,维持从节点状态不少于60秒,等待30秒使主节点和从节点日志同步
kgcrs:PRIMARY> rs.stepDown(60,30)

#切换到从的mongodb上查看
kgcrs:SECONDARY> rs.isMaster()

6、尝试创建数据库写入数据(mongodb的增删改查操作),看是否主从同步
#在主的mongodb上操作:
kgcrs:PRIMARY> use kgc
kgcrs:PRIMARY> db.t1.insert({“id”:1,“name”:“zhangsan”})

在从的上面:
kgcrs:SECONDARY> rs.slaveOk()
kgcrs:SECONDARY> show dbs;

选举复制集:
MongoDB复制集的节点是通过选举产生主节点。

原理:
复制是基于操作日志oplog,相当于MySQL中的二进制日志,只记录发生改变的记录。复制是将主节点的oplog日志同步并应用到其他从节点过程。

选举复制集中的角色:
1:标准节点(host)(只有标准节点可能被选举为主(primary)节点,有选举权)
2:仲裁节点(arbiter)(不存放数据,只负责投票选举,不可能成为主节点,不存放数据,依然没有选举权)
3:被动节点(passive)(有完整副本,只能作为复制集保存,不可能成为主节点,没有选举权)
passives 被动节点 arbiters 仲裁节点

注:
1、标准节点与被动节点的区别:priority值高者是标准节点,低者则为被动节点
2、选举规则是票数高者获胜,priority是优先权为01000的值,相当于额外增加01000的票数。选举结果:票数高者获胜;若票数相同,数据新者获胜

7、指定节点的优先级,验证角色重选情况;

在主mongodb上:
方法一:
创建复制集的时候指定:
cfg={"_id":“kgcrs”,“members”:[
{"_id":0,“host”:“192.168.80.100:27017”,“priority”:100},
{"_id":1,“host”:“192.168.80.100:27018”,“priority”:100},
{"_id":2,“host”:“192.168.80.100:27019”,“priority”:0},
{"_id":3,“host”:“192.168.80.100:27020”,“arbiterOnly”:true}]}
#定义两个主节点,一个被动节点,一个仲裁节点

方法二:
在新增节点的时候设定该节点的优先级别
repSetTest:PRIMARY> rs.add({“host”:“127.0.0.1:27000”,“priority”:1.5})

方法三:
在已运行的复制集上修改优先级别和角色
1)PRIMARY> config=rs.conf()
2)PRIMARY>config.members[3].priority = 3
3)PRIMARY> rs.reconfig(config)

注意:第2步members大括号中面的成员和_id是没有关系的,而是rs.conf查出来节点的数值的顺序;
这些操作必须在Primary上进程。
Priority 0节点的选举优先级为0,不会被选举为Primary,这样的成员称为被动成员

kgcrs:PRIMARY> rs.initiate(cfg) #初始化复制集

kgcrs:PRIMARY> rs.isMaster()? #查看群集状态

8、验证复制集选举原理
(1)、查看oplog日志
kgcrs:PRIMARY> use testDB? ? #进入或创建库
kgcrs:PRIMARY> db.t1.insert({“id”:1,“name”:“Tom”}) #插入数据
kgcrs:PRIMARY> db.t1.insert({“id”:2,“name”:“Jack”})
kgcrs:PRIMARY> db.t1.find()? ? #查看集合
{ “_id” : ObjectId(“5b95c4c915740fa3d0077e8d”), “id” : 1, “name” : “Tom” }
{ “_id” : ObjectId(“5b95c4d715740fa3d0077e8e”), “id” : 2, “name” : “Jack” }

kgcrs:PRIMARY> db.t1.update({“id”:2},{"$set":{“name”:“Bob”}})? ? #修改数据
kgcrs:PRIMARY> db.t1.remove({“id”:2})? #移除数据
kgcrs:PRIMARY> show dbs
kgcrs:PRIMARY> use local? ? ? ? ? ? ? ? #进入local库
kgcrs:PRIMARY> show collections
kgcrs:PRIMARY> db.oplog.rs.find()? ? ? #注意查看每个文档都代表主节点上执行的一个操作,oplog会包含所有对数据有修改的操作(查询操作不会记录)

(2)、模拟主节点故障
ps aux | grep mongo
kill掉一个进程把主节点27017down掉

kgcrs:PRIMARY> rs.status()? ? #查看复制状态

9、复制集管理
(1)配置允许在从节点读取数据
1)、在主节点中创建数据库和集合
mongo --port 27017
kgcrs:PRIMARY> show dbs
kgcrs:PRIMARY> use testDB
kgcrs:PRIMARY> db.t1.find() #查询集合数据

2)从节点读取主节点数据:
mongo --port 27018
kgcrs:SECONDARY> rs.slaveOk()? ? #允许默认从节点读取数据
kgcrs:SECONDARY> show dbs
……
testDB? 0.000GB? ? ? #读取成功
kgcrs:SECONDARY> use testDB
kgcrs:SECONDARY> db.t1.find()

(2)查看复制集状态
查看oplog日志文件的大小及时间范围
kgcrs:SECONDARY> rs.printReplicationInfo()
configured oplog size:? 990MB? ? ? ? ? ? ? #oplog文件大小
log length start to end: 7688secs (2.14hrs) #日志启用的时间段。单位:秒
oplog first event time:? Wed Sep 12 2018 16:50:59 GMT+0800 (CST)? ? #第一个事务日志的产生时间
oplog last event time:? Wed Sep 12 2018 18:59:07 GMT+0800 (CST)? ? #第一个事务日志的结束时间
now:? ? ? ? ? ? ? ? ? ? Wed Sep 12 2018 18:59:16 GMT+0800 (CST)? ? #当前时间

查询节点及节点复制的时间
kgcrs:SECONDARY> rs.printSlaveReplicationInfo() #可以通过下面IP、端口发现,仲裁节点不具备数据复制
source: 192.168.100.76:27018? ? ? ? ? ? ? ? ? ? ? ? #从库的IP及端口? ?
? ? syncedTo: Wed Sep 12 2018 18:59:27 GMT+0800 (CST) #目前的同步情况,延迟了多久等信息
? ? 0 secs (0 hrs) behind the primary
source: 192.168.100.76:27019
? ? syncedTo: Wed Sep 12 2018 18:59:27 GMT+0800 (CST)
0 secs (0 hrs) behind the primary

(3)更给oplog大小
简介:oplog即operations log简写,存储在local数据库中。oplog中新操作会自动替换旧的操作,以保证oplog不会超过预设的大小。默认情况下,oplog大小会占用64位的实例5%的可用磁盘
原理:主节点应用业务操作修改到数据日志中,然后记录这些操作到oplog中,从节点复制这些oplog,然后应用这些修改。这些操作是异步的。如果从节点的操作已经被主节点落下很远,oplog日志在从节点还没执行完,oplog可能已经轮滚一圈了,从节点跟不上同步,复制就会停下,从节点需要重新做完整的同步,为了避免此种情况,尽量保证主节点的oplog足够大,能够存放相当长时间的操作记录
方法一 :离线调整oplog大小
1)、关闭从节点服务器
mongo --port 27018
kgcrs:SECONDARY> use admin
kgcrs:SECONDARY> db.shutdownServer() #关闭服务,从复制集成员退出来

2)、修改从节点主配置文件
vi   /etc/mongod2.conf
端口修改一下
port:  27028

3)、启动单实例
mongod  -f  mongod2.conf

4)、备份当前节点所有oplog记录
mongodump --port 27028 --db local --collection 'oplog.rs'

说明:
port? ? ? ? #指定端口
db? ? ? ? ? #指定数据库
collection? #指定集合

5)、更改oplog文件大小
mongo --port 27028
use local
db.oplog.rs.drop()? #删除oplog文件
db.runCommand({ create: "oplog.rs", capped: true, size: (2 * 1024 * 1024 * 1024)}) #重建文件,指定2048M的空间

6)、关闭服务
use admin
db.shutdownServer()

7)、修改从节点主配置文件
vim /etc/mongod2.conf
net:
? port: 27018? #约29行,把端口改成27018
replication:? ? #约37行,打开复制选项
? ? replSetName: kgcrs? 
? ? oplogSizeMB: 2048? #添加oplog日志文件大小2048MB

8)、启动
mongod  -f  mongod2.conf

mongo --port 27018

rs.printReplicationInfo()    #检查oplog大小和时间范围

rs.printSlaveReplicationInfo()   //查询节点及节点复制的时间

9)进行主从切换,让27018作为主服务器
kgcrs:PRIMARY> rs.freeze(30)? ? ? ? #暂停30秒不参加选举
kgcrs:PRIMARY> rs.stepDown(60,30)? ? #告知主节点交出主节点位置,然后维持从节点状态不少于60秒,同时等待30秒以使主节点和从节点日志同步

方法二:在线升级
在主节点上:
use local

db.oplog.rs.stats() #查看oplog.rs集合状态

rs.printReplicationInfo() #查看oplog大小

db.runCommand({“convertToCapped”:“oplog.rs”,“size”:102400000}) #更改oplog大小

db.oplog.rs.stats()

rs.printReplicationInfo()

(4)、部署认证复制
mongo --port 27018

1、在主服务器上,创建用户
kgcrs:PRIMARY> use admin
kgcrs:PRIMARY> db.createUser({“user”:“root”,“pwd”:“123”,“roles”:[“root”]})

2、修改配置文件,四个配置文件都得添加以下内容
vi /etc/mongod1.conf
security:? #约33行,开启认证功能
? keyFile: /usr/bin/kgcrskey1? #指定验证文件路径。!!!注意实例1是kgcrskey1 ;实例2是kgcrskey2;实例3是kgcrskey3
? clusterAuthMode: keyFile? ? #指定验证模式,秘钥文件验证

3、生成密钥文件 //密钥内容自定义,但是要保证内容的一致性
为了使其他的节点还能够和主节点进行同步,创建密钥文件使其他节点能够同步
cd /usr/bin/
echo “kgcrs key” > kgcrskey1
echo “kgcrs key” > kgcrskey2
echo “kgcrs key” > kgcrskey3
echo “kgcrs key” > kgcrskey4

注:密钥内容自定义,但是要保证内容的一致性

4、更改目录权限
chmod 600 kgcrskey{1…4} #复制集对keyFile的权限有要求,最多到600

5、重启所有服务,并访问
mongo --port 27017

直接查看当前所有数据库:
show dbs;

验证访问:
kgcrs:PRIMARY> use admin
kgcrs:PRIMARY> db.auth(“root”,“123”)

才能访问。

猜你喜欢

转载自blog.csdn.net/weixin_44381207/article/details/86590229