MongoDB 副本集

一、副本集概念

单节点的 MongoDB 在数据的安全和冗余方面是比较低的,在生产环境中,我们为 MongoDB 配置副本集,这样可以提高数据的高可用性和安全性。

副本集 :是一组 Mongod 维护相同数据集的实例。副本集可以包含多个数据承载点和多个仲裁点。在承载数据的节点中,仅有一个节点被视为主节点,其他节点称为次节点。

副本集的节点角色:

  • Primary 主节点,用于承担
  • Secondary 次节点
  • Arbiter 仲裁节点,也是属于次节点

主节点接收所有的数据写入操作,主节点记录数据的所有更改,即oplog

副本集架构图

  • 一个 主节点 两个次节点(Secondary )

  • 一个主节点两个次节点(一个Secondary 节点,一个Arbiter 节点)

将一个额外的mongod实例添加到副本集作为 仲裁节点。仲裁节点不维护数据集。仲裁节点的目的是通过响应其他副本集成员的心跳和选举请求来维护副本集中的选举。因为它们不存储数据集,所以仲裁节点可以是提供副本集仲裁功能的好方法,其资源成本比具有数据集的全功能副本集成员更低。如果您的副本集具有偶数个成员,请添加仲裁者以避免脑裂出现。

  • 主节点故障后重新选举主节点

在主节点未与配置中的其它成员通信超过 10s(默认为10s)的话,则符合条件的次节点将推选自己为主节点。

在选举成功完成之前,副本集无法处理写入操作。

electionTimeoutMillis 默认值为10000(10s) ,我们可以根据自己的项目情况来升高或者降低该值,我们在更改该值的时候需要考虑到网络延迟等因素。

默认情况下,副本集在选取新的主节点的等待时间不超过12秒(主要用于将原有主节点标记为不可用,并选举出新的主节点),

副本集数据同步

为了保持次节点与主节点的数据同步,MongoDB 使用两种方式进行数据的同步:

  • 初始同步, 用于同步主节点的所有数据

    初始同步将所有的数据从副本集的一个成员复制到另外一个成员

  • 增量同步,在初始同步后不断复制新的数据

    在初始同步后不断复制数据,次节点从主节点中同步复制 Oplog,并在异步过程中应用这些操作

Oplog 详解

MongoDB-Oplog详解

注意

副本集在部署前需要确定成员数据,副本集最多能有50个节点,但是只能有7个节点拥有被选举权,副本集需要具有奇数个投票成员,如果有偶数个的话,可以添加一个 仲裁者,来保证有奇数个成员,避免脑裂情况发生,

尽量使用 主机名 来寻找对应的节点,而不是使用 ip 地址,避免 ip 改变导致配置需要更改。

二、副本集部署

部署准备

部署需要更改 /etc/hosts 文件,将主机名和 ip 地址对应好,不应该使用ip。

使用统一的端口。

创建数据储存的位置和配置文件的位置。

确定好副本集的名称

搭建架构选择

  • 三节点,一个主节点,一个次节点,一个仲裁节点

副本集部署

基本环境:
系统 CentOS 7
MongoDB 版本 4.0.8 3个节点
fymongodb001 内网IP:172.18.186.161 公网ip: 47.112.129.2 # 主节点
fymongodb002 内网IP: 172.18.186.162 公网ip: 47.112.131.231 # 次节点
fymongodb003 内网IP: 172.18.186.163 公网ip: 47.112.98.64 # 仲裁节点 副本集名称: fymongodb

三个节点都需要执行

# 下载mongodb
cat <<EOF >>/etc/hosts
172.18.186.161 fymongodb001
172.18.186.162 fymongodb002
172.18.186.163 fymongodb003
EOF
cd /tmp && wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.8.tgz
tar -zxf mongodb-linux-x86_64-4.0.8.tgz
mv mongodb-linux-x86_64-4.0.8 /opt/mongodb
mkdir /opt/mongodb/{data,logs}
useradd mongodb
# 我们这里使用的配置文件 是YAML 格式的
wget https://raw.githubusercontent.com/tobewithyou1996/LinuxGuide/master/MongoDB/mongodb_rep.yaml -P /opt/mongodb/
chown -R mongodb:mongodb /opt/mongodb/
cat <<EOF >>/usr/lib/systemd/system/mongodb.service
[Unit]
Description= mongodb service manager
[Service]
# Other directives omitted
# (file size)
LimitFSIZE=infinity
# (cpu time)
LimitCPU=infinity
# (virtual memory size)
LimitAS=infinity
# (locked-in-memory size)
LimitMEMLOCK=infinity
# (open files)
LimitNOFILE=64000
# (processes/threads)
LimitNPROC=64000
Type=forking
User=mongodb
Group=mongodb
PIDFile=/opt/mongodb/logs/mongod.pid
ExecStart= /opt/mongodb/bin/mongod -f /opt/mongodb/mongodb_rep.yaml
ExecStop= /opt/mongodb/bin/mongod --shutdown --dbpath /opt/mongodb/data
Restart=always
[Install]
WantedBy=multi-user.target
EOF
# 添加环境变量
echo "export PATH=$PATH:/opt/mongodb/bin" >>/etc/profile
source /etc/profile
# 启动
systemctl start mongodb

主节点操作

# 主节点操作
[root@fymongodb001 tmp]# mongo
MongoDB shell version v4.0.8
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("77f60167-1d37-4796-bf2a-60cfdc4b0526") }
MongoDB server version: 4.0.8
> use admin # 切换到 admin 数据库
switched to db admin
# 初始化副本集,副本集名称为 fymongodb ,第一个成员为自己本身。
> rs.initiate({_id:'fymongodb',members: [{ _id: 0 , host: "fymongodb001:27017"}]})
{ "ok" : 1 }
fymongodb:SECONDARY> # 接着回车,直到显示这个节点为Primary主节点
fymongodb:PRIMARY> # 接着添加 次节点 fymongodb002
# 添加次节点
fymongodb:PRIMARY> rs.add('fymongodb002:27017')
{
"ok" : 1,
"operationTime" : Timestamp(1555663440, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1555663440, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
# 添加仲裁节点
fymongodb:PRIMARY> rs.addArb("fymongodb003:27017")
{
"ok" : 1,
"operationTime" : Timestamp(1555663631, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1555663631, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
# 查看当前配置
fymongodb:PRIMARY> rs.conf()
{
"_id" : "fymongodb",
"version" : 3,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
{
"_id" : 0,
"host" : "fymongodb001:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : { },
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "fymongodb002:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : { },
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "fymongodb003:27017",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 0,
"tags" : { },
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : -1,
"catchUpTakeoverDelayMillis" : 30000,
"getLastErrorModes" : { },
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5cb98534cd9d16ff3f4fffdc")
}
}
# rs.status() 查看各个节点的身份

当我们完成上面的操作的时,我们主节点更改的数据已经是会自动同步到次节点的。

次节点操作

fymongodb002次节点(Secondary)设置允许读写操作。

[root@fymongodb002 ~]# mongo
MongoDB shell version v4.0.8
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("f353edd5-d79a-4947-9844-7f9bde98a949") }
MongoDB server version: 4.0.8
fymongodb:SECONDARY> fymongodb:SECONDARY> show dbs; # 我们发现无法读写
2019-04-19T17:04:40.852+0800 E QUERY [js] Error: listDatabases failed:{
"operationTime" : Timestamp(1555664675, 1),
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk",
"$clusterTime" : {
"clusterTime" : Timestamp(1555664675, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
} :
fymongodb:SECONDARY> rs.slaveOk() # 允许 次节点 进行读取
fymongodb:SECONDARY> show dbs; # 我们就可以查看到次节点的数据了。
admin 0.000GB
config 0.000GB
djx 0.000GB
local 0.000GB
fymongodb:SECONDARY> use djx;
switched to db djx
fymongodb:SECONDARY> show collections; # 从主节点同步过来的数据。
djx
lsp

数据同步测试

测试数据的同步,我们在主节点创建一个集合test 并添加一条数据 'age':38 ,我们可以看到次节点也同步了该数据。

故障模拟测试

测试一

模拟主节点 fymongodb001 宕机了,然后查看次节点 fymongodb002 是否会被选举成为主节点。

我们可以看到 fymongodb002 选举为主节点.

测试二

fymongodb002 选举为主节点后,fymongodb001 恢复了,fymongodb001 会作为次节点加入。

测试三

测试在次节点(Secondary)进行数据删除。是删除不了的。

fymongodb:SECONDARY> db.test.drop()
2019-04-19T21:48:38.140+0800 E QUERY [js] Error: drop failed: {
"operationTime" : Timestamp(1555681711, 1),
"ok" : 0,
"errmsg" : "not master",
"code" : 10107,
"codeName" : "NotMaster",
"$clusterTime" : {
"clusterTime" : Timestamp(1555681711, 1),
"signature" : {
"hash" : BinData(0,"I+dFkOHcdqW+La7xvy8JFij+5CY="),
"keyId" : NumberLong("6681517989155569665")
}
}
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
DBCollection.prototype.drop@src/mongo/shell/collection.js:707:1
@(shell):1:1

配置副本集登录验证

副本集配置用户和密码,登录主节点,添加admin 用户。

> use admin
switched to db admin
> db.createUser({ user: "admin", pwd: "9toc7tpji8", roles: [{ role: "root", db: "admin" }] })
Successfully added user: {
"user" : "admin",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}

在主节点生成 keyflie 并复制到其它两个节点

# 生成 keyFile
openssl rand -base64 90 -out /opt/mongodb/keyfile
#并复制到其它两个节点
scp /opt/mongodb/keyfile fymongodb002:/opt/mongodb/
scp /opt/mongodb/keyfile fymongodb003:/opt/mongodb/

更改三个节点的 keyFile 文件权限和所有者

chmod 600 /opt/mongodb/keyfile  # 一定要更改成 600 权限,否正会报错
chown mongodb:mongodb /opt/mongodb/keyfile # 更改文件所有者

更改三个节点的 mongodb_rep.yaml 配置文件,将 security 的参数 authorization 设置为 enabled,并配置

keyFile 的路径。

security:
authorization: "enabled"
keyFile: '/opt/mongodb/keyfile'
clusterAuthMode: "keyFile"

然后依次重启 fymongodb001fymongodb002fymongodb003

# fymongodb001
systemctl restart mongodb
# fymongodb002
systemctl restart mongodb
# fymongodb003
systemctl restart mongodb

登陆 fymongodb001,我们使用 db.auth() 进行登陆验证。

fymongodb:PRIMARY> show dbs;
fymongodb:PRIMARY> use admin
switched to db admin
fymongodb:PRIMARY> db.auth('admin','9toc7tpji8')
1
fymongodb:PRIMARY> show dbs;
admin 0.000GB
config 0.000GB
local 0.000GB

三 、副本集维护

副本集成员如何以单节点启动

副本集当做单节点启动需要更改配置文件,主要的配置文件有以下几点:

  • 注释副本集名称设置,replSet=fymongodb
  • 更改端口
  • 如果是分片储存的,那么还需要注释分片配置,添加 skipShardingConfigurationChecks = true。

然后我们执行维护完后,关闭节点

use admin
db.shutdownServer()

然后还原原来的配置,然后作为副本集成员加入副本集。

副本集设置节点的优先级

如果我们想让某个节点成为主节点,或者是当主节点 down 了后,你想指定某个节点 优先级更高地成为 次节点。

cfg = rs.conf()
cfg.members[0].priority = 0.5
cfg.members[1].priority = 0.5
cfg.members[2].priority = 1
rs.reconfig(cfg)

副本集使用备份数据进行启动

# 使用备份数据进行启动
mongod --dbpath /data/db
# 删除 local 数据库
use local
db.dropDatabase()
# 指定副本集名称并以备份数据 启动
mongod --dbpath /data/db --replSet <replName>
# 启动副本集
rs.initiate( {
_id : <replName>,
members: [ { _id : 0, host : <host:port> } ]
})

副本集数据量比较大时如何添加次节点

当副本集的数据量比较大的时候,我们添加新的节点的时候,如果使用初始化同步的话,会给主节点造成比较大的压力。我们有以下选择:

  • 暂停当前副本集中的一个次节点,然后将 次节点的数据(data)复制到要新添加的节点的数据目录。然后再将两个节点启动。(建议先测试)

    如果要复制数据文件,请确保您的副本包含local数据库的内容。

  • 指定同步节点 rs.syncFrom(hostportstr),指定同步节点为次节点,默认的是同步节点 是主节点。

    但是该设置在重新启动节点,或者同步指定的新节点的连接被关闭了,是会失效的。(建议先测试)

  • 如果我们决定还是从主节点进行同步数据。

副本集延迟节点

延迟节点在此未记录,详细见官方文档。

副本集常用命令

# 副本集初始化
rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "mongodb0.example.net:27017" },
{ _id: 1, host: "mongodb1.example.net:27017" },
{ _id: 2, host: "mongodb2.example.net:27017" }
]
})
# 副本集添加成员
rs.add('mongodb3.example.net:27017')
# 副本集添加仲裁节点
rs.addArb('mongodb4.example.net:27017')
# 移除节点
rs.remove('hostportstr')
# 查看当前的配置
rs.conf()
# 查看各个节点状态和身份
rs.status()
# 设定某个节点多少秒不可成为主节点
rs.freeze(secs)
# 设置次节点从指定节点同步数据
rs.syncFrom(hostportstr)
# 降低主节点为次节点,只能在主节点上运行
rs.stepDown([stepdownSecs, catchUpSecs])
# 查看帮助
rs.help()
# 次节点执行,表示允许次节点读取数据
rs.slaveOk()
# 判断当前节点是否是主节点
rs.isMaster()
# 查看 Oplog 信息
rs.printReplicationInfo()
# 查看副本集的次节点与主节点延迟
db.printSlaveReplicationInfo()
# 移除原有副本集命令
use local
db.system.replset.remove({})
# 关闭 mongodb进程服务
use admin
db.shutdownServer()

四、注意事项

建议将副本集至少部署在3个可用区。

配置副本集成员,使用的是主机名而不是 ip,因为 ip 可能变动。

副本集包含奇数个投票成员。

错误问题

报错内容:

Failed global initialization: BadValue: replication.replSetName is not allowed when storage.indexBuildRetry is specified

storage 参数 indexBuildRetry 不能与 副本集共存,当开启 副本集的时候,就需要将indexBuildRetry 参数注释。官网链接

Changed in version 4.0: The setting storage.indexBuildRetry cannot be used in conjunction withreplication.replSetName.

MongoDB-副本集搭建与管理的更多相关文章

  1. MongoDB副本集搭建及备份恢复

    一.MongoDB副本集(repl set)介绍 早起版本使用master-slave,一主一从和MySQL类似,但slave在此架构中为只读,当主库宕机后,从库不能自动切换为主: 目前已经淘汰了ma ...

  2. mongodb副本集搭建过程中的问题和解决技巧

    在我以往的认知中,一个系统一旦正式上线,多半不会轻易的迁移服务器,尤其是那种涉及到多个关联应用,涉及到多台硬件服务器的系统,因为这种迁移将是牵一发而动全身的. 但是,却仍然有这种情况存在,就如我这几天 ...

  3. windows版本 MongoDB副本集搭建及开启身份验证

    ------------恢复内容开始------------ ------------恢复内容开始------------ MongoDB副本集搭建 我搭建的是一个主节点,两个副节点 构建目录结构如下 ...

  4. MongoDB 副本集搭建

    搭建mongodb副本集 [root@ mongodb]# cd /u02 [root@ u02]# mkdir -p mongodb/data_2777 [root@ u02]# mkdir -p ...

  5. Mongodb副本集搭建经验

    一.环境配置经验 1.一般安装的副本集的时候,主实例可以有数据库和用户:从实例不能.仲裁机不能有任何数据库包括用户 2.搭建副本集的时候Host使用外网IP,否则使用Mongodb VUE 1.6.9 ...

  6. MongoDB 副本集搭建 & 副本集扩容

    副本集的搭建 创建多实例目录 [root@redis03 ~]# mkdir /server/mongodb/2801{7,8,9}/{conf,logs,pid,data} -p 编辑多实例配置文件 ...

  7. mongodb副本集搭建

    1.创建目录 mkdir -p /data/r1  /data/r2  /data/r3 2.启动: bin/mongod --config ../mongod.conf --replSet r1 b ...

  8. 在centos7上搭建mongodb副本集

    1.安装副本集介绍 副本集(Replica Set)是一组MongoDB实例组成的集群,由一个主(Primary)服务器和多个备份(Secondary)服务器构成.通过Replication,将数据的 ...

  9. mongodb 4.0副本集搭建

    近期有同学问mongodb副本集难不难部署,我的回答是不难,很快,几分钟搞定,比mysql MHA简单的不止一点半点. 那么到底如何部署呢?请看下文. 1.  准备工作 1.1 下载软件 选择版本并下 ...

  10. mongo副本集搭建及服务器复用方案

    比较常见的mongodb副本集搭建是有:常规节点.数据副本.仲裁节点组成,也就是需要三台服务器组建.常规节点即数据的主存储节点,数据副本是主存储节点的从属节点,它定期去主节点获取更新日志来更新自己.仲 ...

随机推荐

  1. django by example 第四章 dashboard处html无法渲染问题

    描述: 实现django by example 代码时,第四章 dashboard处html无法渲染问题. 此时报错,NoReverseMatch at /account/login/, Error ...

  2. nginx的https代理http配置

    http { upstream https2http_proxy{ server 192.168.22.103:80; } server { listen 1443 ssl; server_name ...

  3. AX_Function

    formrun.owner().GetItemId() if (fr.name() == formstr(inventTransEditDimensions) || fr.name() == form ...

  4. ibatis (六) dynamic的用法

    view plain copy print? dynamic可以去除第一个prepend="and"中的字符(这里为and),从而可以帮助你实现一些很实用的功能.具体情况如下: 1 ...

  5. 服务器被minerd

    cd /opt chmod -x minerd 去/root/.ssh 目录下,清除authorized_keys,KHK75NEOiq 文件 在ssh的配置文件/etc/ssh/sshd_confi ...

  6. verilog 有符号数运算

    1)之前的笔记写过<补码探讨>,可知在FPGA综合成电路的时候最底层都是以补码的形式在运算,正数的补码就是本身,负数的补码要取反+1. (2)那么Verilog中编程的时候对编程人员来说, ...

  7. Oracle DBLINk的使用

    Oracle中自带了DBLink功能,它的作用是将多个oracle数据库逻辑上看成一个数据库,也就是说在一个数据库中可以操作另一个数据库中的对象,例如我们新建了一个数据database1,我们需要操作 ...

  8. 团队作业第五周(HCL盐酸队)

    一.Alpha版本测试报告 1.测试计划 测试项目 上下移动   左右移动   发射子弹   与敌方坦克进行攻击 2.测试过程 测试截图 错误记录(提交issues到码云团队项目) 3.测试找出的bu ...

  9. kaldi的TIMIT实例二

    ============================================================================ MonoPhone Training & ...

  10. 每日分享!canvas的使用~

    今天大概的说下canvas的使用~ canvas是H5新增的一个元素,可以用来在canvas上绘制一些图形! 如何使用canvas呢?     首先我们用canvas绘制一条直线!   <!DO ...