本文是翻译MongoDB Manuel中的MongoDB Production Notes一节内容。这节内容重点关注生产环境中影响性能和可靠性的各种注意事项,值得正在部署MongoDB的工作者们关注。以下是正文。

 

本文详细描述了影响MongoDB,特别是生产环境的关键系统配置。

注意:MongoDB Atlas is a cloud-hosted database-as-a-service. MongoDB Cloud Manager, a hosted service, and Ops Manager, an on-premise solution, provide monitoring, backup, and automation of MongoDB instances.

安装包

MongoDB

确保你安装了最新的稳定版本。所有稳定版本都发布在下载页。这是了解最新版本的最佳场所,即使你稍后选择从包管理器安装。

生产环境始终使用64位版本。32位版本是为测试和部署环境准备的,不适于生产环境部署,因为它只能存储2GB以内的数据。了解更多内容请查看32位限制。

32位版本的存在是为满足非正式环境的使用场景。

操作系统

建议使用:

  • Amazon Linux 2
  • Debian 9 and 10
  • RHEL / CentOS 6, 7, and 8
  • SLES 12
  • Ubuntu LTS 16.04 and 18.04
  • Windows Server 2016

MongoDB dbPath

The files in the dbPath directory must correspond to the configured storage engine. mongod will not start if dbPath contains data files created by a storage engine other than the one specified by --storageEngine.

mongod must possess read and write permissions for the specified dbPath.

dbPath目录中的文件必须与配置的存储引擎相对应。如果dbPath包含由存储引擎创建的数据文件,而不是由--storage engine指定的数据文件,mongod将不会启动。

mongod必须拥有指定dbPath的读写权限。

 

并发

WiredTiger支持读写器对集合中文档的并发访问。客户端可以在进行写操作时读取文档,多个线程可以同时修改集合中的不同文档。

如果分配足够的RAM和CPU就可以看到提有关WiredTiger如何利用多个CPU核心以及如何通过CPU改进操作的信息

 

Data Consistency 数据一致性

1 Journaling 日志记录

MongoDB使用磁盘日志的 预写日志记录。日志保证MongoDB可以在mongod因崩溃或其他严重故障而终止的情况下,快速恢复写入到日志文件,但未写入数据文件的 写操作。

保持Journal处于启用状态,以确保mongod能够恢复其数据文件,并在崩溃后将数据文件保持在有效状态。

从MongoDB 4.0开始,不能为使用WiredTiger存储引擎的副本集成员指定--nojournal选项或storage.journal.enabled:false。

 

2 Read Concern 读关注

版本3.2中的新功能。

从MongoDB 3.6开始,如果写入请求确认,可以使用因果一致的会话来读取自己的写入。

在MongoDB 3.6之前,您必须使用{w:“多数”}写关注点发出写操作,然后对读操作使用“多数”或“可线性化”读关注点,以确保单个线程可以读取自己的写操作。

要使用“多数”的读取关注级别,副本集必须使用WiredTiger存储引擎。

对于具有三个成员的主从仲裁者(PSA)架构的部署,可以禁用read concern“多数”;但是,这会影响更改流(仅在MongoDB 4.0和更早版本中)和分片集群上的事务。

 

 3 Write Concern 写关注点

Write concern描述MongoDB请求的写入操作确认级别。写关注点的级别影响写操作返回的速度。当写操作具有弱写关注点时,它们会快速返回。对于更强烈的写问题,客户端必须在发送写操作后等待,直到MongoDB在请求的写问题级别确认写操作。在写入问题不充分的情况下,客户端可能认为写入操作已成功,但在某些服务器故障的情况可能并没有持久化数据。

 

网络

1 Use Trusted Networking Environments¶

始终在受信任的环境中运行MongoDB,使用网络规则阻止所有未知计算机、系统和网络的访问。与依赖于网络访问的任何敏感系统一样,MongoDB部署应该只对需要访问的特定系统(如应用程序服务器、监视服务和其他MongoDB组件)可访问。

默认情况下,未启用授权,mongod假定环境可信。根据需要启用授权模式。有关MongoDB中支持的身份验证机制以及MongoDB中的授权的详细信息,请参阅身份验证和基于角色的访问控制。

有关安全性的其他信息和注意事项,请参阅“安全性”一节中的文档,特别是:

  • Security Checklist
  • Network and Configuration Hardening

对于Windows用户,在Windows上部署MongoDB时,请考虑有关TCP配置的Windows Server Technet文章。

2 禁用HTTP接口

在版本3.6中更改:MongoDB 3.6将不推荐使用的HTTP接口和REST API从MongoDB删除。

MongoDB的早期版本提供了一个HTTP接口来检查服务器的状态,并可以选择运行查询。默认情况下禁用HTTP接口。不要在生产环境中启用HTTP接口。

3 管理连接池大小

通过调整连接池大小以适应您的用例,避免mongod或mongos实例的连接资源超载。从当前数据库请求的典型数量的110-115%开始,并根据需要修改连接池大小。请参阅连接池选项以调整连接池大小。

connPoolStats命令返回有关分片集群中mongos和mongod实例到当前数据库的打开连接数的信息。

db.runCommand({connPoolStats:1})

 

硬件考量

MongoDB的设计是基于兼容大多数硬件考虑,几乎没有特别的要求或限制。MongoDB的核心组件能够运行于小端字节优先的硬件,主要是x86/x86_64处理器上。客户端类库(例如驱动)在大端优先或小端优先系统上都可以运行。

1 分配了足够的内存和CPU

犹如对于所有软件一样,更多的内存和更快的CPU时钟频率对于性能很重要。

基本上,数据库并非受限于CPU。因此,增加核心数量虽然有帮助,但不会提供显著的回报。

2 WiredTiger

WiredTiger存储引擎是多线程的,可以利用额外的CPU核心。CPU的数量和活动线程的相对数量可能会影响性能:

具体应该用多少线程 ,这个阈值取决于您的应用程序。您可以通过实验和测量吞吐量来确定应用程序的最佳并发活动操作数。mongostat的输出提供(ar | aw)列中活动读/写次数的统计信息。

 

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

从MongoDB 3.4开始,默认的WiredTiger内部缓存大小为以下两者中的较大者:

50%(RAM-1 GB),或256兆字节。

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

要查看内存限制,请参阅hostInfo.system.memLimitMB。

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

默认情况下,WiredTiger对所有集合使用snapy块压缩,对所有索引使用前缀压缩。压缩默认值在全局级别上是可配置的,也可以在集合和索引创建期间根据每个集合和每个索引进行设置。

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

1)文件系统缓存中的数据与磁盘上的格式相同,包括对数据文件进行任何压缩的好处。操作系统使用文件系统缓存来减少磁盘I/O。

2) 加载在WiredTiger内部缓存中的索引与磁盘上的格式具有不同的数据表示形式,但仍然可以利用索引前缀压缩来减少RAM的使用。索引前缀压缩从索引字段中删除常用前缀。

3) WiredTiger内部缓存中的收集数据是未压缩的,使用与磁盘格式不同的表示形式。块压缩可以显著节省磁盘存储空间,但数据必须解压缩才能由服务器操作。

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

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

可以在配置文件中设置。

 

注意

storage.wiredTiger.engineConfig.cacheSizeGB限制wiredTiger内部缓存的大小。操作系统将使用可用的空闲内存进行文件系统缓存,这将允许压缩的MongoDB数据文件保留在内存中。此外,操作系统将使用任何空闲RAM缓冲文件系统块和文件系统缓存。

为了适应RAM的其他使用者,您可能必须减小WiredTiger内部缓存的大小。

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

如果在无法访问系统中所有可用RAM的容器(例如lxc、cgroups、Docker等)中运行mongod,则必须将storage.wiredTiger.engineConfig.cacheSizeGB设置为小于容器中可用RAM的值。具体数量取决于容器中运行的其他进程。参见memLimitMB。

要查看缓存和逐出率的统计信息,请参阅从serverStatus命令返回的wiredTiger.cache字段。

 

 

3 Compression and Encryption¶

当使用加密时,配备AES-NI指令集扩展的CPU可以显示出显著的性能优势。如果将MongoDB Enterprise与加密存储引擎一起使用,请选择支持AES-N指令集的CPU以获得更好的性能。

 

4 使用固态硬盘(SSD)

MongoDB使用SATA SSD能得到很好的效果和很好的性价比。

在足够经济的情况下请使用SSD。传统硬盘也可能很有效率,但SSD对于随机IO访问的良好支持更符合mongod的数据更新模型。

传统硬盘通常也是个好的选择,因为使用更昂贵的硬盘来提高随机IO性能并不是那么有效(只能是每次2倍)。使用SSD或增加RAM的容量可能对于提升IO更有效率。

 

5 MongoDB和NUMA硬件

重要:这里讨论的NUMA仅限于Linux系统,因此不影响运行于其他类Unix系统或Windows系统。

在运行NUMA的系统中运行MongoDB可能造成一系列问题,包括一段时间内的效率低下和高系统进行使用率。

当运行MongoDB在NUMA硬件上时,你应该为MongoDB禁用NUMA并使用Interleave内存策略。

注意:MongoDB 2.0以上版本如果部署在Linux系统上,启动时会检查系统配置,如果系统是基于NUMA的,会给出警告。

为禁用NUMA并启用interleave内存策略,请使用numactl并使用以下方式启动mongod

numactl --interleave=all /usr/bin/local/mongod

然后,为了禁用proc配置中的zone reclaim,请使用以下命令:

echo 0 > /proc/sys/vm/zone_reclaim_mode

为了彻底禁用NUMA,你必须操作以上两步。了解更多信息,请查看/proc/sys/vm/*文档。

查看MySQL“疯狂交换”问题和NUMA效果一文,它描述了NUMA对数据库造成的影响。这篇博客确定了NUMA对MySQL的影响,但对于MongoDB的影响也是类似的。这篇文章介绍了NUMA和它的目标,并指出了为什么这些目标和生产环境数据库的需求是不相容的。

6 磁盘和存储系统

虚拟内存

为你的系统分配虚拟内存。分配虚拟内存可以避免内存争抢问题,同时可以阻止Linux系统的OOM Killer杀死mongod。

对于WiredTiger存储引擎,给定足够的内存压力,WiredTiger可以将数据存储在交换空间中。

RAID

绝大多数MongoDB应该使用RAID-10磁盘系统。

RAID-5和RAID-6典型情况下不能为MongoDB提供足够好的性能。

MongoDB应该避免使用RAID-0。RAID-0提供了足够好的写性能,但它只能提供有限的可用性,并且可能导致读操作性能低下,特别是在Amazon EBS卷上。

 

远程文件系统

MongoDB不推荐使用网络文件系统(NFS),因为一些版本的NFS性能低下。

当数据文件和日志文件同时位于NFS上时就会发生性能问题。如果你把日志放到本地或iscsi上则可能得到更好的性能体验。如果必须使用NFS,添加以下NFS选项到你的/etc/fstab文件:bg,nolock及noatime。

 

把不同的组件放到不同的存储设备

为了提高性能,请考虑根据应用程序的访问和写入模式,将数据库的数据、日志和日志分离到不同的存储设备上。将组件作为单独的文件系统挂载,并使用符号链接将每个组件的路径映射到存储它的设备。

对于WiredTiger存储引擎,还可以将索引存储在不同的存储设备上。有关索引,请参见storage.wiredTiger.engineConfig.directory。

注意:这会影响你创建数据快照的能力。因为文件会在不同的设备和卷上。

 

Scheduling 调度

1)虚拟或云主机设备的调度

对于通过虚拟机监控程序连接到虚拟机实例或由云托管提供商托管的本地块设备,来宾操作系统应使用noop调度程序以获得最佳性能。noop调度程序允许操作系统将I/O调度推迟到底层hypervisor。

2)物理服务器的调度

对于物理服务器,操作系统应使用截止日期计划程序。截止日期调度器限制每个请求的最大延迟,并保持良好的磁盘吞吐量,这对于磁盘密集型数据库应用程序来说是最好的。

 

架构

副本集

有关副本集部署的体系结构注意事项的概述,请参阅副本集体系结构文档。Replica Set Architectures 

碎片簇

有关建议的用于生产部署的分片群集体系结构的概述,请参阅分片群集生产体系结构。Sharded Cluster Production Architecture f

 

压缩

WiredTiger可以使用以下压缩库之一压缩收集数据:

1 snappy

提供比zlib或zstd更低的压缩率,但比任何一种都低的CPU成本。

2 zlib

提供了比snappy更好的压缩率,但比snappy和zstd都要高的CPU成本。

3 zstd(从MongoDB 4.2开始提供)

提供比snappy和zlib更好的压缩率,并且比zlib具有更低的CPU成本。

默认情况下,WiredTiger使用snappy压缩库。要更改压缩设置,请参见storage.wiredTiger.collectionConfig.blockCompressor。

默认情况下,WiredTiger对所有索引使用前缀压缩。

 

Clock Synchronization

MongoDB组件保留逻辑时钟以支持与时间相关的操作。使用NTP来同步主机时钟可以降低组件之间时钟漂移的风险。组件之间的时钟漂移增加了时间相关操作不正确或异常行为的可能性,如下所示:

如果任何给定MongoDB组件的底层系统时钟偏离同一部署中的其他组件一年或更长时间,则这些成员之间的通信可能变得不可靠或完全停止。

maxAcceptableLogicalClockDiftSecs参数控制组件之间可接受的时钟偏移量。MaxAcceptableLogicalClockDiftSecs值较低的集群对时钟漂移的容忍度相应较低。

对于返回当前群集或系统时间的操作,具有不同系统时钟的两个群集成员可能返回不同的值,例如Date()、NOW和cluster_time。

在MongoDB组件之间存在时钟漂移的集群中,依赖于计时的特性可能会有不一致或不可预测的行为。

例如,TTL索引依赖于系统时钟来计算何时删除给定文档。如果两个成员有不同的系统时钟时间,则每个成员可以在不同的时间删除TTL索引覆盖的给定文档。由于客户端会话和因果一致性保证使用TTL索引来控制它们的寿命,时钟漂移可能导致不一致或不可预测的会话超时行为。

运行MongoDB低于3.4.6或3.2.17的部署需要NTP同步,使用Wired Tiger存储引擎,时钟漂移可能导致检查点挂起。该问题在MongoDB 3.4.6+和MongoDB 3.2.17+中得到了修复,并在MongoDB 3.6、4.0和4.2的所有点发布中得到了解决。

 

 

在Linux上运行MongoDB

重要:以下讨论只适用于Linux,因此不影响mongod在其他类Unix系统或Windows系统的部署。

内核和文件系统

在Linux上的生产环境中运行MongoDB时,应该使用Linux内核版本2.6.36或更高版本,并使用XFS或EXT4文件系统。如果可能的话,使用XFS,因为它通常在MongoDB中执行得更好。

对于WiredTiger存储引擎,强烈建议使用XFS,以避免将EXT4与WiredTiger一起使用时可能出现的性能问题。

使用MMAPv1存储引擎,MongoDB在使用数据库文件之前预先分配它们,并经常创建大文件。因此,您应该使用XFS或EXT4文件系统。如果可能的话,使用XFS,因为它通常在MongoDB中执行得更好。

一般来说,如果您使用的是XFS文件系统,那么至少要使用2.6.25版本的Linux内核。

如果使用EXT4文件系统,请至少使用2.6.28版本的Linux内核。

在Red Hat Enterprise Linux和CentOS上,至少使用2.6.18-194版Linux内核。

System C Library

MongoDB在Linux上使用GNU C库(glibc)。一般来说,每个Linux发行版都提供了自己经过审查的版本。为了获得最佳结果,请使用此系统提供版本的最新更新。您可以使用系统的包管理器检查是否安装了最新版本。例如:

在RHEL/CentOS上,以下命令更新系统提供的GNU C库:

sudo yum update glibc

在Ubuntu/Debian上,以下命令更新系统提供的GNU C库:

sudo apt-get install libc6

fsync() on Directories

MongoDB要求文件系统对目录支持fsync()。所以例如HGFS和Virtual Box的共享目录不支持这个操作。

Set vm.swappiness to 1

Swappiness是一种Linux内核设置,当需要分配swap时,它会影响虚拟内存管理器的行为,范围从0到100,包括。

   设置为0时,内核只会交换以避免出现内存不足问题。

   设置为100会告诉它积极地交换到磁盘。

如果主机运行3.5或更高版本的内核,或RHEL/CentOS kernel 2.6.32-303或更高版本,则将此值设置为0可能会禁用交换。将此设置为1。

要查看当前交换级别,请运行:

cat/proc/sys/vm/swappiness目录

要在系统运行时更改交换,请运行:

sysctl vm.swappiness=1

要永久更改交换性,请在首选文本编辑器中编辑/etc/sysctl.conf文件并更改此值:

vm.swappiness=1个

 

Recommended Configuration¶

1 对于所有MongoDB部署:

使用网络时间协议(NTP)在主机之间同步时间。这在sharded clusters中尤为重要。

2 对于WiredTiger存储引擎,请考虑以下建议:

  • 在包含数据文件的卷关闭atime配置。
  • 按照UNIX ulimit设置的推荐,设置描述符限制,-n及其他用户进程限制(ulimit),-u到多于20000。较低的ulimit配置在大压力情况下会影响MongoDB,并且可能产生错误及导致连接到MongoDB失败和服务不可用。
  • 不要使用hugepages虚拟内存页,因为MongoDB在正常虚拟内存页中表现更好。
  • 在BIOS中禁用NUMA。如果做不到,请参考MongoDB和NUMA硬件章节。

如果不使用默认的MongoDB目录路径或端口,请为MongoDB配置SELinux。

请参阅:Configure SELinux for MongoDB和Configure SELinux for MongoDB Enterprise以获得所需的配置。

 

无论存储介质类型(旋转磁盘、SSD等)如何,将readahead设置设置为8到32。

较高的预读通常有利于顺序I/O操作。由于MongoDB磁盘访问模式通常是随机的,因此使用更高的readahead设置提供的好处有限,或者可能会降低性能。因此,为了获得最佳的MongoDB性能,请将readahead设置在8到32之间,除非测试在更高的readahead值中显示出可测量、可重复和可靠的好处。MongoDB商业支持可以提供关于备用预读配置的建议和指导。

 

 

MongoDB and TLS/SSL Libraries

在Linux平台上,您可以在MongoDB日志中看到以下语句之一:

<path to TLS/SSL libs>/libssl.so.<version>:没有可用的版本信息(由/usr/bin/mongod要求)

<path to TLS/SSL libs>/libcrypto.so.<version>:没有可用的版本信息(由/usr/bin/mongod要求)

这些警告表示系统的TLS/SSL库与mongod编译时所针对的TLS/SSL库不同。通常这些消息不需要干预;但是,您可以使用以下操作来确定mongod期望的符号版本:

objdump-T<path to mongod>/mongod | grep“SSL”

objdump-T<path to mongod>/mongod | grep“加密”

这些操作将返回类似于以下行之一的输出:

0000000000000000 DF*UND*0000000000000000 libssl.so.10 SSL_写入

0000000000000000 DF*UND*0000000000000000 OPENSSL_1.0.0 SSL_write

此输出中的最后两个字符串是符号版本和符号名称。将这些值与以下操作返回的值进行比较,以检测符号版本不匹配:

objdump-T<path to TLS/SSL libs>/libssl.so.1*

objdump-T<path to TLS/SSL libs>/libcrypto.so.1*

这个过程既不精确也不详尽:mongod从libcrypto库中使用的许多符号不是以CRYPTO开头的。

虚拟环境中的MongoDB

本章节描述了在常用虚拟环境中运行MongoDB需要考虑的问题。

EC2

MongoDB与EC2环境兼容,不需要指定特别的环境配置。

作为选择之一,你也可以选择一组绑定了MongoDB和提供了Amazon Provisioned IOPS卷的Amazon机器映像(AMI)。Provisioned IOPS能够极大地增进MongoDB的性能和易用性。查看这篇博客以了解更多信息。

VMWare

MongoDB兼容VMWare。如果用户陷入VMWare的内存过量使用特性问题,推荐禁用掉这个特性。

克隆一个正在运行MongoDB的虚拟机是可能的。你可以使用这个特性来配置一个新的虚拟主机,并把它加入到Replica Set中。如果你克隆了一台启用日志的VM,克隆出来的快照将是可用的。如果没有启用日志,需要先信用mongod,克隆VM,最后重新启动mongod。

OpenVZ

有些用户在运行老版本的OpenVZ上运行MongoDB上遇到问题是因为它处理虚拟内存的方式,跟VMWare类似原因。

这个问题看起来在最近的OpenVZ版本中已经解决了。

性能监控

iostat

在Linux上,可以使用iostat命令检查磁盘IO是否是你的数据库的瓶颈。在使用iostat时指定一个更新时间秒数,以避免得到的是自机器启动以来的平均IO统计。

例如,以下命令将会以每份报告中显示扩展统计,带有MB/s为单位的流量统计,每秒统计一次:

iostat -xmt 1

iostat的关键字段:

  • %util: 这是快速检查时最有用的字段。它指示设备/驱动器占用了处理时间的多少百分比。
  • avgrq-sz: 平均请求大小。越小的值代表越随机的IO操作。

bwm-ng

bwm-ng是用于监控网络流量的命令行工具。如果你怀疑网络遇到瓶颈,则可以使用bwm-ng来启动诊断流程。

备份

为了备份MongoDB数据库,请检查MongoDB备份方法。