在创纪录的时间内构建强大的 MongoDB 副本集(4 种方法)

已发表: 2023-03-11

MongoDB 是一个 NoSQL 数据库,它使用具有动态模式的类似 JSON 的文档。 使用数据库时,最好有一个应急计划,以防其中一台数据库服务器出现故障。 侧边栏,您可以通过为您的 WordPress 网站利用一个漂亮的管理工具来减少这种情况发生的可能性。

这就是拥有多个数据副本很有用的原因。 它还减少了读取延迟。 同时,它可以提高数据库的可扩展性和可用性。 这就是复制的用武之地。它被定义为跨多个数据库同步数据的做法。

在本文中,我们将深入探讨 MongoDB 复制的各个重要方面,例如其功能和机制等。

什么是 MongoDB 中的复制?

在 MongoDB 中,副本集执行复制。 这是一组通过复制维护相同数据集的服务器。 您甚至可以将 MongoDB 复制用作负载平衡的一部分。 在这里,您可以根据用例在所有实例之间分配写入和读取操作。

甜蜜的梦是由……数据保护组成的! 不要让数据丢失困扰您 - 了解如何使用 MongoDB 复制来保证您的信息安全️ 点击推文

什么是 MongoDB 副本集?

属于给定副本集的每个 MongoDB 实例都是成员。 每个副本集都需要有一个主要成员和至少一个次要成员。

主要成员是与副本集进行交易的主要访问点。 它也是唯一可以接受写操作的成员。 复制首先复制主要的 oplog(操作日志)。 接下来,它会在辅助节点各自的数据集上重复记录的更改。 因此,每个副本集一次只能有一个主要成员。 各种primaries接收写操作会造成数据冲突。

通常,应用程序只查询主要成员的写入和读取操作。 您可以将设置设计为从一个或多个次要成员读取。 异步数据传输可能导致辅助节点的读取服务于旧数据。 因此,这样的安排并不适合所有用例。

副本集特征

自动故障转移机制使 MongoDB 的副本集在竞争中脱颖而出。 在没有主节点的情况下,辅助节点之间的自动选举会选择一个新的主节点。

MongoDB 副本集与 MongoDB 集群

MongoDB 副本集将跨副本集节点创建同一数据集的多个副本。 副本集的主要目的是:

  • 提供内置备份解决方案
  • 提高数据可用性

MongoDB 集群是完全不同的球类游戏。 它通过分片键将数据分布在许多节点上。 这个过程会将数据分成许多块,称为分片。 接下来,它将每个分片复制到不同的节点。 集群旨在支持大型数据集和高吞吐量操作。 它通过水平扩展工作负载来实现。

用外行的话来说,这是副本集和集群之间的区别:

  • 集群分配工作负载。 它还在许多服务器上存储数据片段(分片)。
  • 副本集完全复制数据集。

MongoDB 允许您通过创建分片集群来组合这些功能。 在这里,您可以将每个分片复制到辅助服务器。 这允许分片提供高冗余和数据可用性。

维护和设置副本集在技术上可能既费力又耗时。 并找到合适的托管服务? 那是另一个令人头疼的问题。 有这么多选择,很容易浪费时间进行研究,而不是建立您的业务。

让我向您简要介绍一个工具,该工具可以完成所有这一切以及更多工作,以便您可以回过头来用您的服务/产品来粉碎它。

Kinsta 的应用程序托管解决方案受到超过 55,000 名开发人员的信任,您只需 3 个简单的步骤即可启动并运行它。 如果这听起来好得令人难以置信,那么这里有一些使用 Kinsta 的更多好处:

  • 通过 Kinsta 的内部连接享受更好的性能:忘记与共享数据库的斗争。 切换到具有没有查询计数或行计数限制的内部连接的专用数据库。 Kinsta 更快、更安全,并且不会向您收取内部带宽/流量费用。
  • 为开发人员量身定制的功能集:在支持 Gmail、YouTube 和 Google 搜索的强大平台上扩展您的应用程序。 放心,你在这里是最安全的。
  • 通过您选择的数据中心享受无与伦比的速度:选择最适合您和您的客户的区域。 Kinsta 的275 多个PoP 有超过 25 个数据中心可供选择,可确保您网站的最高速度和全球影响力。

立即免费试用 Kinsta 的应用程序托管解决方案!

复制在 MongoDB 中是如何工作的?

在 MongoDB 中,您将写入器操作发送到主服务器(节点)。 主要分配跨辅助服务器的操作,复制数据。

这是复制在 MongoDB 中如何工作的流程图,用于 3 个节点(1 个主节点,2 个辅助节点)
MongoDB复制过程图解(图片来源:MongoDB)

三种类型的 MongoDB 节点

在三种类型的 MongoDB 节点中,有两种以前出现过:主节点和辅助节点。 在复制过程中派上用场的第三种 MongoDB 节点是仲裁器。 仲裁节点没有数据集的副本,不能成为主节点。 话虽如此,仲裁者确实参与了初选的选举。

我们之前提到过当主节点宕机时会发生什么,但是如果从节点挂掉了怎么办? 在那种情况下,主节点变为辅助节点并且数据库变得不可访问。

会员选举

选举可以在以下情况下发生:

  • 初始化副本集
  • 失去与主节点的连接(可以通过心跳检测到)
  • 使用rs.reconfigstepDown方法维护副本集
  • 将新节点添加到现有副本集

一个副本集最多可以拥有 50 个成员,但只有 7 个或更少的成员可以在任何选举中投票。

集群选举新主节点之前的平均时间不应超过 12 秒。 选举算法将尝试让具有最高优先级的次要可用。 同时,优先级值为0的成员不能成为初选成员,不参与选举。

这是一张图,描绘了次节点在选举后成为 MongoDB 中的主要节点。
从节点成为主节点(图片来源:Medium)

写关注

为了持久性,写操作有一个框架来复制指定数量的节点中的数据。 您甚至可以通过此向客户提供反馈。 这个框架也被称为“写关注”。 它具有数据承载成员,需要在操作成功返回之前确认写入问题。 通常,副本集的值为 1 作为写入关注点。 因此,只有主节点应该在返回写入关注确认之前确认写入。

您甚至可以增加确认写入操作所需的成员数量。 您可以拥有的成员数量没有上限。 但是,如果数字很高,则需要处理高延迟。 这是因为客户端需要等待所有成员的确认。 此外,您可以设置“多数”的写入关注。这将在收到确认后计算超过一半的成员。

阅读偏好

对于读取操作,您可以提及描述数据库如何将查询定向到副本集成员的读取首选项。 通常,主节点接收读取操作,但客户端可以提及读取偏好​​以将读取操作发送到辅助节点。 以下是阅读首选项的选项:

  • primaryPreferred :通常,读取操作来自主节点,但如果这不可用,则从辅助节点提取数据。
  • primary :所有读操作都来自主节点。
  • secondary :所有读操作都由从节点执行。
  • nearest :在这里,读取请求被路由到最近的可达节点,可以通过运行ping命令检测到。 读取操作的结果可以来自副本集的任何成员,无论它是主要的还是次要的。
  • secondaryPreferred :这里大部分的读操作都来自secondary节点,但是如果没有secondary节点,则从primary节点取数据。

复制集数据同步

为了维护共享数据集的最新副本,副本集的次要成员从其他成员复制或同步数据。

MongoDB 利用两种形式的数据同步。 初始同步以使用完整数据集填充新成员。 复制以执行对完整数据集的持续更改。

初始同步

初始同步时,从节点运行init sync命令将主节点的所有数据同步到另一个包含最新数据的从节点。 因此,辅助节点始终利用tailable cursor功能来查询主节点的 local.oplog.rs 集合中的最新 oplog 条目,并在这些 oplog 条目中应用这些操作。

从 MongoDB 5.2 开始,初始同步可以是基于文件副本的或逻辑的。

逻辑同步

当您执行逻辑同步时,MongoDB:

  1. 在为每个集合复制文档时开发所有集合索引。
  2. 复制除本地数据库之外的所有数据库。 mongod扫描所有源数据库中的每个集合,并将所有数据插入到这些集合的副本中。
  3. 对数据集执行所有更改。 通过利用来自源的 oplog, mongod升级其数据集以描述副本集的当前状态。
  4. 在数据复制过程中提取新添加的 oplog 记录。 确保目标成员在本地数据库中有足够的磁盘空间,以便在此数据复制阶段期间暂时存储这些 oplog 记录。

初始同步完成后,成员从STARTUP2过渡到SECONDARY

基于文件副本的初始同步

马上,您只能在使用 MongoDB Enterprise 时执行此操作。 此过程通过复制和移动文件系统上的文件来运行初始同步。 在某些情况下,此同步方法可能比逻辑初始同步更快。 请记住,如果您在没有查询谓词的情况下运行 count() 方法,基于文件副本的初始同步可能会导致计数不准确。

但是,这种方法也有其局限性:

  • 在基于文件副本的初始同步期间,您无法写入正在同步的成员的本地数据库。 您也不能对同步到的成员或同步自的成员运行备份。
  • 在利用加密存储引擎时,MongoDB 使用源密钥来加密目标。
  • 您一次只能从一个给定的成员运行初始同步。

复制

次要成员在初始同步后一致地复制数据。 次要成员将从源同步中复制操作日志,并在异步过程中执行这些操作。

辅助节点能够根据 ping 时间和其他成员复制状态的变化,根据需要自动修改来自源的同步。

流复制

从 MongoDB 4.4 开始,来自源的同步将连续的 oplog 条目流发送到它们的同步辅助节点。 流式复制减少了高负载和高延迟网络中的复制滞后。 它还可以:

  • 降低由于主要故障转移而丢失w:1写入操作的风险。
  • 减少从辅助节点读取的陈旧性。
  • 使用w:“majority”w:>1减少写操作的延迟。 简而言之,任何需要等待复制的写关注点。
多线程复制

MongoDB曾经通过多线程批量写入操作来提高并发性。 MongoDB 按文档 ID 对批次进行分组,同时使用不同的线程应用每组操作。

MongoDB 始终以其原始写入顺序对给定文档执行写入操作。 这在 MongoDB 4.0 中发生了变化。

从 MongoDB 4.0 开始,如果读取发生在应用复制批处理的辅助节点上,则针对辅助节点并配置了“majority”“local”读取关注级别的读取操作现在将从数据的 WiredTiger 快照中读取。 从快照读取保证了数据的一致视图,并让读取与正在进行的复制同时发生而无需锁定。

因此,需要这些读取关注级别的辅助读取不再需要等待应用复制批次,并且可以在接收到它们时进行处理。

如何创建 MongoDB 副本集

如前所述,MongoDB 通过副本集处理复制。 在接下来的几节中,我们将重点介绍一些可用于为您的用例创建副本集的方法。

方法一:在 Ubuntu 上创建一个新的 MongoDB 副本集

在开始之前,您需要确保至少有三台运行 Ubuntu 20.04 的服务器,每台服务器上都安装了 MongoDB。

要设置副本集,必须提供一个地址,该地址中的每个副本集成员都可以访问该地址。 在这种情况下,我们在集合中保留三个成员。 虽然我们可以使用 IP 地址,但不建议这样做,因为地址可能会意外更改。 更好的替代方法是在配置副本集时使用逻辑 DNS 主机名。

我们可以通过为每个复制成员配置子域来做到这一点。 虽然这对于生产环境来说可能是理想的,但本节将概述如何通过编辑每个服务器各自的主机文件来配置 DNS 解析。 该文件允许我们将可读的主机名分配给数字 IP 地址。 因此,如果您的 IP 地址在任何情况下发生变化,您所要做的就是更新三台服务器上的主机文件,而不是从头开始重新配置副本集!

大多数情况下, hosts存储在/etc/目录中。 对三个服务器中的每一个重复以下命令:

 sudo nano /etc/hosts

在上面的命令中,我们使用 nano 作为我们的文本编辑器,但是,您可以使用您喜欢的任何文本编辑器。 在配置本地主机的前几行之后,为副本集的每个成员添加一个条目。 这些条目采用 IP 地址后跟您选择的人类可读名称的形式。 虽然您可以随心所欲地命名它们,但一定要具有描述性,这样您才能区分每个成员。 对于本教程,我们将使用以下主机名:

  • mongo0.replset.member
  • mongo1.replset.member
  • mongo2.replset.member

使用这些主机名,您的 /etc/hosts 文件将类似于以下突出显示的行:

这是包含主机名和 IP 地址的 /etc/hosts 文件的快照。
主机名说明

保存并关闭文件。

为副本集配置好DNS解析后,我们需要更新防火墙规则,让它们可以互相通信。 在 mongo0 上运行以下ufw命令以提供 mongo1 对 mongo0 上端口 27017 的访问:

 sudo ufw allow from mongo1_server_ip to any port 27017

代替mongo1_server_ip参数,输入您的 mongo1 服务器的实际 IP 地址。 此外,如果您已将此服务器上的 Mongo 实例更新为使用非默认端口,请务必更改 27017 以反映您的 MongoDB 实例正在使用的端口。

现在添加另一个防火墙规则以授予 mongo2 对同一端口的访问权限:

 sudo ufw allow from mongo2_server_ip to any port 27017

代替mongo2_server_ip参数,输入您的 mongo2 服务器的实际 IP 地址。 然后,更新其他两台服务器的防火墙规则。 在 mongo1 服务器上运行以下命令,确保更改 IP 地址代替 server_ip 参数以分别反映 mongo0 和 mongo2 的 IP 地址:

 sudo ufw allow from mongo0_server_ip to any port 27017
 sudo ufw allow from mongo2_server_ip to any port 27017

最后,在 mongo2 上运行这两个命令。 同样,请确保为每台服务器输入正确的 IP 地址:

 sudo ufw allow from mongo0_server_ip to any port 27017
 sudo ufw allow from mongo1_server_ip to any port 27017

下一步是更新每个 MongoDB 实例的配置文件以允许外部连接。 为此,您需要修改每个服务器中的配置文件以反映 IP 地址并指示副本集。 虽然您可以使用任何首选的文本编辑器,但我们再次使用 nano 文本编辑器。 让我们在每个 mongod.conf 文件中进行以下修改。

在 mongo0 上:

 # network interfaces net: port: 27017 bindIp: 127.0.0.1,mongo0.replset.member# replica set replication: replSetName: "rs0"

在 mongo1 上:

 # network interfaces net: port: 27017 bindIp: 127.0.0.1,mongo1.replset.member replication: replSetName: "rs0"

在 mongo2 上:

 # network interfaces net: port: 27017 bindIp: 127.0.0.1,mongo2.replset.member replication: replSetName: "rs0"
 sudo systemctl restart mongod

这样,您就为每个服务器的 MongoDB 实例启用了复制。

您现在可以使用rs.initiate()方法初始化副本集。 该方法只需要在副本集中的单个 MongoDB 实例上执行。 确保副本集名称和成员与您之前在每个配置文件中所做的配置相匹配。

 rs.initiate( { _id: "rs0", members: [ { _id: 0, host: "mongo0.replset.member" }, { _id: 1, host: "mongo1.replset.member" }, { _id: 2, host: "mongo2.replset.member" } ] })

如果该方法在输出中返回“ok”: 1,则表示副本集已正确启动。 下面是输出应该是什么样子的示例:

 { "ok": 1, "$clusterTime": { "clusterTime": Timestamp(1612389071, 1), "signature": { "hash": BinData(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId": NumberLong(0) } }, "operationTime": Timestamp(1612389071, 1) }

关闭 MongoDB 服务器

您可以使用db.shutdownServer()方法关闭 MongoDB 服务器。 下面是相同的语法。 forcetimeoutsecs都是可选参数。

 db.shutdownServer({ force: <boolean>, timeoutSecs: <int> })

如果 mongod 副本集成员运行某些操作作为索引构建,则此方法可能会失败。 要中断操作并强制关闭成员,您可以输入布尔参数force为 true。

使用 –replSet 重启 MongoDB

要重置配置,请确保副本集中的每个节点都已停止。 然后删除每个节点的本地数据库。 使用–replSet标志再次启动它,并仅在副本集的一个 mongod 实例上运行rs.initiate()

 mongod --replSet "rs0"

rs.initiate()可以带一个可选的副本集配置文件,即:

  • Replication.replSetName—replSet选项用于在_id字段中指定副本集名称。
  • 成员数组,其中包含每个副本集成员的一个文档。

rs.initiate()方法触发选举并选出其中一个成员作为主要成员。

将成员添加到副本集

要将成员添加到集合中,请在各种机器上启动 mongod 实例。 接下来,启动一个 mongo 客户端并使用rs.add()命令。

rs.add()命令具有以下基本语法:

 rs.add(HOST_NAME:PORT)

例如,

假设 mongo1 是您的 mongod 实例,它正在侦听端口 27017。使用 Mongo 客户端命令rs.add()将此实例添加到副本集。

 rs.add("mongo1:27017")

只有连接到主节点后,才能将 mongod 实例添加到副本集。 要验证您是否已连接到主服务器,请使用命令db.isMaster()

删除用户

要删除成员,我们可以使用rs.remove()

为此,首先,使用我们上面讨论的db.shutdownServer()方法关闭您希望删除的 mongod 实例。

接下来,连接到副本集的当前主节点。 要确定当前主节点,请在连接到副本集的任何成员时使用db.hello() 。 确定主节点后,运行以下任一命令:

 rs.remove("mongodb-node-04:27017") rs.remove("mongodb-node-04")
这是执行 rs.remove() 命令后的输出快照。
上图显示节点已成功从副本集中删除。 (图片来源:Bmc)

如果副本集需要选举一个新的主节点,MongoDB 可能会短暂地断开 shell。 在这种情况下,它会再次自动重新连接。 此外,即使命令成功,它也可能显示DBClientCursor::init call() failed 错误。

方式二:配置MongoDB副本集部署测试

通常,您可以设置副本集以在启用或禁用 RBAC 的情况下进行测试。 在这种方法中,我们将设置副本集并禁用访问控制,以便将其部署在测试环境中。

首先,使用以下命令为属于副本集的所有实例创建目录:

 mkdir -p /srv/mongodb/replicaset0-0 /srv/mongodb/replicaset0-1 /srv/mongodb/replicaset0-2

此命令将为三个 MongoDB 实例 replicaset0-0、replicaset0-1 和 replicaset0-2 创建目录。 现在,使用以下一组命令为它们中的每一个启动 MongoDB 实例:

对于服务器 1:

 mongod --replSet replicaset --port 27017 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0 --oplogSize 128

对于服务器 2:

 mongod --replSet replicaset --port 27018 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0 --oplogSize 128

对于服务器 3:

 mongod --replSet replicaset --port 27019 --bind_ip localhost,<hostname(s)|ip address(es)> --dbpath /srv/mongodb/replicaset0-0 --oplogSize 128

–oplogSize参数用于防止机器在测试阶段过载。 它有助于减少每个磁盘占用的磁盘空间量。

现在,使用下面的端口号连接到使用 Mongo shell 的实例之一。

 mongo --port 27017

我们可以使用rs.initiate()命令启动复制过程。 您必须将hostname参数替换为您的系统名称。

 rs conf = { _id: "replicaset0", members: [ { _id: 0, host: "<hostname>:27017}, { _id: 1, host: "<hostname>:27018"}, { _id: 2, host: "<hostname>:27019"} ] }

您现在可以将配置对象文件作为启动命令的参数传递,并按如下方式使用它:

 rs.initiate(rsconf)

你有它! 您已成功创建用于开发和测试目的的 MongoDB 副本集。

方法 3:将独立实例转换为 MongoDB 副本集

MongoDB 允许其用户将其独立实例转换为副本集。 虽然独立实例主要用于测试和开发阶段,但副本集是生产环境的一部分。

首先,让我们使用以下命令关闭我们的 mongod 实例:

 db.adminCommand({"shutdown":"1"})

通过在命令中使用–repelSet参数来重新启动您的实例,以指定您将要使用的副本集:

 mongod --port 27017 – dbpath /var/lib/mongodb --replSet replicaSet1 --bind_ip localhost,<hostname(s)|ip address(es)>

您必须在命令中指定服务器名称和唯一地址。

将 shell 与您的 MongoDB 实例连接起来,并使用 initiate 命令启动复制过程并成功地将实例转换为副本集。 您可以使用以下命令执行所有基本操作,例如添加或删除实例:

 rs.add(“<host_name:port>”)
 rs.remove(“host-name”)

此外,您可以使用rs.status()rs.conf()命令检查 MongoDB 副本集的状态。

方法 4:MongoDB Atlas——更简单的替代方法

复制和分片可以一起工作以形成称为分片集群的东西。 虽然设置和配置虽然简单但可能非常耗时,但 MongoDB Atlas 是比前面提到的方法更好的替代方法。

它使您的副本集自动化,使该过程易于实施。 只需点击几下,即可部署全局分片副本集,实现容灾、易管理、数据本地化、多区域部署。

在 MongoDB Atlas 中,我们需要创建集群——它们可以是副本集,也可以是分片集群。 对于一个特定的项目,其他地区的一个集群中的节点数量限制为总共 40 个。

这不包括免费或共享集群以及相互通信的 Google 云区域。 任意两个区域之间的节点总数必须满足此约束。 例如,如果有一个项目:

  • 区域 A 有 15 个节点。
  • 区域 B 有 25 个节点
  • 区域 C 有 10 个节点

我们只能再分配 5 个节点到区域 C,因为,

  1. A区+B区=40; 满足 40 作为允许的最大节点数的约束。
  2. 区域B+区域C = 25+10+5(分配给C的额外节点)= 40; 满足 40 作为允许的最大节点数的约束。
  3. 区域A+区域C=15+10+5(额外分配给C的节点)=30; 满足 40 作为允许的最大节点数的约束。

如果我们再分配 10 个节点到区域 C,使区域 C 有 20 个节点,那么区域 B + 区域 C = 45 个节点。 这会超出给定的限制,因此您可能无法创建多区域集群。

当您创建集群时,Atlas 会在项目中为云提供商创建一个网络容器(如果之前不存在的话)。 要在 MongoDB Atlas 中创建副本集集群,请在 Atlas CLI 中运行以下命令:

 atlas clusters create [name] [options]

确保提供一个描述性的集群名称,因为它在集群创建后无法更改。 参数可以包含 ASCII 字母、数字和连字符。

根据您的要求,有多个选项可用于在 MongoDB 中创建集群。 例如,如果您想要为您的集群进行连续的云备份,请将--backup设置为 true。

处理复制延迟

复制延迟可能非常令人不快。 这是主节点上的操作与该操作从 oplog 应用到辅助节点之间的延迟。 如果您的业务处理大型数据集,则预计会在某个阈值内出现延迟。 但是,有时外部因素也可能导致延迟增加。 要从最新的复制中获益,请确保:

  1. 您在稳定且足够的带宽中路由网络流量。 网络延迟在影响您的复制方面起着巨大的作用,如果网络不足以满足复制过程的需要,则在复制整个副本集中的数据时会出现延迟。
  2. 您有足够的磁盘吞吐量。 如果辅助设备上的文件系统和磁盘设备无法像主设备一样快速地将数据刷新到磁盘,那么辅助设备将难以跟上。 因此,辅助节点处理写查询的速度比主节点慢。 这是大多数多租户系统中的常见问题,包括虚拟化实例和大规模部署。
  3. 您在一段时间后请求写确认写入关注,以便为辅助节点提供赶上主节点的机会,尤其是当您要执行需要对主节点进行大量写入的批量加载操作或数据摄取时。 辅助节点将无法足够快地读取操作日志以跟上更改; 特别是对于未确认的写入问题。
  4. 您确定正在运行的后台任务。 某些任务(如 cron 作业、服务器更新和安全检查)可能会对网络或磁盘使用产生意外影响,从而导致复制过程延迟。

如果您不确定您的应用程序中是否存在复制滞后,请不要担心——下一节将讨论故障排除策略!

MongoDB 副本集故障排除

您已经成功设置了副本集,但您注意到您的数据在服务器之间不一致。 这对于大型企业来说是非常令人担忧的,但是,通过快速的故障排除方法,您可能会找到原因甚至纠正问题! 下面给出了一些可能派上用场的副本集部署故障排除的常见策略:

检查副本状态

我们可以通过在连接到副本集主节点的 mongosh 会话中运行以下命令来检查副本集的当前状态和每个成员的状态。

 rs.status()

检查复制延迟

如前所述,复制滞后可能是一个严重的问题,因为它使“滞后”成员没有资格快速成为主要成员,并增加了分布式读取操作不一致的可能性。 我们可以使用以下命令检查复制日志的当前长度:

 rs.printSecondaryReplicationInfo()

这将返回syncedTo值,该值是每个成员的最后一个 oplog 条目写入辅助节点的时间。 这是一个演示相同内容的示例:

 source: m1.example.net:27017 syncedTo: Mon Oct 10 2022 10:19:35 GMT-0400 (EDT) 0 secs (0 hrs) behind the primary source: m2.example.net:27017 syncedTo: Mon Oct 10 2022 10:19:35 GMT-0400 (EDT) 0 secs (0 hrs) behind the primary

当主要成员的不活动时间大于members[n].secondaryDelaySecs值时,延迟成员可能会显示为落后主要成员 0 秒。

测试所有成员之间的连接

副本集的每个成员都必须能够与其他每个成员连接。 始终确保验证两个方向的连接。 大多数情况下,防火墙配置或网络拓扑会阻止正常和所需的连接,从而阻止复制。

例如,假设 mongod 实例绑定到本地主机和与 IP 地址 198.41.110.1 关联的主机名“ExampleHostname”:

 mongod --bind_ip localhost, ExampleHostname

要连接到此实例,远程客户端必须指定主机名或 IP 地址:

 mongosh --host ExampleHostname mongosh --host 198.41.110.1

如果一个副本集由 m1、m2 和 m3 三个成员组成,使用默认端口 27017,您应该按如下方式测试连接:

在 m1 上:

 mongosh --host m2 --port 27017 mongosh --host m3 --port 27017

在 m2 上:

 mongosh --host m1 --port 27017 mongosh --host m3 --port 27017

在 m3 上:

 mongosh --host m1 --port 27017 mongosh --host m2 --port 27017

如果任何方向的任何连接失败,您必须检查您的防火墙配置并重新配置它以允许连接。

使用密钥文件身份验证确保安全通信

默认情况下,MongoDB 中的密钥文件身份验证依赖于加盐挑战响应身份验证机制 (SCRAM)。 为此,MongoDB 必须读取并验证用户提供的凭据,其中包括特定 MongoDB 实例知道的用户名、密码和身份验证数据库的组合。 这是用于对连接到数据库时提供密码的用户进行身份验证的确切机制。

当您在 MongoDB 中启用身份验证时,将自动为副本集启用基于角色的访问控制 (RBAC),并且用户被授予一个或多个角色,这些角色决定了他们对数据库资源的访问权限。 当启用 RBAC 时,这意味着只有经过身份验证且具有适当权限的有效 Mongo 用户才能访问系统上的资源。

密钥文件就像集群中每个成员的共享密码。 这使得副本集中的每个 mongod 实例都可以使用密钥文件的内容作为共享密码来验证部署中的其他成员。

只有具有正确密钥文件的 mongod 实例才能加入副本集。 密钥的长度必须介于 6 到 1024 个字符之间,并且只能包含 base64 集中的字符。 请注意,MongoDB 在读取键时会去除空白字符。

您可以使用多种方法生成密钥文件。 在本教程中,我们使用openssl生成一个由 1024 个随机字符组成的复杂字符串,用作共享密码。 然后它使用chmod更改文件权限以仅向文件所有者提供读取权限。 Avoid storing the keyfile on storage mediums that can be easily disconnected from the hardware hosting the mongod instances, such as a USB drive or a network-attached storage device. Below is the command to generate a keyfile:

 openssl rand -base64 756 > <path-to-keyfile> chmod 400 <path-to-keyfile>

Next, copy the keyfile to each replica set member . Make sure that the user running the mongod instances is the owner of the file and can access the keyfile. After you've done the above, shut down all members of the replica set starting with the secondaries. Once all the secondaries are offline, you may go ahead and shut down the primary. It's essential to follow this order so as to prevent potential rollbacks. Now shut down the mongod instance by running the following command:

 use admin db.shutdownServer()

After the command is run, all members of the replica set will be offline. Now, restart each member of the replica set with access control enabled .

For each member of the replica set, start the mongod instance with either the security.keyFile configuration file setting or the --keyFile command-line option.

If you're using a configuration file, set

  • security.keyFile to the keyfile's path, and
  • replication.replSetName to the replica set name.
 security: keyFile: <path-to-keyfile> replication: replSetName: <replicaSetName> net: bindIp: localhost,<hostname(s)|ip address(es)>

Start the mongod instance using the configuration file:

 mongod --config <path-to-config-file>

If you're using the command line options, start the mongod instance with the following options:

  • –keyFile set to the keyfile's path, and
  • –replSet set to the replica set name.
 mongod --keyFile <path-to-keyfile> --replSet <replicaSetName> --bind_ip localhost,<hostname(s)|ip address(es)>

You can include additional options as required for your configuration. For instance, if you wish remote clients to connect to your deployment or your deployment members are run on different hosts, specify the –bind_ip. For more information, see Localhost Binding Compatibility Changes.

Next, connect to a member of the replica set over the localhost interface . You must run mongosh on the same physical machine as the mongod instance. This interface is only available when no users have been created for the deployment and automatically closes after the creation of the first user.

We then initiate the replica set. From mongosh, run the rs.initiate() method:

 rs.initiate( { _id: "myReplSet", members: [ { _id: 0, host: "mongo1:27017" }, { _id: 1, host: "mongo2:27017" }, { _id: 2, host: "mongo3:27017" } ] } )

As discussed before, this method elects one of the members to be the primary member of the replica set. To locate the primary member, use rs.status() . Connect to the primary before continuing.

Now, create the user administrator . You can add a user using the db.createUser() method. Make sure that the user should have at least the userAdminAnyDatabase role on the admin database.

The following example creates the user 'batman' with the userAdminAnyDatabase role on the admin database:

 admin = db.getSiblingDB("admin") admin.createUser( { user: "batman", pwd: passwordPrompt(), // or cleartext password roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] } )

Enter the password that was created earlier when prompted.

Next, you must authenticate as the user administrator . To do so, use db.auth() to authenticate. 例如:

db.getSiblingDB(“admin”).auth(“batman”, passwordPrompt()) // or cleartext password

Alternatively, you can connect a new mongosh instance to the primary replica set member using the -u <username> , -p <password> , and the --authenticationDatabase parameters.

 mongosh -u "batman" -p --authenticationDatabase "admin"

Even if you do not specify the password in the -p command-line field, mongosh prompts for the password.

Lastly, create the cluster administrator . The clusterAdmin role grants access to replication operations, such as configuring the replica set.

Let's create a cluster administrator user and assign the clusterAdmin role in the admin database:

 db.getSiblingDB("admin").createUser( { "user": "robin", "pwd": passwordPrompt(), // or cleartext password roles: [ { "role" : "clusterAdmin", "db" : "admin" } ] } )

Enter the password when prompted.

If you wish to, you may create additional users to allow clients and interact with the replica set.

瞧! You have successfully enabled keyfile authentication!

Keep your data in sync across multiple databases with MongoDB replication! Learn how to create a replica set and troubleshoot like a pro right here Click to Tweet

概括

Replication has been an essential requirement when it comes to databases, especially as more businesses scale up. It widely improves the performance, data security, and availability of the system. Speaking of performance, it is pivotal for your WordPress database to monitor performance issues and rectify them in the nick of time, for instance, with Kinsta APM, Jetpack, and Freshping to name a few.

Replication helps ensure data protection across multiple servers and prevents your servers from suffering from heavy downtime(or even worse – losing your data entirely). In this article, we covered the creation of a replica set and some troubleshooting tips along with the importance of replication. Do you use MongoDB replication for your business and has it proven to be useful to you? 在下面的评论部分让我们知道!