MongoDB Replica Set使用几点总结
本文会涉及到MongoDB副本集的初始化,读写性能,scala driver,简单运维等内容。
副本集初始化
在各个节点上replica set进程,
nohup numactl --interleave=all ./mongod --dbpath /home/mongodb/data/ --logpath /home/mongodb/mongodb-linux-x86_64-2.4.7/run.log --port 8017 --rest --journal --replSet smartq --oplogSize 500 --profile=1 --slowms=5 --fork &我的启动中,开启了rest接口,journal log,设置了oplog size大小500M(因为之后再修改oplog大小会比较麻烦),还开启了慢查询profile,如果有不熟悉这三块日志的,可以参考下面的简单描述:
- Journal日志。Journal日志通过预写式的redo日志为MongoDB增加了额外的可靠性,开启该功能时,数据的更新会先写入Journal日志,定期提交,然后在真实数据上执行这些变更,如果服务器安全关闭,日志会被清除在服务器启动时,如果存在Journal日志,则会执行提交.启动Journal功能只需要在启动mongod时指定-journal参数即可,这样,系统的Journal信息都会被放到数据库目录(默认是/data/db)的journal文件夹中
- oplog日志。MongoDB的高可复用策略中有一种叫做Replica Sets,Replica Sets复制过程中一个服务器充当主服务器,而一个或多个服务器充当从服务器,主服务器将更新写入一个本地的collection中,这个collection记录着发生在主服务器的更新操作,并将这些操作分发到从服务器上。这个日志是一个capped Collection,且有大小之分,所以最好在启动mongod服务时配置好大小(单位:MB). mongd -oplogsize=1024
- 慢查询日志。慢查询日志记录了执行时间超过所设定时间阈值的操作语句,慢查询日志对于发现性能有问题的语句很有帮助,建议开启此功能经常分析该日志的内容.要配置这个功能值需要在mongod启动时指定profile参数即可。Eg.将超过5s的操作记录都记录下来 mongod --profile=1 --slowms=5 运行一段时间后,可以通过查看db.system.profile 这个collection来获取慢日志信息
numactl --interleave=all这块设置。NUMA和UMA(SMP)多核CPU架构的不同实现方式,推荐阅读下Introduction to Parallel Computing的章节内容。如果不设置这个参数,进入mongod后会有相应提示,可能带来的问题可以参考记一次MongoDB性能问题,附原理解析这篇文章。
起了各个节点后,连接到某一台mongod上,进行副本集初始化工作:
var config = { _id: "smartq", members: [ { _id:0, host:"host0-ip:8017" }, { _id:1, host:"host1-ip:8017" }, { _id:2, host:"host2-ip:8017" } ] } rs.initiate(config)输入rs.status()可以查看primary和secondary节点情况,刚初始化的时候节点的状态会经历一些变化,之后选举出primary。更多指令可以参考 rs.help() 。更多细节可以参考文章mongodb副本集架构搭建
读写性能
我的副本集的写性能,在java driver环境下,差不多是1W-2W+ 行每秒,吞吐量大约2M+ 每秒。写只能在primary节点上进行。
我的副本集的读性能,在不带索引的情况下,DBCursor的扫描速度是4K~7K 行 每秒。输入一个查询,执行后,返回一个DBCursor是很快的,但是游标的顺序fetch行数还是比较慢的。我尝试了DBCursor提供的一些方式(我使用的是mongo-java-driver-2.10.1的包),对比了下以下几种获取速度,
rs = coll.find().sort(new BasicDBObject("_id", 1)).toArray(); rs = coll.find().batchSize(100).limit(l).toArray(); rs = coll.find().toArray(); // toArray()开销 Iterator it = coll.find().iterator(); // little faster than toArray() while (it.hasNext()) { it.next(); }刚开始一直使用toArray()的方式把DBCursor能指向的数据全部吐到内存里来,但其实toArray()的开销稍稍大于返回一个iterator之后逐个扫描一次。而基于_id字段进行排序之后再toArray(),带来的额外开销很少,侧面说明_id字段因为有索引,做排序很快很方便,值得好好利用。batchSize这个设置,我尝试设置了100,1000,感受是对于几万到几十万的数据吞吐没有多大影响。
总结是读性能在速度上还是需要索引支撑,且在能承受最终一致性的前提下,将读分布到secondary上缓解。
Scala Driver
尝试了下Scala Driver来进行读性能的测试,速度和java driver是一致的,而scala driver本身也是对java driver的简单封装,且目前支持的api也不全。
Scala Driver项目叫Casbah,是10gen官方的Toolkit。在build.sbt下的配置如下:
name := "hi-scala" organization := "xx.xxx.xxx" version := "0.0.1-SNAPSHOT" scalaVersion := "2.9.3" libraryDependencies ++= Seq( "org.mongodb" %% "casbah" % "2.6.3" )简单使用:
import com.mongodb.casbah.Imports._ object CasbahTest extends Logging { def main(args: Array[String]): Unit = { val mongoClient = MongoClient("host-ip", 8017) val db = mongoClient("db") val coll = db("collection") val start = System.currentTimeMillis() val rs = coll.find() // for (doc <- rs) { // doc // } logInfo("Result: " + rs.size) // no toArray() val end = System.currentTimeMillis() logInfo("Time: " + (end-start)) } }更多内容参看 Casbah Tutorial
Copy Collection
在同个db下拷贝collection似乎没有快速的方法,那就写简单的js,进行insert操作,
var i = 0; while(i < 10000) { var cname = 'copy' + i; db.copy1.find().forEach( function(x){ db.getCollection(cname).insert(x); }); i++ }然后让mongod在后台执行,效率也很慢,
nohup ./mongo localhost:8017/hdfs ../../jscript/copy_collection.js &执行一段时间后,secondary的status可能会显示RECOVERING,原因是oplog记录的内容过多,primary的oplog可能已经重新刷过一次了,导致secondary与primary脱节,无法再持续进行本身的同步数据的操作。解决方法是把secondary kill掉,删掉data数据,重新起mongod加入副本集。这利用的是副本集同步机制中的初始化同步,即对于新的没有数据的member,拷贝现有副本集内某个member的整份数据,整个过程流程为先clone数据,然后apply all changes,最后建索引。启动之后,secondary会出于STARTUP状态,开始比较快速地进行数据的同步,这里比较快也就是上百M每秒的样子。
(全文完)
最后更新:2017-04-03 14:54:23
上一篇:
Javax.swing中JFrame.getContentPane().add(pane)与JFrame.add(pane)有何区别?
下一篇:
编程的视频
《生活大爆炸》里那些高智商游戏
Oracle 12c多租户特性详解:从Schema到PDB的变化与隔离
MyEclipse中add jars和add external jars的区别带来的svn checkout的问题
DedeCMS后台经常无法加载编辑器
阿里云移动云Apsara Mobile重磅发布 推出Cloud Native App全新研发范式
1.基本常用命令
2017年英特尔在其数据中心业务和AI方面下大注
大型项目使用Automake/Autoconf完成编译配置(1)——提纲挈领
Oracle中的number类型
Cocos2d-x实例:设置背景音乐与音效- AppDelegate实现