优化Linux以提升MongoDB性能
除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机制的操作就完成了。