文档章节

MyCat - 测试篇

张哈希_
 张哈希_
发布于 2016/04/24 11:44
字数 1418
阅读 63
收藏 1

数据库路由中间件MyCat - 测试篇

测试背景

为了检测MyCat性能表现以及架构扩展性,设计测试。首先需要编写压力测试代码,程序基于Jmeter,并且封装了JDBC,模拟涅槃项目实际应用的连接方式。测试程序生成基于当前系统时间的随机数,并且保证这个随机数一秒内重复概率为百万分之一。
程序请求必须保证每个分片的请求量是一样的.
测试脚本举例:

package com.sf.hash.drm;

import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.ThreadLocalRandom;

public class DRMTest2 extends AbstractJavaSamplerClient{
    private String JDBC_DRIVER;
    private String DB_URL;
    private String USER;
    private String PASSWORD;

    private static ThreadLocal <Connection> conn = new ThreadLocal<Connection>();
    private static ThreadLocal<Statement> stmt = new ThreadLocal<Statement>();

    private String testStr;

    private int aa=0;
    private int count=0;
    //初始化方法,实际运行时每个线程仅执行一次,在测试方法运行前执行,类似于LoadRunner中的init方法
    public void setupTest(JavaSamplerContext arg0) {

        JDBC_DRIVER = arg0.getParameter("JDBC_DRIVER", "");
        USER = arg0.getParameter("USER", "");
        PASSWORD = arg0.getParameter("PASSWORD", "");
        DB_URL = arg0.getParameter("DB_URL","");
        aa = Integer.parseInt(arg0.getParameter("ID",""));
        try {
            Class.forName(JDBC_DRIVER);
            conn.set(DriverManager.getConnection(arg0.getParameter("DB_URL",""), arg0.getParameter("USER", ""), arg0.getParameter("PASSWORD", "")));
            stmt.set(conn.get().createStatement());

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread()+" start!");
    }
    //设置传入的参数,可以设置多个,已设置的参数会显示到Jmeter的参数列表中
    public Arguments getDefaultParameters() {
        Arguments params = new Arguments();
        params.addArgument("JDBC_DRIVER", "com.mysql.jdbc.Driver");   //定义一个参数,显示到Jmeter的参数列表中,第一个参数为参数默认的显示名称,第二个参数为默认值
        params.addArgument("DB_URL", "jdbc:mysql://10.202.44.205:8666/test");
        params.addArgument("USER", "test");
        params.addArgument("PASSWORD", "test");
        params.addArgument("ID", "0");
        return params;
    }
    //测试执行的循环体,根据线程数和循环次数的不同可执行多次,类似于LoadRunner中的Action方法
    public SampleResult runTest(JavaSamplerContext arg0) {

        SampleResult results = new SampleResult();
        long currentTime = System.nanoTime();
        int key = ThreadLocalRandom.current().nextInt(0,100000000);
        long id = currentTime*4 + key*4 + (aa);
        String sql = "INSERT INTO proxyha(id,name,age) VALUES (" +
                (id) +
                ", '"+aa+"', 18)";

// String sql2 = "UPDATE proxyha set age ='" +
// (id) +
// "'where name ='"+Thread.currentThread()+aa+"'";
        int a = 0;
        try {
            results.sampleStart();
            a = stmt.get().executeUpdate(sql);
// a = stmt.get().executeUpdate(sql2);
            results.sampleEnd();
        } catch (SQLException e) {
            e.printStackTrace();
            int count = 0;
            //重试
            while(!reconnect(arg0))
            {
                count++;
                if(count>100)
                {
                    System.out.print(0);
                    break;
                }
            }
        }
        if(a <= 0){
            results.setSuccessful(false);   //用于设置运行结果的成功或失败,如果是"false"则表示结果失败,否则则表示成功
        }else
            results.setSuccessful(true);
        return results;
    }

    private boolean reconnect(JavaSamplerContext arg0){
         try {
             stmt.get().close();
             conn.get().close();
             conn.set(DriverManager.getConnection(arg0.getParameter("DB_URL",""), arg0.getParameter("USER", ""), arg0.getParameter("PASSWORD", "")));
             stmt.set(conn.get().createStatement());
             aa++;
        } catch (SQLException e) {
            return false;
        }
        return true;
    }

    //结束方法,实际运行时每个线程仅执行一次,在测试方法运行结束后执行,类似于LoadRunner中的end方法
    public void teardownTest(JavaSamplerContext arg0) {
        System.out.println(Thread.currentThread()+" end!");
    }


}

测试场景

  1. 数据库能力测试,用压测程序直接压测每一个库,为了看数据库能力是否一致。
  2. 压测程序能力测试,用n个压测程序压测m个数据库,为了看压测程序是否存在性能瓶颈。
  3. MyCat能力测试,用n个压测程序压测o个MyCat实例后台连接着同样的m个数据库节点。
  4. MyCat故障边界测试:
    1. 单节点缓慢
    2. 单节点down机(对于全局表的dml都会失效)
    3. 分片表单节点锁定
    4. 分片表索引摘除测试update影响

测试环境

这里写图片描述

测试结果

1. 数据库能力测试

这里写图片描述
排除db1m-db4m(因为性能差太多)的问题,之后db1m-db4m与其他12个数据库的性能差不多了。

2. 压测程序能力测试

这里写图片描述

3. MyCat能力测试

这里写图片描述
测试证明,MyCat的TPS可以随着测试脚本与实例数量还有DB节点的数量增加而增加

4. MyCat故障边界测试

4.1 单节点缓慢

这里写图片描述
使用cpulimit命令限制某个DB节点的cpu使用率,原本不限制可以用到1500%, 分别限制到1000%,500%,100%;
这里写图片描述

4.2 单节点宕机

让MyCat的16个节点其中一个节点在运行脚本过程中宕机
这里写图片描述

4.3 分片表单节点锁定

运行脚本,让MyCat的16个节点其中一个节点在运行脚本过程中做在线的ddl
这里写图片描述
运行脚本,让MyCat的16个节点其中一个节点在运行脚本过程中全表锁定
这里写图片描述

4.3 分片表索引摘除测试update影响

修改脚本(从insert改成以主键查找update)。运行脚本,让MyCat的16个节点其中一个节点在运行脚本过程中删除主键索引(表是以主键作为分片id)
这里写图片描述
修改脚本(从insert改成以非主键(unique字段)查找update)。运行脚本,让MyCat的16个节点其中一个节点在运行脚本过程中删除非主键(unique)索引(表是以主键作为分片id)
这里写图片描述

测试结论

根据上面测试结果,在物理环境正常的情况下,TPS是可以随着MyCat实例个数与后台db个数增加而增加的。
以下故障边界都有个前提条件:请求是均匀分布在每个后台db节点上的。

  • MyCat性能不受限于最慢的分片主机,分片主机缓慢只是单点影响,不会影响全局
  • 单节点宕机不会影响只发到其他节点的命令,但是只要涉及到这个节点的命令(比如select * from table range(0,1000))都不能正常执行
  • 分片表单节点锁定对于MyCat性能影响不大。
  • 分片表分片字段索引丢失如果按照分片字段查找更新的话,影响不大。但是如果非分片字段索引丢失如果按照那个字段查找更新的话,由于请求会发到每个节点,那么每个请求都会全量搜索,对于性能影响很大。

© 著作权归作者所有

张哈希_
粉丝 7
博文 42
码字总数 67907
作品 0
房山
程序员
私信 提问
MyCAT全局序列号-数据库方式

1.MyCat中的全局序列号介绍 在实现分库分表的情况下,数据库自增主键已无法保证自增主键的全局唯一。为此,MyCat 提供了全局 sequence,并且提供了包含本地配置和数据库配置等多种实现方式。...

HilaryHe
2018/07/23
0
0
MyCat 看了这篇什么都会了

1、什么是MyCat 1、一个彻底开源的,面向企业应用开发的大数据库集群 2、支持事务、ACID、可以替代MySQL的加强版数据库 3、一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群 ...

木迪_2a4e
2018/09/17
0
0
Mycat - 高可用与负载均衡实现,满满的干货!

前情回顾 Mycat - 实现数据库的读写分离与高可用中我们实现了mysql的读写分离与高可用,有几个点我们回顾下 如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Net...

编程SHA
02/20
0
0
Mycat多租户/分布数据库/集群数据库以及SAAS研究进度报告

1、mycat操作 (1)垂直切分配置 (2)水平切分配置 (3)mycat修改schema.xml之后热重启 (4)mycat注解的实现 (5)mycat高可用(搭配HAproxy等一起做集群,多个mycat节点) 2、mycat可以配...

蓝奔z
2018/08/24
0
0
mycat实现mysql分库分表

1. mycat介绍 MyCat发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,...

红隐
2018/05/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

texlive安装

Installing to: D:/bin/texlive/texlive/2019Installing [001/307, time/total: ??:??/??:??]: adobemapping [2130k]Installing [002/307, time/total: 00:03/08:57]: ae [84k]Installing......

MtrS
24分钟前
2
0
运维规范

命名规范 发布流程 监控告警 故障定位 状态 日志 监控

以谁为师
今天
2
0
约瑟夫环(报数游戏)java实现

开端 公司组织考试,一拿到考题,就是算法里说的约瑟夫环,仔细想想 以前老师将的都忘了,还是自己琢磨把~ package basic.gzy;import java.util.Iterator;import java.util.LinkedList;...

无极之岚
今天
3
0
Kernel字符设备驱动框架

Linux设备分为三大类:字符设备,块设备和网络设备,这三种设备基于不同的设备框架。相较于块设备和网络设备,字符设备在kernel中是最简单的,也是唯一没有基于设备基础框架(device结构)的...

yepanl
今天
3
0
Jenkins 中文本地化的重大进展

本文首发于:Jenkins 中文社区 我从2017年开始,参与 Jenkins 社区贡献。作为一名新成员,翻译可能是帮助社区项目最简单的方法。 本地化的优化通常是较小的改动,你无需了解项目完整的上下文...

Jenkins中文社区
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部