对副本集进行故障排除
在本页面
本节介绍了对replica set部署进行故障排除的常见策略。
检查副本集状态
若要显示副本集的当前状态和每个成员的当前状态,请在连接到副本集primary的mongo shell 中运行rs.status()方法。有关rs.status()显示的信息的描述,请参见replSetGetStatus。
Note
rs.status()方法是运行replSetGetStatus数据库命令的包装器。
检查复制延迟
复制滞后是对primary的操作与该操作从oplog到secondary的应用之间的延迟。复制滞后可能是一个重要问题,并且可能严重影响 MongoDB replica set的部署。过多的复制滞后使“滞后”成员不具备迅速成为主要成员的资格,并增加了分布式读取操作不一致的可能性。
要检查当前复制滞后时间:
- 在连接到主要数据库的mongo shell 中,调用rs.printSlaveReplicationInfo()方法。
返回每个成员的syncedTo
值,该值显示将最后一个 oplog 条目写入辅助节点的时间,如以下示例所示:
source: m1.example.net:27017
syncedTo: Thu Apr 10 2014 10:27:47 GMT-0400 (EDT)
0 secs (0 hrs) behind the primary
source: m2.example.net:27017
syncedTo: Thu Apr 10 2014 10:27:47 GMT-0400 (EDT)
0 secs (0 hrs) behind the primary
当主要对象的闲置时间大于members[n].slaveDelay值时,delayed member可能显示为比主要对象晚0
秒。
Note
rs.status()方法是replSetGetStatus数据库命令的包装。
- 通过检查Cloud Manager和Ops Manager中可用的“复制滞后”图中的非零或增加 oplog 时间值来监视复制速率。
复制延迟的可能原因包括:
- Network Latency
检查您的集合成员之间的网络路由,以确保没有数据包丢失或网络路由问题。
使用ping
等工具测试集合成员之间的 await 时间,使用traceroute
等工具公开数据包网络端点的路由。
- Disk Throughput
如果辅助节点上的文件系统和磁盘设备无法像主节点一样快地将数据刷新到磁盘,则辅助节点将很难保持状态。与磁盘相关的问题在多租户系统中非常普遍,包括虚拟化实例,并且如果系统通过 IP 网络访问磁盘设备(与 Amazon EBS 系统一样),则可能是暂时的。
使用系统级工具评估磁盘状态,包括iostat
或vmstat
。
- Concurrency
在某些情况下,主服务器上长时间运行的操作可能会阻止辅助服务器上的复制。为了获得最佳结果,请将write concern配置为要求确认复制到辅助数据库。如果复制无法跟上写负载,这可以防止写操作返回。
您还可以使用database profiler查看是否存在与滞后发生率相对应的慢查询或长时间运行的操作。
- 适当的写入问题
如果要执行大量数据提取或批量加载操作,这需要对主数据库进行大量写入,尤其是使用unacknowledged write concern
,则辅助数据库将无法足够快地读取操作日志以跟上更改。
为避免这种情况,请每隔 100、1,000 或另一个间隔请求写确认写关注,以使次要计算机有机会赶上主要计算机。
有关更多信息,请参见:
Oplog 条目的应用缓慢
对于从版本 3.6.11 开始的 MongoDB 3.6 部署,副本集的辅助成员现在为记录操作日志条目,所花费的时间超过了慢操作阈值。这些慢速 oplog 消息将在文本applied op: <oplog entry> took <num>ms
下的REPL组件下的diagnostic log中记录。这些慢操作日志条目仅取决于慢操作阈值。它们不取决于日志级别(系统级别或组件级别),配置级别或运行缓慢的采样率。探查器不会捕获缓慢的操作日志条目。
测试所有成员之间的连接
replica set的所有成员必须能够连接到集合中的所有其他成员以支持复制。始终验证两个“方向”上的连接。网络拓扑和防火墙配置可能会阻止正常的连接和所需的连接,从而阻止复制。
在 3.6 版中进行了更改:从 MongoDB 3.6 开始,MongoDB 二进制文件mongod和mongos默认绑定到 localhost(127.0.0.1
)。如果为二进制文件设置了net.ipv6配置文件设置或--ipv6
命令行选项,则该二进制文件还会绑定到 IPv6 地址::1
。
以前,从 MongoDB 2.6 开始,默认情况下,只有正式 MongoDB RPM(Red Hat,CentOS,Fedora Linux 和派生版本)和 DEB(Debian,Ubuntu 和派生版本)程序包中的二进制文件绑定到 localhost。
当仅绑定到 localhost 时,这些 MongoDB 3.6 二进制文件只能接受来自同一台计算机上运行的 Client 端(包括mongo shell,部署中其他成员(副本集和分片群集)的连接)。远程 Client 端无法连接到仅绑定到 localhost 的二进制文件。
要覆盖并绑定到其他 IP 地址,可以使用net.bindIp配置文件设置或--bind_ip
命令行选项来指定 IP 地址列表。
Warning
绑定到非 localhost(例如可公开访问)的 IP 地址之前,请确保已保护群集免受未经授权的访问。有关安全建议的完整列表,请参见Security Checklist。至少考虑enabling authentication和加强网络基础设施。
例如,以下mongod实例同时绑定到 localhost 和示例 IP 地址198.51.100.1
:
mongod --bind_ip localhost,198.51.100.1
为了连接到该实例,远程 Client 端必须指定 IP 地址198.51.100.1
或与该 IP 地址关联的主机名:
mongo --host 198.51.100.1
mongo --host My-Example-Associated-Hostname
考虑以下网络双向测试示例:
Example
给定一个副本集,其中三个成员分别在三个不同的主机上运行:
-
m1.example.net
-
m2.example.net
-
m3.example.net
这三个都使用默认端口27017
。
- 使用以下操作集
m1.example.net
测试从m1.example.net
到其他主机的连接:
mongo --host m2.example.net --port 27017
mongo --host m3.example.net --port 27017
- 使用从
m2.example.net
设置的以下操作测试从m2.example.net
到其他两台主机的连接,如下所示:
mongo --host m1.example.net --port 27017
mongo --host m3.example.net --port 27017
现在,您已经在两个方向上测试了m2.example.net
和m1.example.net
之间的连接。
- 通过设置
m3.example.net
主机中的以下操作来测试从m3.example.net
到其他两个主机的连接,如下所示:
mongo --host m1.example.net --port 27017
mongo --host m2.example.net --port 27017
如果任何方向的连接失败,请检查网络和防火墙配置,然后重新配置环境以允许这些连接。
重新启动多个辅助节点时的套接字异常
重新引导副本集的成员时,请确保该副本集能够在维护期间选择主副本集。这意味着确保该集合的大多数members[n].votes可用。
当集合的活跃成员不能再占多数时,集合的primary会下移并成为secondary。前一个主服务器关闭与 Client 端应用程序的所有打开的连接。尝试写入以前的主要对象的 Client 端会收到套接字异常和“连接重置”错误,直到该集合可以选择主要对象为止。
Example
给定一个三成员副本集,其中每个成员都有一票,如果至少有两个成员可以相互连接,则该集合可以选举主要成员。如果立即重新启动两个辅助节点,则主要节点会降级并成为辅助节点。直到至少另一个辅助节点变为可用,即,至少一个重新启动的辅助节点也变为可用,该集合才没有主节点,也无法选择新的主节点。
有关投票的更多信息,请参见副本集选举。有关连接错误的相关信息,请参见TCP 保持活动时间是否会影响 MongoDB 部署?。
检查 Oplog 的大小
较大的oplog可以使副本集对延迟的容忍度更大,并使副本集更具弹性。
要检查给定replica set成员的操作日志的大小,请在mongo shell 中连接到该成员并运行rs.printReplicationInfo()方法。
输出显示操作日志的大小和操作日志中包含的操作的日期范围。在以下示例中,操作日志大约为 10 MB,并且能够容纳大约 26 小时(94400 秒)的操作:
configured oplog size: 10.10546875MB
log length start to end: 94400 (26.22hrs)
oplog first event time: Mon Mar 19 2012 13:50:38 GMT-0400 (EDT)
oplog last event time: Wed Oct 03 2012 14:59:10 GMT-0400 (EDT)
now: Wed Oct 03 2012 15:00:21 GMT-0400 (EDT)
操作日志应该足够长,以使所有事务在您希望辅助服务器上拥有最长的停机时间。至少,一个 oplog 应该至少能够保存 24 小时的操作;但是,许多用户更喜欢 72 小时甚至一周的工作时间。
有关 oplog 大小如何影响操作的更多信息,请参见:
-
延迟副本集成员, and
Note
通常,您希望所有成员的 oplog 大小相同。如果调整操作日志的大小,请在所有成员上调整其大小。
要更改操作日志的大小,请参见更改操作日志的大小教程。
OplogImporting 时间戳错误
考虑mongod输出和日志中的以下错误:
replSet error fatal couldn't query the local local.oplog.rs collection. Terminating mongod after 30 seconds.
<timestamp> [rsStart] bad replSet oplog entry?
通常,最后一个oplog条目的ts
字段中 Importing 错误的值会导致此错误。正确的数据类型是时间戳。
对 oplog 集合使用以下两个查询来检查ts
值的类型:
db = db.getSiblingDB("local")
db.oplog.rs.find().sort({$natural:-1}).limit(1)
db.oplog.rs.find({ts:{$type:17}}).sort({$natural:-1}).limit(1)
第一个查询返回操作日志中的最后一个文档,第二个查询返回操作日志中的最后一个文档,其中ts
值为时间戳。 $type运算符使您可以选择BSON type 17,即 Timestamp 数据类型。
如果查询没有返回相同的文档,则操作日志中的最后一个文档的ts
字段中的数据类型错误。
Example
如果第一个查询将其作为最后一个 oplog 条目返回:
{ "ts" : {t: 1347982456000, i: 1},
"h" : NumberLong("8191276672478122996"),
"op" : "n",
"ns" : "",
"o" : { "msg" : "Reconfig set", "version" : 4 } }
第二个查询将其返回为最后一个条目,其中ts
具有Timestamp
类型:
{ "ts" : Timestamp(1347982454000, 1),
"h" : NumberLong("6188469075153256465"),
"op" : "n",
"ns" : "",
"o" : { "msg" : "Reconfig set", "version" : 3 } }
然后,最后一个 oplog 条目中的ts
字段的值是错误的数据类型。
若要为此值设置适当的类型并解决此问题,请使用类似于以下内容的更新操作:
db.oplog.rs.update( { ts: { t:1347982456000, i:1 } },
{ $set: { ts: new Timestamp(1347982456000, 1)}})
根据您的 oplog 条目,根据需要修改时间戳记值。该操作可能需要一段时间才能完成,因为更新必须扫描并将整个操作日志拖入内存。
local.slaves 上的重复密钥错误
在 3.0.0 版中更改。
MongoDB 3.0.0 删除了local.slaves集合。对于 MongoDB 早期版本中的local.slaves
错误,请参阅《 MongoDB 手册》的相应版本。