MongoDB是一个高性能可扩展基于文档的NoSQL数据库,高性能也须要在多个关键维度的配置,包括硬件、应用模式、模式设计、索引、磁盘I/O等。
存储引擎
WiredTiger是3.0之后的默认存储引擎,细粒度的并发控制和数据压缩提供了更高的性能和存储效率。3.0之前默认的MMAPv1也提升了性能。在MongoDB复制集中能够组合多钟存储引擎,各个实例实现不一样的应用需求。
硬件
MongoDB初衷是采用水平扩展构建集群,而不是价格更高的硬件升级。采用复制保证高可用,自动分片使数据均匀分布在各节点服务器上;in-memory计算提供更高的计算性能,该引擎只有企业版有
硬件配置要求
- 确保内存设置能知足性能需求:确保内存>索引容量+高频访问数据容量,经过storage.wiredTiger.engineConfig.cacheSizeGB或--wiredTigerCacheSizeGB进行设置。经过监控db.serverStatus()命令查看并评估
- 写操做负载高的应用采用SSD:SATA接口的SSD提供强大的顺序写性能,能提升MongoDB数据和jounal日志文件的写入速度;同时最为强大的是随机读取性能,这点符合MongoDB的数据访问vi 模式。部署采用RAID-10,比RAID-5/RAID-6减小不少限制,并提供更高性能。
- 存储引擎配置数据压缩和I/O-intensive worloads:WiredTiger存储引擎支持本地压缩,可以更好的使用多核新处理器资源。
- 为每一个MongoDB服务提供专用服务器:在单一服务器上安装多个MongoDB实例,系统会计算每一个实例合适的缓存,并为每一个实例分配默认的cache_size。经过storage.wiredTiger.engineConfig.cacheSizeGB参数调整。
- 使用多路查询路由:在不一样服务器上使用多个mongos,最好将mongos部署在应用服务器上。
- 利用多核心:WiredTiger存储引擎是多线程且能够充分利用CPU多核心。MMAPv1存储引擎由于其并发模型,因此并不要求更多的CPU核心。
- 开启NTP时间同步服务
- 禁用NUMA:MongoDB运行在NUMA系统上会致使操做问题,禁用NUMA须要配置mermory interleave policy
编写脚本/etc/init.d/pro-startMongo
...
# disable NUMA
sysctl -w vm.zone_reclaim_mode=0
启动时必须指定numactl方式
numactl --interleave=all <path> <options>
- 禁用THP:Transparent Huge Pages(THP)是Linux内存管理策略会占用大量的内存
编写脚本/etc/init.d/pro-startMongoDB,加入了前面禁用NUMA部分
# disable transparent hugespages
case $1 in
start)
if [ -d /sys/kernel/mm/transparent_hugepage ]; then
thp_path=/sys/kernel/mm/transparent_hugepage
elif [ -d /sys/kernel/mm/redhat_transparent_hugepage ]; then
thp_path=/sys/kernel/mm/redhat_transparent_hugepage
else
return 0
fi
echo 'never' > ${thp_path}/enabled
echo 'never' > ${thp_path}/defrag
re='^[0-1]+$'
if [[ $(cat ${thp_path}/khugepaged/defrag) =~ $re ]]
then
# RHEL 7
echo 0 > ${thp_path}/khugepaged/defrag
else
# RHEL 6
echo 'no' > ${thp_path}/khugepaged/defrag
fi
unset re
unset thp_path
# disable NUMA
sysctl -w vm.zone_reclaim_mode=0
;;
esac
更改脚本权限并加入自启动
sudo chmod 755 /etc/init.d/pro-startMongo
sudo chkconfig --add pro-startMongo
经过如下测试是否关闭了THP
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag
以下显示表示成功
always madvise [never]
- 设置ulimit:默认的ulimit设置过小,如下是推荐设置
-f (file size): unlimited
-t (cpu time): unlimited
-v (virtual memory): unlimited
-n (open files): 64000
-m (memory size): unlimited
-u (processes/threads): 64000
我是新建/etc/security/limits.d/99-mongodb-nproc.conf文件,加入以下配置:
mongod soft fsize unlimited
mongod hard fsize unlimited
mongod soft cpu unlimited
mongod hard cpu unlimited
mongod soft as unlimited
mongod hard as unlimited
mongod soft nofile 64000
mongod hard nofile 64000
mongod soft nproc 64000
mongod hard nproc 64000
应用、模式设计
- 模式设计:关联模式和嵌套模式,见下图,根据应用设计最合理的模式。
- 文档的key命名尽可能短,好比ParkingId能够改成pid。超过16MB,大文档尽可能使用GridFS
- 在集群环境下,避免scatter-gather查询。其实这依赖于sharding的方式和sharding key的选择,要尽可能知足大部分的业务需求。
- 读写分离设计:在读延迟容许范围内,进行读写分离是个不错的选择,能够大大下降主节点压力。
- 相似关系型数据库,一些优化建议:只查询和更新须要的字段,减小带宽;避免使用否认条件查询;合理使用覆盖索引并考虑最左前缀匹配原则;
硬盘I/O
- 预读设置:使用blockdev --setra <value>命令设置预读,单位是512B(扇区大小),很多于32kb,也不要设置太大,浪费I/O,设置大的预读有助于顺序读,具体的配置根据业务需求设定。
- 使用EXT4或者XFS文件系统。不要使用EXT3哦。
- 禁止Access Time设置。操做系统会维护文件最后的访问时间metadata,对于数据库意味着每次文件系统每访问一个页就会提交一个写操做,这将下降整个数据库的性能。
编辑/etc/fstab文件,指定noatime和nodiratime
/dev/sdb /data ext4 defaults,noatime,nodiratime 1 2
- 禁用Huges Pages虚拟内存页,MongoDB使用普通虚拟内存页性能更好,这个前面提到过。
- 使用RAID10,性能高于RAID-5或RAID-6
- swap设置:设置充足的swap空间防止OOM程序杀掉mongod进程,对于Linux下的MMAPv1存储引擎,不会使用swap空间,能够少许设置swap空间;Windows下的MMAPv1存储引擎须要设置swap空间;WiredTiger存储引擎,须要设置较大的swap空间。使用WiredTiger测试过程当中,发现对于大查询,没有足够的swap空间甚至会报错。在/etc/sysctl.conf设置vm.swappiness为0,尽可能使用内存。swap分区尽量大些,如下是一些建议。测试过程当中是128G内存,我设置交换分区内存大小也是128G。
- 日志和数据文件分开存储,日志存储在普通SAS盘上,数据存储在SSD上。数据库的读通常都是随机读,SSD在随机读性能上表现很是好;日志文件主要是顺序写,速度自己较高,而SSD在顺序读写上的表现很是糟糕,并且比普通SATA性能还要低。Mongodb的日志有journal和syslog,journal日志只能放在dbPath下面的journal目录中,而系统日志能够指定日志路径。journal能够挂载个SATA硬盘设备。这样作到日志和数据分离。
- 多路径设置:设置storage.wiredTiger.engineConfig.directoryForIndexes使索引和数据分离,设置该参数为true后,会在dbPath下面创建一个index目录,在index目录下挂载一个硬盘设备,使索引和数据作到分离。设置directoryPerDB每一个数据库不一样目录,对于每一个目录最好挂载到不一样的硬盘设备上。
- 压缩:WiredTiger提供snappy和zlib两种数据压缩方式。snappy提供压缩比低可是性能损耗低,zlib压缩比高但性能损耗较高,经过storage.wiredTiger.collectionConfig.blockCompressor参数设置