MongoDB副本集

1.介绍

MongoDB 副本集(Replica Set)是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组成。类似于MySQL的MMM架构。更多关于副本集的介绍请见官网

2.原理

副本集中数据同步过程:Primary节点写入数据,Secondary通过读取Primary的oplog得到复制信息,开始复制数据并且将复制信息写入到自己的oplog。如果某个操作失败,则备份节点停止从当前数据源复制数据。如果某个备份节点由于某些原因挂掉了,当重新启动后,就会自动从oplog的最后一个操作开始同步,同步完成后,将信息写入自己的oplog,由于复制操作是先复制数据,复制完成后再写入oplog,有可能相同的操作会同步两份,不过MongoDB在设计之初就考虑到这个问题,将oplog的同一个操作执行多次,与执行一次的效果是一样的。简单的说就是:

当Primary节点完成数据操作后,Secondary会做出一系列的动作保证数据的同步

  • 检查自己local库的oplog.rs集合找出最近的时间戳。
  • 检查Primary节点local库oplog.rs集合,找出大于此时间戳的记录。
  • 将找到的记录插入到自己的oplog.rs集合中,并执行这些操作。

副本集的同步和主从同步一样,都是异步同步的过程,不同的是副本集有个自动故障转移的功能。其原理是:slave端从primary端获取日志,然后在自己身上完全顺序的执行日志所记录的各种操作(该日志是不记录查询操作的),这个日志就是local数据 库中的oplog.rs表,默认在64位机器上这个表是比较大的,占磁盘大小的5%,oplog.rs的大小可以在启动参数中设 定:–oplogSize 1000,单位是M。

注意:在副本集的环境中,要是所有的Secondary都宕机了,只剩下Primary。最后Primary会变成Secondary,不能提供服务。

2.1自动切换

集群开始如下:

image-20200730214916761

primary挂了以后:

image-20200730215028695

3.环境搭建

3.1环境准备

IP 主机名 系统 安装软件
10.0.0.100 Server1 centos7 mongodb
10.0.0.101 Server2 centos7 mongodb
10.0.0.102 Server3 centos7 mongodb

安装过程就忽略了。。。。

在每个服务器的mongodb配置文件加上:

//yaml格式
replication:
replSetName: repset
//如果是普通格式化
replSet=anthony

mongod的配置文件,有yaml格式也有普通的=格式。

yaml格式的参考 https://docs.mongodb.com/manual/reference/configuration-options/#replication.replSetNam

4.初始化配置复制集

4.1 在主服务器创建复制集

我们先配置包含两个节点的复制集,多出来的一个节点,会在接下来再做一个节点添加的操作

mongo
server={"_id":"anthony","members":[{"_id":0,"host":"10.0.0.101:27017"},{"_id":1,"host":"10.0.0.102:27017"}]}

4.2 初始化复制集

在初始化复制集时,要确保从节点没有数据,不然在初始化以后会造成从节点服务器的数据丢失。

rs.initiate(server)

4.3 查看复制集中各节点状态

anthony:SECONDARY> rs.status()
{
"set" : "anthony",
"date" : ISODate("2020-07-14T14:40:20.756Z"),
··· //省略部分内容
"members" : [
{
"_id" : 0,
"name" : "10.0.0.100:27017",
"health" : 1, //健康值为1,代表该节点处于运行良好状态
"state" : 1, //1代表主
"stateStr" : "PRIMARY", //处于peimary状态
··· //省略部分内容
},
{
"_id" : 1,
"name" : "10.0.0.101:27017",
"health" : 1,
"state" : 2, //2代表从
"stateStr" : "SECONDARY", //处于secondary状态
··· //省略部分内容
},
{
"_id" : 2,
"name" : "10.0.0.102:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
··· //省略部分内容
}
}
anthony:PRIMARY> //此时节点状态已经发生转变

5.节点管理(在primary上做)

1. 添加节点

rs.add("10.0.0.103:27017")

2. 删除节点

rs.remove("10.0.0.103:27017")

6.故障转移切换

1. 模拟主节点损坏

ps aux | grep  mongod     //查询本地的节点的进程号
kill -9 40882 //杀死主节点进程

2. 查看节点状态

anthony:SECONDARY> rs.status()
{
"set" : "anthony",
"date" : ISODate("2020-07-14T15:21:21.426Z"),
"myState" : 2,
"term" : NumberLong(2),
"syncingTo" : "10.0.0.102:27017",
"syncSourceHost" : "10.0.0.102:27017",
"syncSourceId" : 2,
··· //省略部分内容
"members" : [
{
"_id" : 0,
"name" : "10.0.0.100:27017",
"health" : 0, //健康值为0,处于停机状态
"state" : 8,
"stateStr" : "(not reachable/healthy)",
··· //省略部分内容
},
{
"_id" : 1,
"name" : "10.0.0.101:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
··· //省略部分内容
},
{
"_id" : 2,
"name" : "10.0.0.102:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
··· //省略部分内容
}
}

7.主动切换主从状态(在primary上做)

rs.freeze(30)      //暂停30s不参与选举
rs.stepDown(60,30) //交出主节点位置,维持从节点状态不少于60秒,等待30秒使主节点和从节点日志同步