概述
复制主要存在是为了提供数据冗余和高可用性。我们通过在物理上隔离的服务器上保持该数据的多个副本或副本来保持数据的持久性。这就是复制:创建冗余数据以简化并保护数据可用性和持久性的过程。
复制允许您通过在服务器之间创建数据的多个副本来提高数据的可用性。如果服务器崩溃或发生服务中断或硬件故障,这特别有用。
如果您的数据只存在于单个数据库中,这些事件中的任何一个都会使访问数据变得不可能。但是,多亏了复制,即使数据库服务器发生故障,您的应用程序也可以保持在线,同时提供灾难恢复和备份选项。
MongoDB通过副本集实现复制。写入操作发送到主服务器(节点),然后将其应用到辅助服务器上,复制数据。
如果主服务器失败(通过崩溃或系统故障),其中一个辅助服务器接管并成为新的主节点,这通过选举完成。如果该服务器重新上线,一旦完全恢复,它就变为辅助服务器,帮助新的主节点。
首先,您需要在三个或更多节点上安装MongoDB。集群中的每个节点都需要能够通过标准端口(默认为27017)与其他节点通信。此外,每个副本集成员都需要有一个可以从其他节点解析的主机名。
建立虚拟专用网络。确保您的网络拓扑将单个站点内成员之间的所有流量路由到局域网。
配置访问控制,防止未知客户端连接到副本集。
配置网络和防火墙规则,仅允许在默认MongoDB端口上从您的部署内部允许传入和传出的数据包。请参阅IP绑定注意事项。
确保副本集的每个成员都可以通过可解析的DNS或主机名访问。
有关更多详细信息,请参阅:我们的文档中的生产注意事项和安全加固。
以下示例指定了副本集名称和IP绑定,通过--replSet
和--bind_ip
命令行选项实现。
mongod --auth --replSet "rs0" --bind_ip localhost,<hostname(s)|ip address(es)>
对于<hostname(s)|ip address(es)>
,指定远程客户端(包括副本集的其他成员)可以用来连接实例的主机名(们)和/或IP地址(们)。
从运行mongod的一个相同机器上,启动mongosh shell。若要连接到监听默认端口27017的localhost上的mongod,只需执行以下命令:
mongosh -u $USERNAME -p $PASSWORD
根据您如何安装MongoDB以及设置环境,您可能需要指定mongosh二进制的路径。
在mongosh shell中,在副本集成员0上运行full rs.initiate({...})
。此命令初始化副本集,且仅在第一个副本集成员上运行。在后续节点上,可以不带参数运行命令,即只需运行rs.initiate()
。
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" }
]
})
MongoDB使用默认副本集配置初始化副本集。
使用rs.conf()
显示副本集配置对象。
rs.conf()
副本集配置对象类似于以下内容:
{
"_id" : "rs0",
"version" : 1,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "mongodb0.example.net:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "mongodb1.example.net:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "mongodb2.example.net:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : -1,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("585ab9df685f726db2c6a840")
}
}
使用rs.status()
来识别副本集中的主节点。
复制延迟是在主服务器上的更新后,数据被复制到从服务器后的延迟。短暂的复制延迟是正常的,并且在选择读取最终一致性的从服务器数据的系统中应该考虑。复制延迟也可能防止从服务器在主节点掉线时承担主节点角色。
如果您想检查当前的复制延迟:
在一个连接到主节点的mongosh shell中,调用rs.printSlaveReplicationInfo()方法。
这返回每个成员的syncedTo
值,这显示了最后一条操作日志条目写入从服务器的确切时间。
复制延迟可能由几个原因引起,包括:
网络延迟:检查您的ping和traceroute以查看是否存在网络路由问题或数据包丢失。见:ping诊断文档,故障排除副本集。
磁盘吞吐量:有时从服务器无法像主服务器那样快速地将数据刷新到磁盘上。这常见于多租户系统,尤其是当系统通过IP网络访问磁盘设备时。系统级工具,如vmstat或iostat可以帮助您找到更多信息。见:生产笔记,mongostat。
并发性:主服务器上的长时间运行的操作可能会阻塞复制。设置您的写入关注点,以确保在复制无法跟上负载时,写入操作不会返回。或者,通过数据库分析器检查慢查询和长时间运行的操作。 见:写入关注点。
适当的写入关注点:如果主节点需要大量写入(由于大量加载操作或大量数据摄入),从节点可能无法跟上操作日志上的更改。考虑将写入关注点设置为“majority”,以确保大型操作被正确复制。
复制:主服务器节点将数据复制到从服务器节点上。这可以帮助增加数据的可用性,并作为备份,以防主服务器故障。
分片:使用分片键处理服务器间的横向扩展。这意味着不是整体复制数据,而是将数据的片段(或“分片”)复制到多个副本集。这些副本集协同工作以利用所有数据。
想象一下披萨。在复制的情况下,你会在每个服务器上制作一个完整的披萨的副本。在分片的情况下,你会将披萨片发送到几个不同的副本集。合并在一起,你可以访问整个披萨。
复制和分片可以协同工作,形成所谓的分片集群,其中每个分片都会依次进行复制,以保持相同的高可用性。
复制有几个好处。由于有多个活的数据副本,因此它增加了数据可用性和可靠性。
复制在硬件故障或服务器崩溃等事件中也非常有用。而不是遭受停机(甚至更糟糕的是,完全丢失数据),复制确保你的数据在多个服务器上安全地受到保护。如果你有分布式的分析团队,你可以有效地在商业智能项目中协作。
复制对主服务器的读写延迟没有实质性影响。在合理的情况下从副本集的辅助节点读取数据可以提高应用延迟,前提是你不介意向客户展示最终一致的数据。
而不是自己配置和管理一切,你始终可以使用MongoDB Atlas。它简化并自动化了你的副本集,使整个过程对你来说变得轻松。MongoDB Atlas还可以通过几个点击在全球范围内部署分片副本集,实现数据本地化、灾难恢复和多区域部署。