MongoDB爱好者
垂直技术交流平台

常见问题:MongoDB诊断

·我在哪里可以找到有关mongod进程意外停止运行的信息?

·TCP keepalive时间是否会影响MongoDB部署?

·为什么MongoDB会记录这么多“Connection Accepted”事件?

·有哪些工具可用于监控MongoDB?

·MMAPv1存储引擎的内存诊断

·WiredTiger存储引擎的内存诊断

·分片集群诊断

本文档提供常见诊断问题和问题的答案。
如果找不到您要找的答案,请查看常见问题解答的完整列表或将您的问题发布到 MongoDB用户邮件列表

我在哪里可以找到有关mongod进程意外停止运行的信息?

如果mongod在基于UNIX或基于UNIX的平台上意外关闭,并且mongod无法记录关闭或错误消息,请检查系统日志中是否有与MongoDB相关的消息。例如,使用以下命令查看位于/var/log/messages中的日志,

复制
sudo grep mongod / var / log / messages
sudo grep score / var / log / messages

TCP keepalive时间是否会影响MongoDB部署?

(译者注:tcp keepalive时间设置,主要用来探测连接对端是否还存活。当你建立一个TCP连接的时候,便有一组定时器与之绑定在一起。其中的一些定时器就用于处理keepalive过程。当keepalive定时器到0的时候,我们便会给对端发送一个不包含数据部分的keepalive探测包。如果我们收到了keepalive探测包的回复消息,那么我们就可以断定连接依然是OK的。如果我们没有收到对端keepalive探测包的回复消息,我们便可以断定连接已经不可用,进而可以采取一些措施。)

在客户端和服务器之间或者分片集群或副本集的成员之间,如果遇到套接字错误,而没有其他合理的原因,请检查TCP keepalive值(例如,Linux系统上的tcp_keepalive_time 值)。常见的keepalive周期是 7200秒(2小时); 但是,不同的发行版和macOS可能有不同的设置。

对于MongoDB,设置更短的keepalive周期将获得更好的结果,大约为120秒(两分钟)。

如果您的MongoDB部署遇到与keepalive相关的问题,则必须在托管MongoDB进程的所有计算机上更改keepalive值。这包括托管mongos或 mongod进程的所有计算机以及连接到MongoDB的客户端进程的所有宿主计算机。

注意
对于非Linux系统,大于或等于600秒(10分钟)的值将被mongod和 mongos忽略。对于Linux,大于300秒(5分钟)的值将在mongod和 mongos套接字上被覆盖,最多为300秒。

在Linux系统上:
· 要查看keep alive设置,可以使用以下命令之一:
复制
sysctl net.ipv4.tcp_keepalive_time

或者:

复制
cat / proc / sys / net / ipv4 / tcp_keepalive_time

该值以秒为单位测量。

注意
虽然路径包含ipv4,但该tcp_keepalive_time值适用于IPv4和IPv6。

  • 要更改该tcp_keepalive_time值,可以使用以下命令之一:
    复制
    sudo sysctl -w net.ipv4.tcp_keepalive_time =

或者:

复制
echo | sudo tee / proc / sys / net / ipv4 / tcp_keepalive_time

  • 这些操作不会在系统重新启动后继续生效。要保留设置,请将以下行添加到/etc/sysctl.conf:

复制
net.ipv4.tcp_keepalive_time =

  • 在Linux中,mongod并mongos进程将设置keep alive值为300秒(5分钟),来重写覆盖大于5分钟的设置。

对于macOS系统:
– 要查看keep alive设置,请执行以下命令:

复制
sysctl net.inet.tcp.keepinit

  • 要更改net.inet.tcp.keepinit值,可以使用以下命令:

复制
sysctl -w net.inet.tcp.keepinit =

上述设置TCP keepalive的方法不是持久的; 每次重新启动或重新启动系统时都需要重置该值。有关持久化设置TCP keepalive值的说明,请参阅操作系统的文档。

对于Windows系统:
– 要查看keepalive设置,请执行以下命令:

复制
reg query HKLM \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters / v KeepAliveTime

默认情况下,注册表值不存在。如果值不存在,则使用系统默认值7200000 毫秒或 十六进制值0x6ddd00。

  • 要更改该KeepAliveTime值,请在管理员命令提示符中使用以下命令,其中以十六进制表示(例如120000 为0x1d4c0):

复制
reg add HKLM \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters \ / t REG_DWORD / v KeepAliveTime / d < value >

Windows用户应该参考 Windows Server Technet Article on KeepAliveTime,以获取有关在Windows系统上为MongoDB部署设置保持活动状态的更多信息。

您需要重新启动mongod并mongos 进程,新的keepalive系统设置才能生效。

为什么MongoDB会记录这么多“Connection Accepted”事件日志?

如果您在MongoDB日志中看到非常大量的连接和重新连接消息,则客户端经常连接和断开与MongoDB服务器的连接。对于不使用请求连接池的应用程序(例如CGI),这是正常行为。考虑使用FastCGI,一个Apache模块或其他类型的持久应用程序服务器来减少连接开销。

如果这些连接不会影响性能,则可以使用运行时quiet选项或命令行选项 –quiet来禁止日志中的这些消息。

有哪些工具可用于监控MongoDB?

从版本4.0开始,MongoDB 为单机部署和副本集提供免费的云监控。免费监控提供如下与部署相关信息:
· 操作执行时间
· 内存使用情况
· CPU使用率
· 操作计数
有关更多信息,请参阅免费监控

MongoDB Cloud ManagerOps ManagerMongoDB企业版提供的先进的内部部署解决方案包括:监控功能,其收集运行的MongoDB部署数据,并提供基于数据可视化和报警。

有关更多信息,另请参阅MongoDB Cloud Manager文档 Ops Manager文档

Monitor for MongoDB文档中提供了完整的第三方工具列表 。

MMAPv1存储引擎的内存诊断

弃用
MongoDB 4.0弃用了MMAPv1存储引擎,并将在以后的版本中删除MMAPv1。要将MMAPv1存储引擎部署更改为 WiredTiger存储引擎,请参阅:
·将Standalone更改为WiredTiger
·将副本集更改为WiredTiger
·将Sharded Cluster更改为WiredTiger

我需要配置swap空间吗?

始终将系统配置为具有swap空间。如果没有swap空间,在极端内存限制,内存泄漏或多个程序使用相同内存的情况下,您的系统可能将不可靠。将swap空间想象成蒸汽释放阀,使系统释放额外的压力而不影响系统的整体功能。

然而,运行的MongoDB系统并不需要为日常操作交换。数据库文件是内存映射的,应构成MongoDB内存的大部分内存使用。因此,mongod 在正常操作中不太可能使用任何交换空间。操作系统将从内存映射文件中释放内存而无需交换,MongoDB可以将数据写入数据文件而无需swap。

什么是“working set”?

working set是客户端最常访问数据的一部分。

我的working set必须适合内存吗?

你的working set应该放在内存中以获得良好的性能。否则会发生许多随机磁盘IO,除非您使用SSD,否则这可能会很慢。

在管理working set大小时要特别注意的一个方面是索引访问模式。如果要在随机位置插入索引(就像哈希算法随机生成的id一样),您将不断更新整个索引。如果您能够以近似升序创建您的ID(例如,日期加上一个随机id值。(译者注:_id默认的类型ObjectId就是类似这样的生成规则,所以建议没有特殊需求,不要修改ObjectId的生成方式)),则所有更新将发生在b-tree 的右侧,并且索引页的working set大小将会很多小。

如果数据库大小以及因此设置的虚拟内存大小远大于内存大小,那就没问题。

如何计算我的应用程序需要多少内存?

您需要的内存大小取决于几个因素,包括但不限于:
· 数据库存储和working set之间的关系。
· 操作系统的LRU缓存淘汰策略(最近最少使用)
· Journaling预写日志的影响
· page fault(缺页中断)的数量或速率以及其他MongoDB Cloud Manager检测发现何时需要更多的内存
· 每个数据库连接线程最多需要1 MB的RAM。

从磁盘加载数据到内存时,MongoDB交给操作系统进行。它只是通过内存映射其所有数据文件,并依赖于操作系统来缓存数据。当内存不足时,操作系统通常会从内存中驱逐最近最少使用的数据。例如,如果客户端访问索引比访问文档更频繁,则索引更可能保留在内存中,但这取决于您的特定用法。

要计算所需的内存大小,您必须计算working set大小或客户最常使用的数据部分。这取决于您的访问模式,您拥有的索引以及文档的大小。由于MongoDB每个连接使用一个线程,因此每个数据库连接也需要最多1 MB的内存,无论是活动还是空闲。

如果page fault很少发生,那么表示您的working set就能放入内存。如果page fault数量比较高,则可能会降低性能。对于SSD固态硬盘而言,这个影响相比机械磁盘就不那么重要了。

如何在UNIX top命令中读取内存统计信息

因为mongod使用内存映射文件,top 中的内存统计信息需要以特殊方式解释。在大型数据库上,VSIZE (虚拟内存大小,单位字节)往往是整个数据库的大小。如果 mongod没有其他进程在运行,则RSIZE (驻留内存大小,单位字节)是计算机的总内存,因为这会计算文件系统缓存内容。

对于Linux系统,请使用vmstat命令帮助确定系统如何使用内存。在macOS系统上使用vm_stat。

WiredTiger存储引擎的内存诊断

我的working set大小一定要适合内存大小吗?

不用。
如果缓存没有足够的空间来加载其他数据,WiredTiger会从缓存中清除内存页以释放空间。

注意
storage.wiredTiger.engineConfig.cacheSizeGB限制WiredTiger内部缓存的大小。操作系统将使用可用的空闲内存用于文件系统缓存,以允许压缩的MongoDB数据文件保留在内存中。此外,操作系统将使用任何空闲内存来缓冲文件系统块和文件系统缓存。
为了容纳额外的内存使用者,您可能必须减少WiredTiger内部缓存大小。

默认的WiredTiger内部缓存大小值假定每台计算机有一个mongod实例。如果单个计算机包含多个MongoDB实例,则应减少该设置值以安排其他mongod 实例。

如果您在无法访问系统中所有可用内存 的容器(例如lxc, cgroupsDocker等)中运行mongod,则必须将storage.wiredTiger.engineConfig.cacheSizeGB设置为小于容器中可用内存大小的值。确切的数量取决于容器中运行的其他进程。

要查看有关缓存和缓存淘汰的统计信息,请使用 serverStatus命令。命令输出的 wiredTiger.cache字段包含有关缓存和缓存淘汰的信息。

复制
...
"wiredTiger" : {
...
"cache" : {
"tracked dirty bytes in the cache" : ,
"bytes currently in the cache" : ,
"maximum bytes configured" : ,
"bytes read into cache" :,
"bytes written from cache" : ,
"pages evicted by application threads" : ,
"checkpoint blocked page eviction" : ,
"unmodified pages evicted" : ,
"page split during eviction deepened the tree" : ,
"modified pages evicted" : ,
"pages selected for eviction unable to be evicted" : ,
"pages evicted because they exceeded the in-memory maximum" : ,,
"pages evicted because they had chains of deleted items" : ,
"failed eviction of pages that exceeded the in-memory maximum" : ,
"hazard pointer blocked page eviction" : ,
"internal pages evicted" : ,
"maximum page size at eviction" : ,
"eviction server candidate queue empty when topping up" : ,
"eviction server candidate queue not empty when topping up" : ,
"eviction server evicting pages" : ,
"eviction server populating queue, but not evicting pages" : ,
"eviction server unable to reach eviction goal" : ,
"pages split during eviction" : ,
"pages walked for eviction" : ,
"eviction worker thread evicting pages" : ,
"in-memory page splits" : ,
"percentage overhead" : ,
"tracked dirty pages in the cache" : ,
"pages currently held in the cache" : ,
"pages read into cache" : ,
"pages written from cache" : ,
},
...

有关一些缓存和缓存淘汰统计信息字段的解释,例如wiredTiger.cache.bytes currently in the cache和wiredTiger.cache.tracked dirty bytes in the cache,请参阅wiredTiger.cache
要调整WiredTiger内部缓存的大小,请参阅 storage.wiredTiger.engineConfig.cacheSizeGB–wiredTigerCacheSizeGB。应该避免将WiredTiger内部缓存大小增加到大于其默认值。

如何计算我的应用程序需要多少内存?

使用WiredTiger,MongoDB同时使用WiredTiger内部缓存和文件系统缓存。

从MongoDB 3.4开始,默认的WiredTiger内部缓存大小是以下两者中的较大者:
· 50%(内存大小 – 1 GB),或
· 256 MB。

例如,在总共4GB 内存的系统上,WiredTiger缓存将使用1.5GB的内存(0.5* (4 GB – 1 GB) = 1.5 GB)。相反,具有总共1.25 GB 内存的系统将为WiredTiger缓存分配256 MB,因为这超过总内存的一半减去1GB字节(0.5 *(1.25 GB – 1 GB) = 128 MB < 256 MB)。

默认情况下,WiredTiger对所有集合使用Snappy块压缩,对所有索引使用前缀压缩。压缩默认设置可在全局级别配置,也可在每个集合和每个索引创建期间单独进行设置。

WiredTiger内部缓存中的数据与磁盘上的数据使用不同表示形式的数据格式:

· 文件系统缓存中的数据与磁盘格式相同,包括对数据文件进行的任何压缩的好处也是一样的。操作系统使用文件系统缓存来减少磁盘I / O.
· 在WiredTiger内部缓存中加载的索引具有与磁盘格式不同的数据表示,但仍可利用索引前缀压缩来减少内存使用。索引前缀压缩从索引字段中去除重复的公共前缀。
· WiredTiger内部缓存中的集合数据是未压缩的,并使用与磁盘格式不同的表示形式。块压缩可以节省大量的磁盘存储空间,但数据必须解压缩才能由服务器操作。

通过文件系统缓存,MongoDB自动使用WiredTiger缓存或其他进程未使用的所有可用内存。

要调整WiredTiger内部缓存的大小,请参阅 storage.wiredTiger.engineConfig.cacheSizeGB–wiredTigerCacheSizeGB。应当避免将WiredTiger内部缓存大小增加到其默认值以上。

注意
storage.wiredTiger.engineConfig.cacheSizeGB限制WiredTiger内部缓存的大小。操作系统将使用可用的空闲内存用于文件系统缓存,这允许压缩的MongoDB数据文件保留在内存中。此外,操作系统将使用任何空闲内存来缓冲文件系统块和文件系统缓存。
为了容纳其他的内存消费者,您可能必须减少WiredTiger内部缓存大小。

默认的WiredTiger内部缓存大小值假定每台计算机只有一个mongod实例。如果单个计算机包含多个MongoDB实例,则应减少该设置以适应其他mongod 实例。

如果您的mongod是运行在无法访问系统中所有可用内存 的容器(例如lxc, cgroups,Docker等)中时,则必须将storage.wiredTiger.engineConfig.cacheSizeGB设置为小于容器中可用内存大小的值。确切的大小取决于容器中运行的其他进程。

要查看有关缓存和缓存淘汰率的统计信息,请参阅从serverStatus命令返回的 wiredTiger.cache字段

分片集群诊断

成功维护分片集群的两个最重要的因素是:
· 选择适当的片键
· 足以支持当前和未来运营的容量。

通过确保为部署选择最佳的片键并确保在当前资源饱和之前始终为集群添加额外容量,可以防止分片遇到的大多数问题。继续阅读,查看您在生产环境中可能遇到的特定问题。

在新的分片集群中,为什么所有数据都保留在一个分片上?

您的集群必须有足够的数据才能进行均衡。通过在分片之间迁移chunk数据块来进行负载均衡,直到每个分片具有大致相同数量的分块。

默认块大小为64M字节。在集群中的chunk数据块数量不平衡差异没有超过迁移阈值之前,MongoDB不会开始迁移 。此行为有助于防止不必要的块迁移降低整个集群的性能。

如果您刚刚部署了分片集群,请确保您有足够的数据来使分片生效。如果没有足够的数据来创建超过8个64 MB的块,那么所有数据都将保留在一个分片上。要么降低块大小设置,要么向集群添加更多数据。

作为一个相关问题,系统将仅在插入或更新时拆分块,这意味着如果您配置了分片并且不继续发出插入和更新操作,则数据库将不会创建任何块。您可以等到应用程序插入数据或手动拆分块。

最后,如果您的片键具有低基数,MongoDB可能无法在数据之间创建足够的分割(chunk将无法继续分裂)。

为什么一个分片会在分片集群中收到不均衡的流量?

在某些情况下,单个分片或集群的子集将接收不均衡的流量和工作负载。在几乎所有情况下,这都是片键的结果,该片键不能有效地允许写缩放。

你也可能有写“热点”chunk数据块。在这种情况下,你可以通过拆分然后迁移这些块来解决问题。

在最坏的情况下,您可能必须考虑重新分片数据并选择不同的片键 来更正此情况。

什么可以阻止分片集群均衡?

如果刚刚部署了分片集群,则可能需要考虑新数据集中数据保留在单个分片上的故障排除建议。
如果集群最初是均衡的,但后来发展出不均匀的数据分布,请考虑以下可能的原因:

· 您已从集群中删除或移除了大量数据。如果添加了其他数据,则其根据其片键可能具有不同的分布。
· 您的片键具有较低的基数 ,MongoDB无法进一步分割chunk数据块。
· 您的数据集增长速度快于均衡器可以在集群间分发数据的速度。这种情况并不常见,通常是以下情况导致的:

—— 均衡窗口太短,相对于数据增长的速度。
—— 写操作的分布不均匀,需要更多的数据迁移工作。您可能必须选择其他分片键才能解决此问题。
—— 分片之间的网络连接不良,这可能导致需要很长时间才能完成数据块迁移。检查网络配置和分片之间的互连。

为什么块迁移会影响分片集群性能?

如果迁移会影响您的集群或应用程序的性能,请考虑以下选项,具体取决于影响的性质:
1. 如果迁移仅偶尔中断集群,则可以限制均衡窗口以防止在高峰时段进行均衡活动。确保有足够的时间来防止数据再次失去均衡。
2. 如果均衡器始终迁移块而不利于整体集群性能:
—— 您可能希望尝试减小块大小 以限制迁移的大小。
—— 您的集群可能超载,您可能希望尝试向 集群添加一个或两个分片以分摊负载。
您的片键也可能导致您的应用程序将所有写入指向单个分片。这种活动模式可能要求均衡器在写入后立即迁移大部分数据。考虑使用提供更好的适合写入扩展的片键重新部署集群。

来源: https://docs.mongodb.com/manual/faq/diagnostics/
分类:常见问题
标签:日志,系统日志,监控,存储引擎,MMAPv1,WiredTiger,分片集群,诊断,索引,b-tree,ObjectId,迁移,分裂,片键基数,片键

钟秋
BBD技术经理,资深架构师
MongoDB中文社区联席主席
有丰富项目中应用MongoDB经验,熟悉MongoDB相互模式设计及性能优化,熟悉大数据相关技术和互联网及大数据应用架构设计

赞(4)
未经允许不得转载:MongoDB中文社区 » 常见问题:MongoDB诊断

评论 抢沙发

评论前必须登录!