坑爹的mongodb异步驱动(mongodb-async-driver)
来源:互联网 发布:mysql终端查看数据库 编辑:程序博客网 时间:2024/05/20 21:23
开始:
一直以来mongodb的同步驱动mongo-java-driver,为了提高性能,WriteConcern设置成了NORMAL模式(3.0以后更名为UNACKNOWLEGE),这意味着驱动把数据写入socket就立马返回成功,mongodb端有任何异常是捕获不到的,也有人称之为“fire and forget”。那么问题来了:数据可靠性为0,鬼知道数据有没有存储成功!
为了提高数据可靠性,其实也很简单:调高WriteConcern的级别就行。具体什么级别,根据业务确定。下面给出WriteConcern的定义:
WriteConcern的定义:
Ø WriteConcern.NORMAL:仅抛出网络错误异常,没有服务器错误异常
Ø WriteConcern.SAFE:抛出网络错误异常、服务器错误异常;并等待服务器完成写操作。
Ø WriteConcern.MAJORITY: 抛出网络错误异常、服务器错误异常;并等待集群中一半以上服务器完成写操作。
Ø WriteConcern.FSYNC_SAFE:抛出网络错误异常、服务器错误异常;写操作等待服务器将数据刷新到磁盘。
Ø WriteConcern.JOURNAL_SAFE:抛出网络错误异常、服务器错误异常;写操作等待服务器提交到磁盘的日志文件。
Ø WriteConcern.REPLICAS_SAFE:抛出网络错误异常、服务器错误异常;等待至少2台服务器完成写操作。
于是:
我将WriteConcern级别调成SAFE模式:
该模式下,数据会写到内存并返回,每隔100ms将数据刷到journal日志,宕机重启时会优先从journal日志恢复数据。理论上,SAFE模式下最多会丢失100ms的数据。
问题来了:
改完WriteConcern,一测性能,下降了1/3左右,这怎么可以忍!!!然后就开始解决性能问题,出发点是,通过其它方法提高性能,一通查资料,就发现了mongodb的异步驱动(心里美滋滋,浪里个浪~~~)。心想异步坑定快啊(允许丢失极少数据,但是需要知道丢了哪个。而之前的NORMAL模式做不到),就算出现异常,我可以稍后捕获。于是搞了一个新组合:WriteConcern.SAFE+mongodb-async-driver。理论上,不管从哪个角度考虑,新组合都优于原有的组合:WriteConcern.NORMAL+mongo-java-driver。
但是:
对,‘但是’来了。测试中发现新组合确实快,但是数据丢了,扔给我一个找不到答案的异常,,,
描述:
单线程循环插入1000条数据,结果只有600左右插入成功,异常如下:
com.mongodb.MongoWaitQueueFullException: Too many operations are already waiting for a server. Max number of operations (maxWaitQueueSize) of 500 has been exceeded.
猜测:
每条插入命令,都会占用一个线程,导致等待获取connection的线程超过了限制(默认500)。
疑问:
为什么有那么多线程?如果是每个插入操作都开启一个线程,那根本没法实际应用,难道没有一种管控策略吗?
测试代码:
public static ExecutorService executorService = Executors.newFixedThreadPool(10);public static CountDownLatch gloabLatch = new CountDownLatch(1);public static volatile long id = 0;public static void main(String[] args) {// To directly connect to the default server localhost on port 27017MongoClient mongoClient = null;try {mongoClient = MongoClients.create();//获取数据库MongoDatabase database = mongoClient.getDatabase("mydb");MongoCollection<Document> col = database.getCollection("mycollection");TestAsyncDriver test = new TestAsyncDriver();test.testInsert(col);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** 控制线程* @param col*/private void testInsert(MongoCollection<Document> col) {int insertNum = 1000;Runnable runner = new InsertThread(col, insertNum); long startTime = System.currentTimeMillis(); System.out.println("开始时间:" + (startTime) + "ms"); executorService.execute(runner); while(true) { if (id>=(insertNum-1)) { executorService.shutdownNow(); break; } } System.out.println("id=" + id); long endTime = System.currentTimeMillis(); System.out.println("所有回调完成耗时:" + (endTime - startTime) + "ms");}/*** 插入线程* @author huqi**/class InsertThread implements Runnable { private final MongoCollection<Document> col; private int insertNum; public InsertThread(MongoCollection<Document> col, int insertNum) { this.col = col; this.insertNum = insertNum; } private synchronized long addId() { return id++; } public void run() { try { long startTime = System.currentTimeMillis(); for (int i=0; i< insertNum; i++) { //插入数据Document doc = new Document("name", "MongoDB") .append("type", "database") .append("id", i) .append("info", new Document("x", 203).append("y", 102));col.insertOne(doc, new SingleResultCallback<Void>(){ @Override public void onResult(final Void result, final Throwable t) { addId(); if (t != null) { System.out.println("t=" + t); } } }); } long endTime = System.currentTimeMillis(); System.out.println("所有插入命令调用完成,耗时:" + (endTime - startTime) + "ms"); }catch (Exception e) { e.printStackTrace();} } }
- 坑爹的mongodb异步驱动(mongodb-async-driver)
- mongodb C driver的异步查询
- MongoDB C++ 驱动部分问题解决方案(MongoDB C++ Driver)
- mongodb-driver-async 如何使用GridFS
- MongoDB系列二:安装mongoDB C/C++驱动(New C++11 driver)
- MongoDB c++ driver(一)
- MongoDB c++ driver(二)
- MongoDB c++ driver(三)
- MongoDB c++ driver(四)
- MongoDB c++ driver(五)
- MongoDB c++ driver(六)
- MongoDB c++ driver(七)
- mongodb的php驱动
- [译] MongoDB Java异步驱动快速指南
- mongodb c driver的使用总结(1)
- MongoDb C# Wrapper 类 (MongoDb Driver 1.9)
- VS2015编译连接mongodb(mongodb C++ driver)
- MongoDB学习日记 - java代码(一):mongodb driver
- 进程间通信(四)---- 共享内存
- Selenium with Python 文档
- CodeForces-835E The penguin's game(思维+二进制乱搞+交互题)
- 记录自己经常用到的Linux命令
- ProtoBuf的序列化和反序列化
- 坑爹的mongodb异步驱动(mongodb-async-driver)
- 【文章】我是文章标题
- adb monkey
- C# --- 其他信息: @xxx不是过程xxx的参数。
- 写一个简单的自定义UITabelView
- SpringBoot集成分页插件PageHelper
- Hbase的JavaApi和工具类
- Hadoop2.7.4集群的Linux安装步骤
- Codeforces 845A Chess Tourney