MongoDB Cluster分片集群问题集合

由于数据量不断增加,以前用的是单节点的MongoDB数据库已经无法满足日益增长的数据存储要求。无论是硬盘存储空间还是查询速度都出现了瓶颈,因此我决定组建一个MongoDB分片集群。具体的组建方案可以参考《从零搭建MongoDB Cluster分片集群》。搭建完成以后,就需要把单台节点的数据导入新的MongoDB集群中。MongoDB数据迁移有很多工具,其中包括mongodump、mongoexport、mongoimport。由于数据迁移需要时间,并且目前还无法确定MongoDB集群的稳定性,同时还要保证线上任务的正常工作。因此,本次数据迁移的方式是自己编写一个脚本,从旧库中读循环读出一批数据然后在写入新的集群中。在数据迁移的过程中,的确发现了很多问题。

集群数据写入缓慢

数据迁移脚本启动一段时间以后,写入速度非常缓慢,平均每分钟插入10条数据。这个问题很明显是集群配置出了问题。此时使用以下命令可以查看mongodb数据库当前正在进行哪些操作和这些操作所使用的时间。

./mongotop --port 27017

运行该命令后可以查看到,由于MongoDB进行某些非常耗时的操作而导致性能下降,这也导致数据写入数据缓慢。然而,新搭建的MongoDB集群并没有连接到线上业务,只有单纯的数据写入访问。分析得出,这很可能是由于chunksize设置得过小(默认值为64MB)。当大批量地写入数据时,MongoDB会频繁地进行数据块切分和移动等操作,导致整个集群的性能下降。需要查看chunksize当前值,需要连接mongos服务并运行以下命令:

mongo localhost:27016
use config
db.settings.find()

可以使用以下命令修改chunksize的值:

mongo localhost:27016
use config
db.settings.insertOne( { _id:"chunksize", value: 512 } )
#或者
#db.settings.save( { _id:"chunksize", value: 512 } )

修改完成以后,数据插入的速度明显加快,达到平均每分钟写入约40,000条数据左右。以下是chunksize属性对于MongoDB集群的影响:
chunksize

相关参考文档:Modify Chunk Size in a Sharded Cluster

MongoDB数据库异常退出

在迁移数据的过程中遇到的另外一个问题就是在运行了一段时间以后出现主节点无故退出,查看日志也没有发现报错情况。最后查看系统日志发现是由于内存不足导致MongoDB进程退出。可以使用以下命令查看Linux系统日志:

dmesg -T | egrep -i -B100 “killed process”

本问题的主要原因是在集群搭建初期,在分片配置文件中并没有设置cacheSizeGB参数。cacheSizeGB默认值为物理内存的50%,由于我采用的是在一台服务器上启动3个MongoDB进程。因此理论上内存使用率会达到物理内存的150%,最终导致系统内存不足。解决方案就是将cacheSizeGB设置为合理的数值。例如当单台服务器为32G内存时,如果要同时运行3个MongoDB进程,将cacheSizeGB设置为8GB左右问题不大。

MongoDB集群数据量与原数据库不同

经过批量数据迁移,使用count进行数据比对过程中发现新MongoDB集群中的数据总数和旧数据库中的不一致,而且相差甚大。经查阅官方文档,判断分片中可能存在孤立文档(Orphaned documents)。孤立文档主要会在MongoDB数据切分的过程中产生,特别是当进行数据切分并迁移到不同分片的过程中出现MongoDB进程异常退出,会产生大量的孤立文档。MongoDB 4.4以后,可以使用cleanupOrphaned清理。

迁移块遗留文件导致磁盘满

由于分片集群均衡器会自动迁移数据块,从而保证每一个分片上的数据块大小均衡。当参数sharding.archiveMovedChunks设置为true时,分片会将迁移块的临时文件备份到数据库文件夹的moveChunk文件夹。长时间运行分片集群服务器以后,该文件夹的备份数据会填满整个磁盘,最终导致数据库崩溃。通过在分片节点上运行以下命令可以查看分片是否开启了迁移块存档设置:

use admin;
db.runCommand("getCmdLineOpts"); #查看启动配置参数
db.adminCommand({getParameter:"*"}) #查看配置信息

在分片集群节点上运行以下命令,查看该分片的副本集中每个节点的状态:

rs.status()

当迁移成功以后,可以删除moveChunk文件夹从而节约空间。通过在mongos上运行以下命令查看迁移是否在进行:

sh.status() #查看最近的迁移状态
sh.isBalancerRunning() #查看是否在迁移中

解决方案:
在数据节点配置文件中将archiveMovedChunks参数设置为false。

参考文档:
moveChunk文件夹
sh.status
Data Partitioning with Chunks
cleanupOrphaned
MongoDB分片相关问题

Captain QR Code

扫码联系船长

发表回复

您的电子邮箱地址不会被公开。