MongoDB复制集架构及典型三点复制集环境搭建

717 阅读9分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第25天,点击查看活动详情

一、复制集架构

在生产环境中,不建议使用单机版的MongoDB服务器。原因如下:

  • 单机版的MongoDB无法保证可靠性,一旦进程发生故障或是服务器宕机,业务将直接不可用。
  • 一旦服务器上的磁盘损坏,数据会直接丢失,而此时并没有任何副本可用。

Mongodb复制集(Replication Set)由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写入Primary,Secondary从Primary同步写入的数据(Secondary读取Primary的opLog),以保持复制集内所有成员存储相同的数据集,提供数据的高可用。复制集提供冗余和高可用性,是所有生产部署的基础。它的现实依赖于两个方面的功能:

  • 数据写入时将数据迅速复制到另一个独立节点上
  • 在接受写入的节点发生故障时自动选举出一个新的替代节点

image.png

在实现高可用的同时,复制集实现了其他几个附加作用:

  • 数据分发: 将数据从一个区域复制到另一个区域,减少另一个区域的读延迟
  • 读写分离: 不同类型的压力分别在不同的节点上执行(默认Secondary不允许读,需进行设置)
  • 异地容灾: 在数据中心故障时候快速切换到异地

Primary和Secondary默认每2s进行一次心跳监测,mongodb运行有50个节点,但是最多允许7个节点参与Primary的选举(为了提交性能)

早期版本的MongoDB使用了一种Master-Slave的架构,该做法在MongoDB 3.4版本之后已经废弃。

1-1、复制集群的问题

1、mongodb在写数据的时候,首先会写数据、写索引、同时写opLog日志,如果为了保证数据保存成功还需要写journaled日志

2、可能会发生如下场景:当主节点数据写入成功,从节点还未来得及从主节点拉取数据的时候,主节点挂了,这样从节点通过选举成为新的主节点,这样刚刚写入的数据就丢失了。

3、复制集群,Secondary节点不支持写操作,因此如果要增加写操作吞吐量需要使用分片集群。

1-1-1、writeConcern

这样该如何处理呢?可以通过在写入数据的时候,设置writeConcern

writeConcern 的取值包括:

0:发起写操作,不关心是否成功;

1~集群最大数据节点数:写操作需要被复制到指定节点数才算成功;

majority:写操作需要被复制到大多数节点上才算成功。

在客户端可以进行如下设置: 至少要写入两个节点,超时时间是5s(设置超时时间,防止服务断联一直阻塞)

db.products.insert( 
  { item: "envelopes", qty : 100, type: "Clasp" },
  { writeConcern: { w: 2, wtimeout: 5000 } } 
 )

1-1-2、Journaled

Journaled方式是要保证服务器端已经写入到硬盘文件了,服务器保证写入到磁盘后再相应客户端,即使当机了,也不会导致数据丢失。

1-1、三节点复制集模式

常见的复制集架构由3个成员节点组成,其中存在几种不同的模式。

PSS模式(官方推荐模式)

PSS模式由一个主节点和两个备节点所组成,即Primary+Secondary+Secondary。
 

image.png

此模式始终提供数据集的两个完整副本,如果主节点不可用,则复制集选择备节点作为主节点并继续正常操作。旧的主节点在可用时重新加入复制集

image.png

PSA模式

PSA模式由一个主节点、一个备节点和一个仲裁者节点组成,即Primary+Secondary+Arbiter,PSA不支持动态事务

image.png 其中,Arbiter节点不存储数据副本,也不提供业务的读写操作。Arbiter节点发生故障不影响业务,仅影响选举投票。此模式仅提供数据的一个完整副本,如果主节点不可用,则复制集将选择备节点作为主节点。

image.png

二、典型三节点复制集环境搭建

即使暂时只有一台服务器,也要以单节点模式启动复制集

  • 单机多实例启动复制集
  • 单节点启动复制集

2-1、复制集注意事项

关于硬件:

  • 因为正常的复制集节点都有可能成为主节点,它们的地位是一样的,因此硬件配置上必须一致;
  • 为了保证节点不会同时宕机,各节点使用的硬件必须具有独立性。

关于软件:

  • 复制集各节点软件版本必须一致,以避免出现不可预知的问题。
  • 增加节点不会增加系统写性能

2-2、环境准备

  • 安装 MongoDB并配置好环境变量
  • 确保有 10GB 以上的硬盘空间

2-2-1、准备配置文件

复制集的每个mongod进程应该位于不同的服务器。我们现在在一台机器上运行3个进程,因此要为它们各自配置:

  • 不同的端口(28017/28018/28019)
  • 不同的数据目录
mkdir -p /data/db{1,2,3}
  • 不同日志文件路径(例如:/data/db1/log/mongod.log)

创建配置文件/data/db1/mongod.conf,内容如下:

# /data/db1/mongod.conf
systemLog:
  destination: file
  path: /usr/local/soft/mongodb/data/db1/log/mongod.log # log path
  logAppend: true
storage:
  dbPath: /usr/local/soft/mongodb/data/db1 # data directory
net:
  bindIp: 0.0.0.0
  port: 28017 # port
#设置复制集名称
replication:
  replSetName: rs0
processManagement:
  fork: true

参考上面配置修改端口,路径,依次配置db2,db3。注意必须是yaml格式,同时多了一个replication.replSetName: rs0这个是设置集群名称,后面也会用到。

2-2-2、启动 MongoDB 进程

mongod -f /usr/local/soft/mongodb/data/db1/mongod.conf
mongod -f /usr/local/soft/mongodb/data/db2/mongod.conf
mongod -f /usr/local/soft/mongodb/data/db3/mongod.conf

image.png

注意:如果启用了 SELinux,可能阻止上述进程启动。简单起见请关闭 SELinux。

# 永久关闭,将SELINUX=enforcing改为SELINUX=disabled,设置后需要重启才能生效
vim /etc/selinux/config
# 查看SELINUX
/usr/sbin/sestatus -v

2-3、配置复制集

复制集通过replSetInitiate命令或mongo shell的rs.initiate()进行初始化,初始化后各个成员间开始发送心跳消息,并发起Priamry选举操作,获得『大多数』成员投票支持的节点,会成为Primary,其余节点成为Secondary。

  • 方法1
# mongo --port 28017
# 初始化复制集
  > rs.initiate()
# 将其余成员添加到复制集
  > rs.add("192.168.65.174:28018")
  > rs.add("192.168.65.174:28019")

image.png

因为登录28017,然后将28018和28019加入集群,这时28017被作为主节点,28018和28019则作为从节点,可以通过rs.status()进行集群状态查看

  • 方法2
# mongo --port 28017
# 初始化复制集
> rs.initiate({
    _id: "rs0",
    members: [{
        _id: 0,
        host: "192.168.65.174:28017"
    },{
        _id: 1,
        host: "192.168.65.174:28018"
    },{
        _id: 2,
        host: "192.168.65.174:28019"
    }]
})

2-3-1、验证

MongoDB 主节点进行写入

# mongo --port 28017
rs0:PRIMARY> db.user.insert([{name:"jony1"},{name:"jony2"}])  

MongoDB 从节点进行读

# mongo --port 28018
# 指定从节点可读-默认从节点不可读
rs0:SECONDARY> rs.secondaryOk()
rs0:SECONDARY> db.user.find()  

如下数据已经被从节点获取到了

image.png

2-4、复制集状态查询

  • 查看复制集整体状态:
rs.status()

可查看各成员当前状态,包括是否健康,是否在全量同步,心跳信息,增量同步信息, 选举信息,上一次的心跳时间等。

image.png

members一列体现了所有复制集成员的状态,主要如下:

health:成员是否健康,通过心跳进行检测。

state/stateStr:成员的状态,PRIMARY表示主节点,而SECONDARY则表示备节点,如果节点出现故障,则可能出现一些其他的状态,例如RECOVERY。

uptime:成员的启动时间。

optime/optimeDate:成员最后一条同步oplog的时间。

optimeDurable/optimeDurableDate:成员最后一条同步oplog的时间。

pingMs:成员与当前节点的ping时延。

syncingTo:成员的同步来源。

  • 查看当前节点角色:
db.isMaster()

除了当前节点角色信息,是一个更精简化的信息,也返回整个复制集的成员列表,真正的Primary是谁,协议相关的配置信息等,Driver 在首次连接复制集时会发送该命令。

2-4-1、Mongo Shell复制集命令

命令描述
rs.add()为复制集新增节点
rs.addArb()为复制集新增一个 arbiter
rs.conf()返回复制集配置信息
rs.freeze()防止当前节点在一段时间内选举成为主节点
rs.help()返回 replica set 的命令帮助
rs.initiate()初始化一个新的复制集
rs.printReplicationInfo()以主节点的视角返回复制的状态报告
rs.printSecondaryReplicationInfo()以从节点的视角返回复制状态报告
rs.reconfig()通过重新应用复制集配置来为复制集更新配置
rs.remove()从复制集中移除一个节点
rs.secondaryOk()为当前的连接设置 从节点可读
rs.status()返回复制集状态信息。
rs.stepDown()  让当前的 primary 变为从节点并触发 election
rs.syncFrom()设置复制集节点从哪个节点处同步数据,将会覆盖默认选取逻辑
rs.isMaster()查看当前角色节点

2-5、安全认证

2-5-1、创建用户

在主节点服务器上,启动mongo

use admin
#创建用户
db.createUser( {
    user: "jony",
    pwd: "111111",
    roles: [ { role: "clusterAdmin", db: "admin" } ,
    { role: "userAdminAnyDatabase", db: "admin"},
    { role: "userAdminAnyDatabase", db: "admin"},
    { role: "readWriteAnyDatabase", db: "admin"}]
})  

image.png

2-5-2、创建keyFile文件

keyFile文件的作用: 集群之间的安全认证,增加安全认证机制KeyFile(开启keyfile认证就默认开启了auth认证了)

#mongo.key采用随机算法生成,用作节点内部通信的密钥文件。
openssl rand -base64 123 > /usr/local/soft/mongodb/data/mongo.key
#权限必须是600
chmod 600 /data/mongo.key   

image.png

注意:创建keyFile前,需要先停掉复制集中所有主从节点的mongod服务,然后再创建,否则有可能出现服务启动不了的情况。

将主节点中的keyfile文件拷贝到复制集其他从节点服务器中,路径地址对应mongo.conf配置文件中的keyFile字段地址,并设置keyfile权限为600

启动mongod

# 启动mongod--当前目录在mongodb下的data目录下
mongod -f /usr/local/soft/mongodb/data/db1/mongod.conf -keyFile mongo.key
mongod -f /usr/local/soft/mongodb/data/db2/mongod.conf -keyFile mongo.key
mongod -f /usr/local/soft/mongodb/data/db3/mongod.conf -keyFile mongo.key      

image.png

测试

#进入主节点 
mongo --port 28017

如下图开启权限之后,不使用用户名密码就无法查询数据了 image.png

#进入节点 
mongo --port 28017 -ujony -p111111 --authenticationDatabase=admin

image.png

2-6、复制集连接方式

方式一:直接连接 Primary 节点,正常情况下可读写 MongoDB,但主节点故障切换后,无法正常访问

image.png

方式二(强烈推荐):通过高可用 Uri 的方式连接 MongoDB,当 Primary 故障切换后,MongoDB Driver 可自动感知并把流量路由到新的 Primary 节点

image.png

springboot操作复制集配置

spring:
    data:
        mongodb:
            uri: mongodb://jony:jony@192.168.65.174:28017,192.168.65.174:28018,192.168.65.174:28019/test?authSource=admin&replicaSet=rs0