zoukankan      html  css  js  c++  java
  • 使用YCSB测试mongodb

    项目里面需要对mongodb的性能进行测试,看了下网上很多做法都是使用YCSB进行测试,因此开始学习使用YCSB。 

    参考资料:

    1. YCSB github地址:https://github.com/brianfrankcooper/YCSB 
    2. wiki: https://github.com/brianfrankcooper/YCSB/wiki 
    3. 安装参考:https://github.com/brianfrankcooper/YCSB/tree/master/mongodb 
    4. 之前的一些测试经验:http://www.sdpnosql.net/index.php/archives/3/    http://www.sdpnosql.net/index.php/archives/13/

    1 安装

    基于参考文档(https://github.com/brianfrankcooper/YCSB/tree/master/mongodb )安装java,mvn,ycsb 
    基本上安装了python(2.7.5版本以上),java(需要是jdk,而不是jre),mvn和ycsb之后就可以了

    1.1 YCSB目录结构

    安装好YCSB之后,查看YCSB目录如下:

    drwxr-xr-x. 3 root root   30 Oct 10 18:20 accumulo
    drwxr-xr-x. 3 root root   46 Oct 10 18:20 aerospike
    drwxr-xr-x. 2 root root   17 Oct 13 05:03 bin
    drwxr-xr-x. 3 root root   56 Oct 10 18:20 binding-parent
    -rw-r--r--. 1 root root  877 Oct 10 18:20 BUILD
    drwxr-xr-x. 3 root root   30 Oct 10 18:20 cassandra
    -rw-r--r--. 1 root root 7216 Oct 10 18:20 checkstyle.xml
    drwxr-xr-x. 4 root root   60 Oct 13 03:18 core
    drwxr-xr-x. 3 root root   46 Oct 10 18:20 couchbase
    drwxr-xr-x. 3 root root   30 Oct 10 18:20 distribution
    drwxr-xr-x. 4 root root 4096 Oct 10 18:20 doc
    drwxr-xr-x. 4 root root   54 Oct 10 18:20 dynamodb
    drwxr-xr-x. 3 root root   46 Oct 10 18:20 elasticsearch
    drwxr-xr-x. 3 root root   30 Oct 10 18:20 gemfire
    drwxr-xr-x. 2 root root   36 Oct 10 18:20 hbase094
    drwxr-xr-x. 3 root root   46 Oct 10 18:20 hbase098
    drwxr-xr-x. 3 root root   46 Oct 10 18:20 hbase10
    drwxr-xr-x. 3 root root   43 Oct 10 18:20 hypertable
    drwxr-xr-x. 3 root root   46 Oct 10 18:20 infinispan
    drwxr-xr-x. 3 root root   30 Oct 10 18:20 jdbc
    -rw-r--r--. 1 root root 8082 Oct 10 18:20 LICENSE.txt
    drwxr-xr-x. 3 root root   43 Oct 10 18:20 mapkeeper
    drwxr-xr-x. 4 root root   59 Oct 13 03:19 mongodb
    drwxr-xr-x. 3 root root   43 Oct 10 18:20 nosqldb
    -rw-r--r--. 1 root root  479 Oct 10 18:20 NOTICE.txt
    drwxr-xr-x. 3 root root   46 Oct 10 18:20 orientdb
    -rw-r--r--. 1 root root 5263 Oct 10 18:20 pom.xml
    -rw-r--r--. 1 root root 2033 Oct 10 18:20 README.md
    drwxr-xr-x. 3 root root   46 Oct 10 18:20 redis
    drwxr-xr-x. 3 root root   46 Oct 10 18:20 tarantool
    drwxr-xr-x. 3 root root   30 Oct 10 18:20 voldemort
    drwxr-xr-x. 2 root root 4096 Oct 13 01:09 workloads

    这里面有几个目录需要注意下:

    bin:
        - 目录下有个可执行的ycsb文件,是个python脚本,是用户操作的命令行接口。ycsb主逻辑是:解析命令行、设置java环境,加载java-libs,封装成可以执行的java命令,并执行
    
    workloads:
        - 目录下有各种workload的模板,可以基于workload模板进行个性化修改
    
    core:
        - 包含ycsb里各种核心实现,比如DB的虚拟类DB.java,各个db子类都要继承该类;还有比如workload抽象类,如果我们要自定义workload实现也需要继承该类
    
    各种DB的目录:
        - 比如mongo,redis等,里面包含了对应测试的源码等。
        - 当ycsb mvn编译后,会在对应的目录下生成target文件,ycsb会加载对应target文件中的class类

    2 使用

    ycsb在执行的时候,分为两阶段:load阶段 和 transaction阶段

    2.1 load阶段

    该阶段主要用于构造测试数据,ycsb会基于参数设定,往db里面构造测试需要的数据,如:

    ./bin/ycsb load mongodb-async -s -P workloads/workloada > outputLoad.txt

    mongodb-async

    在ycsb中,对于不同的db都有一些选项,比如mongo就有mongodb 和 mongodb-async。 
    默认的mongodb表示同步,即load和run使用同步的方式,ycsb会调用mongodb/src底下对应的MongodbClient实现对应的insert/update等操作。如果设置了mongodb-async,ycsb会调用mongodb/src底下对应的AsyncMongoDbClient.java实现

    参数设置:

    Options:
        -P file        Specify workload file // workload文件
        -cp path       Additional Java classpath entries
        -jvm-args args Additional arguments to the JVM
        -p key=value   Override workload property // 一些设置
        -s             Print status to stderr // 把状态达到stderr中
        -target n      Target ops/sec (default: unthrottled) // 每秒总共操作的次数
        -threads n     Number of client threads (default: 1) // 客户端线程数

    参数解读:

    -P workload文件

    在ycsb的目录下有多种workload,参考:https://github.com/brianfrankcooper/YCSB/wiki/Core-Workloads,我们以workloada举例子 
    基础配置:

    recordcount=1000     # 总共的操作条数
    operationcount=1000  # 总共操作的次数
    workload=com.yahoo.ycsb.workloads.CoreWorkload=
    
    readallfields=true  # 在读取的时候,是否需要读取所有字段
    
    readproportion=0.5  # 读取比例
    updateproportion=0.5 # update比例
    scanproportion=0
    insertproportion=0
    
    requestdistribution=zipfian

    workloada的负载比较中,read和update类比例为1:1,里面一些设置参数如上,如果我们再设置mongo的时候,还需要再workload中增加对应的mongo配置,如下:

    mongodb.url=mongodb://192.168.137.10:34001/ycsb?  # mongodb对应的uri等
    mongodb.database=ycsb # 对应的db
    mongodb.writeConcern=normal # 写级别

    -p选项

    -p用于设置一些对应的参数,如果workload中的参数,也可以以-p的方式放在命令行中设置

    -s

    -s是表示,在运行中,把一些状态打印到stderr中,一般status信息,用于表示在运行中的一些中间状态(比如当前处理了多少请求,还有多少请求等)

    -target n

    表示1s中总共的操作次数(各个线程加起来的),如果性能不满足,比如最高性能只有100,你设置了1000,那么ycsb会尽量往这个数目去靠近。默认是不做限制

    -thread 线程数

    设置ycsb client的并发测试线程数,默认是1,单线程,所以再测试的时候,一定要设置这个选项

    2.2 transcation阶段

    在2.1load数据结束之后,ycsb就可以进行测试了,也就是transaction阶段。在transaction阶段,会基于workload中的比例设置,和线程参数设置进行db的压测。具体参数如上

    3 一些自定义操作

    由于这次在使用ycsb测试mongodb中主要是为了测试mongodb3.0的性能,同时需要和2.6.9进行对比。而3.0性能写性能大幅度提升是因为锁力度从db锁升级到collection锁。而默认的insert、update操作都是对于同一个collection操作(usertable),没法体现这个优势。 
    因此我们需要修改对应的insert、update和read接口实现一次性写多个db。修改如下:

    修改mongodb底下的MongoDbClient和AsyncMongoDbClient中关于insert、update、read函数实现
    如下:
    原来的实现:
    public final int update(final String table, final String key,
      final HashMap<String, ByteIterator> values) {
        try {
          final MongoCollection collection = database.getCollection(table);
          final DocumentBuilder query = BuilderFactory.start().add("_id", key);
          final DocumentBuilder update = BuilderFactory.start();
          final DocumentBuilder fieldsToSet = update.push("$set");
    
          for (final Map.Entry<String, ByteIterator> entry : values.entrySet()) {
            fieldsToSet.add(entry.getKey(), entry.getValue().toArray());
          }
          final long res =
              collection.update(query, update, false, false, writeConcern);
          return res == 1 ? 0 : 1;
        } catch (final Exception e) {
          System.err.println(e.toString());
          return 1;
        }
    }
    修改后:
    public final int update(final String table, final String key, final HashMap<String, ByteIterator> values) {
    // 对原来的update函数做修改,在每次update时都多做几次操作
    int ret = updateOneTable(table, key, values);
    if (ret != 0) {
    return ret;
    }

    for (int i = 0; i < TABLE_NUM; ++i) {
    String tableName = table + String.valueOf(i);
    ret = updateOneTable(tableName, key, values);
    if (ret != 0) {
    return ret;
    }
    }

    return 0;
    }

    public final int updateOneTable(final String table, final String key, final HashMap<String, ByteIterator> values) {
    try {
    final MongoCollection collection = database.getCollection(table);
    final DocumentBuilder query = BuilderFactory.start().add("_id", key);
    final DocumentBuilder update = BuilderFactory.start();
    final DocumentBuilder fieldsToSet = update.push("$set");

    for (final Map.Entry<String, ByteIterator> entry : values.entrySet()) {
    fieldsToSet.add(entry.getKey(), entry.getValue().toArray());
    }

    final long res = collection.update(query, update, false, false, writeConcern);
    return res == 1 ? 0 : 1;
    } catch (final Exception e) {
    System.err.println(e.toString()); return 1;
    }
    }

    其中TABLE_NUM可以根据实际需求进行设置(实际中,我们设置了该值为4,表示一次写5个table)

  • 相关阅读:
    oracle中Blob和Clob类型的区别
    为什么要分库分表
    Enable file editing in Visual Studio's debug mode
    SQL Server Dead Lock Log
    Debug .NET Framework Source
    SQL Server text field里面有换行符的时候copy到excel数据会散乱
    诊断和修复Web测试记录器(Web Test Recorder)问题
    Can't load Microsoft.ReportViewer.ProcessingObjectModel.dll
    'telnet' is not recognized as an internal or external command
    Linq to XML
  • 原文地址:https://www.cnblogs.com/SailorXiao/p/5808828.html
Copyright © 2011-2022 走看看