DBA MongoDB 复制集群
功能概述
MongoDB的复制集rs与MySQL的MHA架构相似,也是做高可用的。
MongoDB复制集本身是一种单活架构,搭建条件最少是1主2从,可由单机多实例构成。
但是它并不是一次性的服务,在主库宕机后能够持续的工作,而非停止服务。
同时,rs的从库不可写,自带读写分离机制(需要指定),但MHA架构可不管这些。
基础知识
故障恢复
当复制集成功运作后,会在具有投票权的节点之间互相发送心跳。
当5次心跳未收到时,则判断节点失联,如果失联的是主节点,从节点会发起选举,选出新的主节点,而如果失联的是从节点,则不会产生新的选举。
选举过程基于RAFT一致性算法实现,选举成功的必要条件是大多数投票节点都存活。
一个复制集中最多可以有50个节点,但具有投票权的节点至多只能有7个。
投票机制
为什么MongoDB复制集必须要1主2从呢?其实也不一定,但是有一个前提即确保节点数必须为单数。
在PRIMARY库宕机后,会通过投票机制来选取新的PRIMARY库,如果是双数,则可能导致出现平票的情况。
在某些场景中,我们可能只需要1主1从外加投票节点的一种机制(这种情况比较少见,更常见的是1主1从1延迟从),则可以通过某些参数进行配置。
注意:投票节点永不参与竞选,也不会存储任何业务数据,仅负责投票。
如果想成为主节点,则该从节点至少要有下面几点要求:
- 能够与大多数节点建立链接
- 具有较新的oplog,与已宕机的主节点oplog差异最小
- 根据配置项的优先级来进行选举(如果有的话)
复制过程
当一个修改操作,无论是插入、删除、或者更新,到达主节点后,与MySQL中日志优先写的策略一样,这些变更记录会存储在一个oplog的文件中(类似于MySQL的binlog)。
从节点通过在主节点上打开tailable游标,不断获取新进入主节点的oplog,并在自己的数据上进行回放操作,以此保证跟主节点的数据一致性。
大体思路和MySQL差不多,可以查看之前MySQL的主从搭建文章。
节点配置
常见的节点配置有以下几种:
- 节点投票权:是否具有投票权
- 选主优先级:是否能优先成为新主,优先级为0的节点无法参与竞选
- 隐藏节点(hidden):只复制数据,但对应用不可见,隐藏节点可以具有投票权,但优先级必须为0
- 延迟节点(delay):复制主库N秒之前的数据,保持时间差防止误操作,一般来说延迟节点也会设置为隐藏节点
- 投票节点(arbiter):仅投票,不存储业务数据,不提供任何服务,不参与选主
搭建过程
实例准备
由于MongoDB的复制集支持单机多实例的配置。
所以我们在单机上搭建3个MongoDB实例,端口号规划如下:
27017:PRIMAY节点
27018:SECONDARY节点
27019:SECONDARY节点
首先停用掉已有的MongoDB服务:
T > systemctl stop mongod.service
准备目录:
T > mkdir -p /usr/local/mongors/2701{8,9}
T > mkdir -p /usr/local/mongors/2701{8,9}/data
T > mkdir -p /usr/local/mongors/2701{8,9}/logs
T > mkdir -p /usr/local/mongors/2701{8,9}/conf
准备配置文件,注意三份节点的路径配置,在需要修改的地方我都打了注释:
systemLog:
destination: file
path: "/usr/local/mongors/27018/logs/mongod.log" # logpath
logAppend: true
storage:
journal:
enabled: true
dbPath: "/usr/local/mongors/27018/data" # dbpath
directoryPerDB: true
processManagement:
fork: true
net:
bindIp: 0.0.0.0
port: 27018 # port
replication:
oplogSizeMB: 2048
replSetName: rs0 # 复制集名称,记录下来
# 我的主库27017开启了权限认证
# security:
# authorization: enabled
修改权限:
T > chown -R mongod:mongod /usr/local/mongors
此时你可以对另外两个额外的实例搭建sys系统服务,方便后续管理,也可以通过常规方式进行启动。我就不搭建了,接下来开始启动服务:
T > systemctl start mongod.service
T > mongod -f /usr/local/mongors/27018/conf/mongod.conf
T > mongod -f /usr/local/mongors/27019/conf/mongod.conf
尝试登陆三个实例,查看实例是否搭建成功:
T > mongo -uroot -p123 127.0.0.1:27017/admin
T > mongo --port 27018
T > mongo --port 27019
或者使用ps命令查看进程:
T > ps -ef | grep mongo
集群搭建
登陆主库27017,开始集群搭建:
T > mongo -uroot -p123 127.0.0.1:27017/admin
接下来初始化集群:
> rs.initiate()
此时标志符会发生改变:
rs0:SECONDARY>
rs0:PRIMARY>
添加从节点:
rs0:PRIMARY> rs.add("centos:27018")
rs0:PRIMARY> rs.add("centos:27019")
# 注意:此时添加从节点最好使用hostname进行添加,
# 我的hostname是centos
# 如果使用127.0.0.1的方式,会造成添加不进去的问题
通过以下命令查看复制集状态,确定子节点都被成功添加:
rs0:PRIMARY> rs.status()
尝试写入数据:
rs0:PRIMARY> use db1
rs0:PRIMARY> db.collection.insert({"k":"v"})
登录27018,27019,查看shell提示符是否改变:
T > mongo --port 27018
T > mongo --port 27019
rs0:SECONDARY>
如果发生改变,在27018和27019中输入以下命令,启动复制:
rs0:SECONDARY> rs.secondaryOk()
# 旧版命令:rs.slaveOk()
查看从节点中是否复制成功:
rs0:SECONDARY> show dbs
admin 0.000GB
config 0.000GB
db1 0.000GB
local 0.000GB
搭建方式
除了上面的一种搭建方式外,你也可以选用另一种搭建方式,在主节点中创建一个全局变量,再通过配置的方式将全局变量导入到搭建集群的函数rs.initiate()中:
> config = {
"_id" : "rs0",
members : [
{"_id" : 0, "host" : "hostname:27017"},
{"_id" : 1, "host" : "hostname:27018"},
{"_id" : 2, "host" : "hostname:27019"},
]
}
> rs.initiate(config)
节点管理
查看复制集状态的三个基本命令,需要登录主库中操作:
命令 | 描述 |
---|---|
rs.status() | 查看整体复制集状态 |
rs.isMaster() | 查看所有的节点信息,方便查找主节点 |
rs.conf() | 查看复制集的配置信息 |
在主库中你可以添加和删除任意节点,命令如下所示:
命令 | 描述 |
---|---|
rs.add(“ip:port”) | 新增从节点 |
rs.remove(“ip:port”) | 删除从节点 |
rs.addArb(“ip:port”) | 新增仲裁节点(投票节点) |
如果要对配置文件中进行修改,如设置延迟节点等,可使用如下的方式操作:
# 复制配置到全局变量中
cfg = rs.conf()
# 选取节点,修改配置信息,下标从0开始,2就是第3个节点
# 选主优先级
cfg.members[2].priorty = 0
# 隐藏节点
cfg.members[2].hidden = true
# 设定延迟节点
cfg.members[2].slaveDelay= 60*60*4 # 4小时
# 应用配置项
rs.reconfig(cfg)
如果要监控主从延时状态,请在延时从库下执行以下命令:
rs.printSlaveReplicationInfo()
读写分离
关于读写分离、应用层接入等事宜,请查看下篇文章。
MongoDB事务相关