MongoDB系统性能调优(持续更新)

5 篇文章 0 订阅
5 篇文章 0 订阅
  • cache_size

    指定WT存储引擎内部cache的内存用量上限。

    需要注意的是,仅作用于WiredTiger cache,而非mongod进程的内存用量上限。MongoDB同时使用WT cache和文件系统cache,往往mongod进程的内存用量高于该值。cache_size相对于物理内存总量不要设置的太满,需要留有一定内存为操作系统所用,否则有OOM潜在风险。

    默认情况下,cache_used超过80%将触发eviction,如果物理内存充足,建议设置足够大的cache_size,以加载全部数据,避免不必要的eviction。

    个人经验值 cache_size = (data + index) / 0.8

    cache_size支持在不停服的情况下动态调整,比如将cache_size设置为80GB,执行如下命令:

      db.adminCommand({setParameter: 1, wiredTigerEngineRuntimeConfig: "cache_size=80G"})
    
  • eviction

    cache_used是很关键的指标,超过80%将触发eviction,类似LRU算法,淘汰冷数据,避免cache用量持续增长。

    一个健康的MongoDB服务,其cache_used应该不超过80%,即使超过,能在短时间内降到80%也是没问题的。如果长时间高于80%则需要重视起来,因为cache_used过高会导致数据库性能下降,体现在慢操作(读写请求耗时长)、qr/qw高(读写请求排队)等方面。所以我们要极力保证cache_used在一个健康的范围内。

    eviction包括很多参数,比如eviction_triggereviction_targeteviction_dirty_target等,指定在什么条件下触发和停止cache eviction,这里,我更关心的是eviction线程数量。

    对于eviction线程,MongoDB默认配置是eviction=(threads_min=1,threads_max=4),根据cache使用情况,创建1-4个eviction线程去淘汰冷数据。

    如果cache体积较大 数据量大、读写频繁,那么需要更多的eviction线程。

    如果调高threads_max仍然无法降低cache_used,建议设置更大的cache_size

    动态调整配置:

      db.adminCommand({setParameter: 1, wiredTigerEngineRuntimeConfig: "eviction=(threads_min=1,threads_max=8)"})
    
  • wiredTigerConcurrentWriteTransactions

    指定最大并发写事务数。

    对于写频繁的服务,通过mongostat查看运行状态,如果qw持续较高、aw经常是128(默认值),说明写请求发生排队,同时WT无法提供更高的并发写。

    此时观察CPU负载,如果负载不高(相对于核数,CPU未充分利用),尝试调高此参数,能够一定程度上缓解问题,即使出现qw高,往往也是短暂的,可能下一秒恢复正常。

    调高此参数,相当于压榨CPU,CPU负载较之前会有一定增加,如果负载在合理范围内,可以接受;负载过高的话,建议扩容。

    建议根据实际情况动态调整,并持续观察效果,找到一个合理的值。

    查看当前配置:

      db.adminCommand({getParameter: 1, wiredTigerConcurrentWriteTransactions: 1})
      or
      db.adminCommand({getParameter: '*'}).wiredTigerConcurrentWriteTransactions
    

    动态调整配置:

      db.adminCommand({setParameter: 1, wiredTigerConcurrentWriteTransactions: 512})

tcmalloc
tcmalloc提供了释放速度字段来调节缓存的释放速度tcmallocReleaseRate,官方建议是0-10,0表示永不释放,默认是1。实际为0~1000

db.adminCommand({setParameter:1, tcmallocReleaseRate:500})

释放太过激进的内存占用,配合tcmallocReleaseRate使用。这2个配置可以让MongoDB尽快释放内存。

db.adminCommand({setParameter:1,tcmallocAggressiveMemoryDecommit:1})

读写并发设置
wiredTigerConcurrentReadTransactions
允许并发读取的最大值,默认128。

db.adminCommand( { setParameter: 1, wiredTigerConcurrentReadTransactions: <num> } )

wiredTigerConcurrentWriteTransactions
允许并发写入的最大值,默认128。

db.adminCommand( { setParameter: 1, wiredTigerConcurrentWriteTransactions: <num> } )

Checkpoint刷盘
db.adminCommand({setParameter: 1, wiredTigerEngineRuntimeConfig:`checkpoint=(wait=30,log_size=1GB)`})

环境变量设置

WIREDTIGER_CONFIG=checkpoint=(wait=30,log_size=1GB)

如果写入数据还没到Evict的比例,只能通过checkpoint定时刷盘。通过调整checkpoint的wait时间,即时把脏数据写入磁盘,避免用户线程参与evict数据。减少checkpoint的wait时间可以提高磁盘IO的利用率

IO优化

网络压缩

networkMessageCompressors是MongoDB配置中的一个关键参数,用于启用网络数据传输时的压缩功能。通过设置这个参数,MongoDB可以在数据传输过程中对消息进行压缩,减少数据在网络上传输的大小,从而提高网络I/O性能。

mongod.conf或启动mongo实例时的配置文件中,你可以指定networkMessageCompressors参数来指定要使用的压缩算法。例如,你可以将其设置为zlib表示使用zlib压缩算法。除了zlib之外,MongoDB还支持snappyzstd等压缩算法。

示例配置:

net: 
  compression: 
    compressors: zlib

通过启用数据压缩,MongoDB可以减少数据在网络传输时的大小,降低网络带宽的消耗,并且能够提高MongoDB集群在网络I/O方面的性能表现

除MongoDB本身的配置外,操作系统的配置也会影响数据库的性能

实现所有MongoDB Server的时间同步
减少时间戳记录
关闭磁盘预读值(read-ahead)
关闭内存管理
禁用非同意内存访问(non-uniform memory access)


实现所有MongoDB Server的时间同步
集群是由多台Server 配置而成的,不能存在时间不同步的情况。因此,我们通过操作系统的NTP 服务来实现所有MongoDB Server的时间同步。

了解时间同步(NTP )
NTP ( network time protocol )是用来对网络中的Server进行时间同步的协议。在局域网中,时间同步的精确度可达到0.1ms;在互联网中,时间同步的精确度可达到150ms。因此,对时间同步有要求的系统,都可以使用NTP来实现。

我们先对操作系统的时间有一个初步的了解:

软件时间是指, Linux 操作系统从1970-01-01到当下计算出来的总秒数。
硬件时间是指,以BIOS内部的时间为主要的时间依据。
如果BIOS内部芯片出现问题,则会造成BIOS时间与标准时间不一致。
在使用NTP服务时,不允许Server与同步源之间的误差时间超过1000s,因此需要先手动将时间与同步源同步,再设定NTP服务。
设定时间同步有两种方式: -种方式是手动命令设定时间同步,另一种方式是通过服务自动实行时间同步。

手动设定时间同步
手动设定时间同步是通过命令来指定同步源的IP地址或域名。这种同步是单次同步。手动设定时间同步的格式如下:

手动与某台Server (以IP地址“10.10.10.10" 为范例)同步

 ntpdate 10.10.10.10
手动与中国公共NTP服务器同步

ntpdate cn.pool.ntp.org
通过服务自动实现时间同步
通过NTP服务可实现实时的时间自动同步。需在服务文件中设定同步源的IP地址。

通过NTP的文件ntp.conf来设定想要与哪台Server同步。
编辑ntp文件,命令如下:

vim /etc/ntp.conf
文件内容如下:

#server 0.centos.pool.ntp.org
#server 1.centos.pool.ntp.org
#server 2.centos.pool.ntp.org
#允许10.10.10.10连接本NTP服务器
restrict 10.10.10.10
#设定时间同步来源主机10.10.10.10
server 10.10.10.10

当此台主机为NTP服务器时restrct用来管理哪些主机可以连到此比台服务器实现时间同步,server用来设定从哪台NTP服务器同步时间。

设定完NTP服务后,启动NTP服务,命令如下:
systemctl start ntpd
查看NTP服务是否正常运行,命令如下:
systemctl stalus ntpd
执行的结果如下:

ntpd.service - Network Time Service
Loaded : loaded (usrlib/systemdisystemintpd .service ; disabled )
Active : active (running) since Sat 2018-03-24 11:02:57 CST ;2 weeks 5days ago
Process : 46232 Execstar-/usr/sbin/ntped - u ntp:ntp $OPTIONS ( code=exited, status=0/SUCCESS ) Main PID: 46232 ( ntpd )
查看使用哪台Server进行时间同步。
ntpstat
ntpq -P
可在操作系统中使用"date" 命令查看同步之后的时间。

减少时间戳记录
在默认情况下,Linux文件系统文件在被访问,创建、修改时都会记录时间戳,例如文件的创立时间、最后一次修改时间、最近一一次访问时间等。

在系统运行时,如果大量存取磁盘文件,则会使设备-直处于忙碌的状态,从而影响性能。如果能减少一些磁盘存取的动作(如减少时间戳的记录),则可以降低磁盘I/O的负载。

时间戳的选项
时间戳包含以下几个选项。

atime: 记录文件系统中每个文件的最后访问时间。即使只读取数据,时间戳也会被写入硬盘。
noatime:不记录任何文件的访问时间。但这样可能会造成有前后访问时间关系的程序失常。
relatime:在以下两种情况记录时间戳。
如果文件的最后访问时间早于最后更改时间,则记录文件的最后访问时间。

如果访问时间超过定义的间隔(RHEL,默认为1天),则记录文件的最后访问时间

设定时间戳记录
设定时间戳记录,需在/etc/fstab 这个文件中修改系统参数。

找到MongoDB准备放置数据的目录
本书的范例将数据放在/data目录下,所以将/data 目录进行修改,将其设为noatime.

注意:①MongoDB不一定要安装在/data这个目录下,这个目录默认是不存在的:②也不一定要为这个目录挂载一个单独的卷,这并非必要的配置。

编辑/etc/fstab文件
命令如下:

vim /etc/fstab
修改文件内容如下:

/dev/sda1 /data  xfs  defaults,noatime  00
修改完毕后需要重新挂载,才能使设置生效
mount -o remount/
在进行建些提置时需要特别小心,图为是时破盘做操作,如果推作错遇到 可能导致整台Senver 死机

关闭磁盘预读功能
磁盘预读是指Linux内核对系统文件进行预先读取,即将文件从磁盘预先读到内存缓存中。因为读取内存的速度比读取磁盘的速度快很多,所以,磁盘预读不仅可以提高文件读取的效率,也可以减少磁盘的访问量及I/0的等待时间。

因为MongoDB不一定是按照因定的顺序将数据存进磁盘、而里大多就时候MonpoDB不会按照磁盘顺序来读取数据。所以磁盘预读的文件与MongoDB直接读取磁盘的文件不同。因此,磁盘预读对MongoDB并没有真正的帮助,反而可能影响了性能。

如果磁盘预读值被设定为0,则表示不使用磁盘预读功能。

手动关闭
关闭磁盘预读有两种方法:

手动关闭
让系统自动关闭
查看存放数据目录所挂载的磁盘分区
不论是手动设定还是让系统自动设定,都需要提前知道MongoDB数据所在目录挂权的磁盘分区。

我们存放数据的目录为/dalta,使用命令可以知道/data挂载的磁盘分区为/dev/mapper/centos-home。具体方法如下。

查看存放数据目录所挂载的磁盘分区

df -h
手动关闭磁盘预读功能
使用以下命令查看磁盘预读大小:
/sbin/blockdev --getra ldev/mapper/centos-home
关闭磁盘预读命令(设定为0),命令如下:
/sbin/blockdev -- setra 0/dev/mapper/centos-home
若想确定blockdev的绝对路径,可以使用“which blockdev"命令来查看。

一般来说, 都是在“/usr/sbi/blockdev" 路径下,而“/usr/sbin" 是挂载在“/usr” 下,因此使用 “/usr/sbin/blockdev” 与“/sbin/blockdev" 是一一样的。

让系统自动关闭
也可以设定排程,让系统自动关闭磁盘预读。具体方法如下。

在本地初始化的程序中加入修改磁盘预读为0的命令。
编辑本地初始程序文件,具体命令如下:

vim /etc/rc.local
/usr/sbin/blockdev --setra 0/dev/mapper/centos-home
设定/etc/rc.d/rc.local的执行权限( "a+x"表示全部角色都可以执行)
chmod a+x /etc/rc.d/rc.local
查看/etc/rc.d/rc.local的权限状态:
/etc/rc.d/rc.local


其中,第1个字母"d"代表文件类型。然后是三组“rwx” (r代表读: w代表写; x代表可执行)

第1组"rwx"代表的是所属者的权限。
第2组"rwx" 代表的是同群组成员的权限。
第3组“rwx"代表的是其他人的权限。
如果没有某个权限,则用“-”代替。

上面代码中“-rwxr-xr-x" 表示:

第1个字母为“-” ,表示这不是文件类型的文件。
所属者的权限是“rwx" ,可以读写/执行。
同群组成员的权限是 “r-x"可以读/执行,没有写权限(“写”权限用“-”代替了)。
其他人的权限是“r-x",可以读/执行。
如将权限设定为“a+x", 则表示全部角色都可执行。

执行这个本地初始化的程序有以下两种做法:
将本地初始化的程序作为服务启动。

启动服务命令:

systemctl start rc-local
查看服务状态命令:

systemctl status rc-local
查看到的结果如下:

rc-local.service -letc/rc.drc.local Compatibility
Loaded : loaded (usilib/systemnd/system/rc local.service ;static )_ 成功启动  Active Lactive ( exited) since Fni 2017-09 -29 10:53:36 CST ;7s ago
Process:15803 ExecStart/etclrc.dIrc localstart (code=exited,ited.status=0/SUCCESS)
建立排程来定时执行命令。

编辑排程文件:

vim /etc/crontab
文件内容如下:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MALTO=root

00 01 * * * root /etc/rc.d/rc.local
完成设定后,可以使用以下命令来查看一下磁盘预读的大小:

/sbin/blockdev --getra /dev/mapper/centos-home
查询到的结果如下:

0
关闭内存管理
在Linux操作系统中,内存是由CPU的内存管理单元来管理的。操作系统使用映像表(即“内存页条目")来记录虚拟内存页及物理内存页的对应关系。如果内存页较小,则需要较大的映像表来记录对应关系:如果内存页较大,则可以用较小的映像表来记录对应关系。

了解标准大页和透明大页
在了解内存页与映射表的关系后,将继续介绍管理内存页的机制,分为两种:大页(Huge Pages, HP)和透明大页( Transparent Huge Pages, THP )。

大页(Huge Pages )
大页就是一种很大的内存页。使用它可以减少映射表的大小,以提高CPU检索内存映射表的命中率。

透明大页(THP )
在系统运行时,THP会动态地调整内存,且配置后不需要重启操作系统即可生效( MongoDB进程需要重启)。为动态分配,在系统运行时内存分配会有延迟的情况。

透明大页是以Centos/RedHat6.0开始使用的,Centos7.0版本开始为默认启用对数据库而言,访问内存并非连续的,因此启用透明大页并没有实际上的效益,反而会造成性能上的影响,因此需要将其英闭

在CentOS 7.0中配置THP
暂时配置
在执行命令之后,可以手工将THP调整为关闭状态,但在重新启动后会还原设定。

禁用THP,命令如下:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
只禁用THP的碎片整理功能,命令如下:
cho never > sys/kernel/mm/transparent_hugepage/defrag
永久配置
创建新的Profile文件,命令如下:
 sudo mkdir /etc/tuned/no-thp
编辑tuned.conf文件,命令如下:
vim /etc/tuned/ho-thp/tuned.conf
文件内容如下:

[mian]
include=virtual-guest

[vm]
transparent_hugepages_never
启动profile,命令如下:

sudo tuned-adm profile no-thp
检查结果是否关闭THP
查询THP的状态,命令如下:
cat /sys/kernel/mm/transparent_hugepage/enabld
查询THP碎片整理的状态,命令如下:
cat /sys/kernel/mm/transparent_hugepage/defrag
禁用“非统一内存访问”( NUMA )
首先先来了解一下什么是非统 -内存访问 ( non-uniform memory access ),介绍它在硬件资源使用上有什么好处,并告诉大家为什么要禁用NUMA机制。

NUMA 的工作原理
NUMA是当服务器为多核时,在内存使用上的设计方式。此设计会将CPU与内存平均分配在多个逻辑节点(node)上。

每个节点上均有独立的CPU与内存,可以解决硬件资源扩展问题。当程序或进程在某节点上使用本地内存时会有比较好的性能,但使用其他节点的内存时性能会比较差。

节点的数量取决于CPU的数量-般来说通常为两个节点,最多不超过4个。如CPU为16核、内存32G、物理CPU为2,则会有两个节点(node0、node1),每个节点会有8核16GB内存。

查看硬件的NUMA分配节点资源的情况
可使用以下命令查看NUMA机制分配节点资源分配的情况:

numactl -hardware
禁用NUMA机制
在内存大且多CPU的环境下,采用NUMA机制确实能提升不少性能。但是对于内存需求较大的数据库来说,若本地节点的内存用尽,则不会使用其他节点的内存,而是默认优先将内存数据置换到磁盘中的swap空间,井回收本地节点的内存。此换动作会造成性能变差。因此,数据库若是在NUMA机制上运行,则在硬件的内存还没完全用尽时就会使用到swap置换,从而造成性能变差。

解决此问题需要两个步骤:首先禁用内存回收的功能,然后设定MongoDB可以使用全部节点的内存。

禁用内存回收的功能,命令如下:
echo 0|sudo tee/proc/sys/vm/zone_reclaim_mode

sudo sysctl -w vm.zone_reclaim_mode=0
使用numactl启动MongoDB服务,使得MongoDB可以使用全部节点的内存,命令如下:
numactl --interleave=all mongod -f /etc/mongod.conf
至此,禁用NUMA机制的操作就完成了。

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值