mongodb快速均衡导入数据
需求环境:
有一个项目需要将mongodb sharding从2.6升级到3.0 并使用wt引擎,其中2.6环境很多collectiong开启了Sharding,且数据量很大.
选择mongodump,mongorestore方式
问题:
在restore步骤出现了2个问题
1)大数量数据导入缓慢时间花费长
2)chunks分配不均匀,需要很长时间做balance.
分析原因:
针对以上问题我对mongodb的进行了初步的学习和研究,同时也查看了一些优秀的博客,发现部分原因:
mongodb导入大量数据,会涉及到chunks的分裂和新chunk文件分配这个过程耗费时间,并且自动均衡策略不能均匀分配chunks到每个shard这在数据导入时也会引起不同的shard io使用差距大,无法合理使用整个集群的io。
解决办法:
可以提前预先分配chunks并且均匀的移动到每个shard,针对这个场景我写了一个简单的python脚本实现
#! /usr/bin/python #input basic info ns = "crawler.logsData" shard_key = "_id" shards= ["shard01","shard02","shard03","shard04"] min_key = 237223617 max_key = 264171274 avg_doc_size = 2340 #byte chunk_size = 64*1024*1024 #byte 64MB fragment = 0.9 def split_chunk(ns,shard_key,shards,min_key,max_key,avg_doc_size,chunk_size,fragment ): fname='./'+ns+'.js' f=open(fname,'a') f.write("db = db.getSiblingDB('admin')"+'\n') docs_per_chunk = int(chunk_size*fragment/avg_doc_size) key_value=min_key+docs_per_chunk shard_counter = 0 shardlen = len(shards) while key_value < max_key: str_split_chunk=('db.runCommand( { split : "%s", middle : {%s:%d} } )')% (ns,shard_key,key_value) str_move_chunk=('db.runCommand({moveChunk: "%s", find: {%s:%d}, to: "%s"})')%(ns,shard_key,key_value,shards[shard_counter]) shard_counter = shard_counter + 1 if shard_counter == shardlen: shard_counter = 0 key_value=key_value+docs_per_chunk f.write(str_split_chunk+'\n') f.write(str_move_chunk+'\n') # print(str_split_chunk) # print(str_move_chunk) f.closed split_chunk(ns,shard_key,shards,min_key,max_key,avg_doc_size,chunk_size,fragment)
step1
编辑以上脚本填写参数运行 会生成一个分配和move chunks的js文件文件名是crawler.logsData.js
step2
使用以下命令运行可以实现chunks的均匀预分配
time mongo admin -u username -p'passwd' < /home/user/crawler.logsData.js
step3
运行以下命令实现collection crawler.logsData的数据导入
time mongorestore --host *** --port ** --db crawler --collection logsData -u username -p "passwd" /home/user/crawler/logsData.bson
注意:
step1&2可以预先处理不必等到迁移时,这样分配chunks和 chunks balance的时间就可以在实际迁移时节约出来了,这样做还可减少导入数据发生chunk split.
以下是我的测试结果 mongorestore 时间花费 26GB数据 14分钟
发散:
针对以上测试,我们进一步思考,是否可以把这个方式使用到维护方面,如果我们预先知道collection的每月的数据增长量,那么就可以提前为下一个月的数据做chunks的预分配,
这样就不必使用mongodb balance因为在写入数据时就已经按照我们的规划均匀写入数据,这样可以均衡sharding的io使用率,提高整个sharding写入效率.