MongoDB中的副本集是一组维护相同数据集的mongod进程。副本集提供冗余和高可用性,是所有生产部署的基础。
冗余和数据可用性
复制提供冗余并提高数据可用性。对于不同数据库服务器上的多个数据副本,复制提供了一定程度的容错性,以防止单个数据库服务器的丢失。
在某些情况下,复制可以提供增加的读容量,因为客户机可以将读操作发送到不同的服务器。在不同的数据中心维护数据副本可以提高分布式应用程序的数据局部性和可用性。还可以为专用目的维护其他副本,如灾难恢复、报告或备份。
主机名 | IP地址 | 系统 | 角色 | 数据库版本 |
---|---|---|---|---|
mongodb-DB01 | 192.168.0.1 | Ubuntu 16.04.3 LTS | Primary | MongoDB server version: 4.2.2 |
mongodb-DB02 | 192.168.0.2 | Ubuntu 16.04.3 LTS | Secondary | MongoDB server version: 4.2.2 |
mongodb-DB03 | 192.168.0.3 | Ubuntu 16.04.3 LTS | Arbiter | MongoDB server version: 4.2.2 |
副本集是一组维护相同数据集的mongod实例。副本集包含多个数据承载节点和一个可选仲裁节点。在数据承载节点中,一个且仅有一个成员被认为是主节点,其他节点被认为是辅助节点。主节点接收所有写操作。一个复制集只能有一个主节点,这个主节点可以用{w: “majority”}写关系来确认写;虽然在某些情况下,另一个mongod的例子可能会暂时认为自己也是主要的。主节点在其操作日志中记录对其数据集的所有更改,即oplog。
从服务器复制主服务器的oplog,并将操作应用到它们的数据集,以便从服务器的数据集反映主服务器的数据集。如果主服务器不可用,一个合格的从服务器将举行一次选举来选举新主服务器
在某些情况下(例如您有一个主服务器和一个辅助服务器,但是成本限制禁止添加另一个辅助服务器),您可以选择将一个mongod实例添加到一个副本集中作为仲裁节点。仲裁节点参与选举,但不持有数据(即不提供数据冗余)。
Arbiter永远是Arbiter,Arbiter 节点只参与投票,不能被选为 Primary,并且不从 Primary 同步数据。而Primary可能退下来成为Secondary,而Secondary可能在选举期间成为Primary。
主节点(Primary)
接收所有的写请求,然后把修改同步到所有Secondary。一个Replica Set只能有一个Primary节点,当Primary挂掉后,其他Secondary或者Arbiter节点会重新选举出来一个主节点。
默认读请求也是发到Primary节点处理的,可以通过修改客户端连接配置以支持读取Secondary节点。
副本节点(Secondary)
与主节点保持同样的数据集。当主节点挂掉的时候,参与选主。
仲裁者(Arbiter)
不保有数据,不参与选主,只进行选主投票。使用Arbiter可以减轻数据存储的硬件需求,Arbiter几乎没什么大的硬件资源需求,但重要的一点是,在生产环境下它和其他数据节点不要部署在同一台机器上。
Priority0
Priority0节点的选举优先级为0,不会被选举为 Primary。
比如你跨机房 A、B 部署了一个复制集,并且想指定 Primary 必须在 A 机房,这时可以将 B 机房的复制集成员 Priority 设置为0,这样 Primary 就一定会是 A 机房的成员。
(注意:如果这样部署,最好将大多数节点部署在 A 机房,否则网络分区时可能无法选出 Primary。)
Vote0
Mongodb 3.0里,复制集成员最多50个,参与 Primary 选举投票的成员最多7个,其他成员(Vote0)的 vote 属性必须设置为0,即不参与投票。
Hidden
Hidden 节点不能被选为主(Priority 为0),并且对 Driver 不可见。
因 Hidden 节点不会接受 Driver 的请求,可使用 Hidden 节点做一些数据备份、离线计算的任务,不会影响复制集的服务。
Delayed
Delayed 节点必须是 Hidden 节点,并且其数据落后与 Primary 一段时间(可配置,比如1个小时)。
因 Delayed 节点的数据比 Primary 落后一段时间,当错误或者无效的数据写入 Primary 时,可通过 Delayed 节点的数据来恢复到之前的时间点。
从服务器复制主服务器的oplog并异步地将操作应用到它们的数据集。通过让从服务器的数据集重放主服务器的数据集,副本集可以在一个或多个成员失败的情况下继续运行。
复制延迟指的是将主写操作复制(即复制)到从写操作所花费的时间。一些小的延迟可能是可以接受的,但是随着复制延迟的增加,出现了一些严重的问题,包括在主服务器上构建缓存压力。
从MongoDB 4.2开始,管理员可以限制主应用其写操作的速度,目的是将大多数提交延迟保持在可配置的最大值flowControlTargetLagSeconds之下。
默认情况下,流控制是启用的。
请注意要进行流控制,复制集/分片集群必须具备:featureCompatibilityversion (FCV)为4.2,read concern majority为启用。也就是说,如果FCV不是4.2或read concern majority被禁用,启用流控制就没有效果。
启用流控制后,随着延迟越来越接近flowControlTargetLagSeconds,主节点上的写操作必须在获取写操作的锁之前获得票据。通过限制每秒发出的票据数量,流控制机制试图将延迟保持在目标之下。
当一个主节点与集群的其他成员的通信时间不超过配置的electionTimeoutMillis周期(默认为10秒)时,一个合格的辅助节点将调用一个选举来将自己指定为新主节点。该集群尝试完成一个新的初选的选举并恢复正常运行。
在选举完成之前,副本集无法处理写操作。如果将读操作配置为副本集的从服务器上运行时,当主服务器脱机,则副本集可以继续为读操作提供服务。
默认的副本集设置集群选择新主节点之前的中间时间通常不应该超过12秒。这包括将初选标记为不可用、调用并完成选举所需的时间。您可以通过修改设置来调整这个时间段。electionTimeoutMillis复制配置选项。网络延迟等因素可能会延长完成副本集选举所需的时间,从而影响您的集群在没有主节点的情况下运行的时间。这些因素取决于特定的集群架构。
将electionTimeoutMillis复制配置选项从默认10000(10秒)降低可以更快地检测主故障。但是,由于临时网络延迟等因素,集群可能会更频繁地调用选举,即使主节点在其他方面是健康的。这可能导致w: 1写操作的回滚增加。
应用程序连接逻辑应该包括对自动故障转移和后续选择的容错。
从MongoDB 3.6开始,MongoDB驱动程序可以检测到主写操作的丢失,并一次自动重试某些写操作,提供额外的内置自动故障转移和选举处理:默认情况下,MongoDB 4.2兼容的驱动程序支持可重试写
MongoDB 4.0和3.6兼容的驱动程序必须通过在连接字符串中包含retrywrite =true来显式地启用retrywrite。
默认情况下,客户端从主读取数据,客户端也可以指定一个读首选项来将读操作发送到从服务器上
对从服务器的异步复制意味着从服务器读取的数据可能返回不是实时的主服务器上数据状态的数据。
包含读操作的多文档事务优先使用主服务器读取。给定事务中的所有操作都必须路由到同一成员。
MongoDB驱动程序使用一个服务器选择算法来选择使用哪个副本集成员,或者当连接到多个mongos实例时,选择使用哪个mongos实例。
服务器选择在每个操作中发生一次。由 read 首选项 和 localThresholdMS 阈值设置控制。
在版本3.4中新增:MongoDB 3.4增加了maxStalenessSeconds read 首选项。
maxStalenessSeconds 指定了最大复制延迟,即“过时”,从服务器可能会受到影响,但仍然有执行读取操作。
maxStalenessSeconds read 首选项适用于从Secondary节点读取数据的应用程序,并且希望避免当Secondary节点在复制主服务器的写操作方面远远落后于主服务器时从Secondary读取数据。例如由于Secondary服务器与Primary服务器之间的网络中断,它可能会停止复制。在这种情况下客户端应该停止从Secondary节点读取数据,直到管理员解决停机问题并等Secondary节点跟上。
Read Preference | Selection Process |
---|---|
primary (Default) | 驱动程序选择主服务器 |
secondary | 驱动程序组装一个合格的Secondary成员列表。maxStalenessSeconds和 tag sets 可以进一步限制成员的资格。如果符合条件的成员列表不是空的,则驱动程序确定哪个符合条件的成员是“最近的”(即网络平均往返时间最低的成员),并通过添加这个“最近的”服务器的平均往返时间和localThresholdMS.来计算一个延迟窗口。驱动程序使用此延迟窗口将符合条件的成员列表缩减到该窗口中的成员。从这个位于延迟窗口内的符合条件的成员列表中,驱动程序随机选择一个符合条件的成员。 |
nearest | 驱动程序组装一个合格成员的列表(primary and secondaries)。maxStalenessSeconds和 tag sets 可以进一步限制成员的资格。如果资格的成员列表中不是空的,驱动程序决定哪些资格成员是“最近的”(即最低的成员平均网络往返时间)和计算延迟窗口通过添加“最近的”的平均往返时间服务器和localThresholdMS 。驱动程序使用此延迟窗口将符合条件的成员列表缩减到该窗口中的成员。从这个位于延迟窗口内的符合条件的成员列表中,驱动程序随机选择一个符合条件的成员。 |
primaryPreferred | 如果主节点可用,驱动程序选择主节点。否则,服务器选择将遵循read首选项辅助项的过程。 |
secondaryPreferred | 按照read首选项辅助服务器的选择过程,如果符合条件的辅助成员列表不是空的,驱动程序将选择符合条件的辅助成员。否则,如果列表为空,驱动程序选择主节点。 |
根据read concern,客户端可以看到在持久化之前写的结果数据。
不管写操作的write concern是什么,其他使用 “local” 或 "available"的 read concern 的客户端都可以在向发出的客户端确认写操作之前看到写操作的结果。
使用"local" 或 “available” 读的客户端可以读取数据,这些数据随后可能在复制集故障转移期间回滚。
对于多文档事务中的操作,当事务提交时,在事务中所做的所有数据更改都会被保存并在事务外部可见。也就是说,事务在回滚其他更改时不会提交某些更改。在事务提交之前,在事务中所做的数据更改在事务外部是不可见的。
然而,当一个事务写入多个分片时,并不是所有外部读操作都需要等待提交的事务的结果在整个分片中可见。例如,如果提交了一个事务,并且在分片a上可以看到写1,但是在分片B上还不能看到写2,那么外部的read at read关注点“local”可以在不看到写2的情况下读取写1的结果。
连接性
确保网络流量可以在集合的所有成员与网络中的所有客户端之间安全地传递。
考虑以下:
建立虚拟专用网。确保您的网络拓扑通过局域网路由单个站点内成员之间的所有流量。
配置访问控制以防止从未知客户端到副本集的连接。
配置网络和防火墙规则,以便仅在默认的MongoDB端口上并且仅在您的部署中允许传入和传出数据包。
确保可以通过可解析的DNS或主机名访问副本集的每个成员。您应该适当地配置DNS名称或设置系统/etc/hosts文件以反映此配置。
配置
在部署MongoDB之前,请创建MongoDB用来存储数据文件的目录。
mongod 存储在相关位置的配置文件中指定配置/etc/mongod.conf。
如果可能,请使用逻辑DNS主机名而不是IP地址,尤其是在配置副本集成员或分片群集成员时。逻辑DNS主机名的使用避免了由于IP地址更改而导致的配置更改。
在三个节点安装部署mongodb4.2.2,操作如下:
# Primary,Secondary,Arbiter 节点安装 mongodb4.2.2
root@mongodb-DB01:~# groupadd mongodb && useradd -r -m -g mongodb -s /bin/bash mongodb
root@mongodb-DB01:~# tar -zxvf mongodb-linux-x86_64-ubuntu1604-4.2.2.tgz
root@mongodb-DB01:~# cat mongod.conf
systemLog:
destination: file
path: "/data/mongodb/log/mongod.log" # 如果是 arbiter节点,日志可定义为 arbiter.log 以示区分
logAppend: true
storage:
dbPath: "/data/mongodb/data"
journal:
enabled: true
processManagement:
fork: true
net:
bindIp: localhost,192.168.0.1 # 根据 mongod 实例的具体IP地址来绑定
port: 27017
maxIncomingConnections:65536
security:
authorization: enabled
replication:
replSetName: "rs0"
enableMajorityReadConcern: true
root@mongodb-DB01:~# chmod 644 /etc/mongodb.conf
# 软件安装,这里安装二进制包
root@mongodb-DB01:~# mkdir -p /usr/local/mongodb
root@mongodb-DB01:~# cp -Rf ./tar/mongodb-linux-x86_64-ubuntu1604-4.2.2/* /usr/local/mongodb/
root@mongodb-DB01:~# chown -R mongodb:mongodb /usr/local/mongodb
# 主目录设置
root@mongodb-DB01:~# mkdir -p /data/mongodb/{data,log}
root@mongodb-DB01:~# chown -R mongodb:mongodb /data/mongodb
root@mongodb-DB01:~# chmod 755 -R /data/mongodb
# 环境变更设置
root@mongodb-DB01:~# echo "export PATH=\$PATH:/usr/local/mongodb/bin" >> /etc/profile
root@mongodb-DB01:~# source /etc/profile
# 启动mongodb进程: 禁用认证参数 --noauth
root@mongodb-DB01:~# su - mongodb -c "/usr/local/mongodb/bin/mongod --config /etc/mongod.conf --noauth 2>&1 >/dev/null &"
root@mongodb-DB01:~# ps -ef | grep mongod
在三个节点启动mongod实例,然后登录任意节点创建集群,并初始化数据库,这里启动的命令参数我们加了–noauth表示登录mongod实例不需要认证,可以创建管理员账号等操作,后续我们再启用认证。 接下来创建集群并初始化操作:
# 登录任意一台mongodb节点
root@mongodb-DB01:~# /usr/local/mongodb/bin/mongo --port 27017 --host localhost
> use admin
> switched to db admin
# 初始化副本集
> root@mongodb-DB01:~# rs.initiate( {
_id : "rs0",
members: [
{ _id: 0, host: "192.168.0.1:27017" },
{ _id: 1, host: "192.168.0.2:27017" },
{ _id: 2, host: "192.168.0.3:27017", "arbiterOnly" : true, "priority" : 0 }
]
})
# 查看副本集配置
root@mongodb-DB01:~# rs.conf()
{
"_id" : "rs0",
"version" : 1,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
{
"_id" : 0,
"host" : "192.168.0.1:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "192.168.0.2:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "192.168.0.3:27017",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 0,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
...... # 这里省略部分输出
}
# 查看副本集的状态
root@mongodb-DB01:~# rs.status()
{
"set" : "uat_rs",
...... # 这里省略部分输出
"members" : [
{
"_id" : 0,
"name" : "192.168.0.1:27017",
"ip" : "192.168.0.1",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY", # 主节点
......... # 这里省略部分输出
},
{
"_id" : 1,
"name" : "192.168.0.2:27017",
"ip" : "192.168.0.2",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY", # 辅助节点
......... # 这里省略部分输出
},
{
"_id" : 2,
"name" : "192.168.0.3:27017",
"ip" : "192.168.0.3",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER", # 仲裁节点
......... # 这里省略部分输出
}
],
...... # 这里省略部分输出
}
以上在Mongodb4.2.2版本下的副本集部署已完成,副本集提供了许多支持应用程序需求的选项。例如,可以在多个数据中心部署具有成员的副本集,或者通过调整成员来控制选举结果。一些成员的优先权。副本集还支持用于报告、灾难恢复或备份功能的专用成员。
以上是免认证方式部署了副本集,要部署启用了访问控制的副本集,请参阅使用密钥文件身份验证部署副本集
MongoDB更新副本集设置为密钥文件身份验证: https://blog.csdn.net/qq_33158376/article/details/106355253