定制开发sysbench扩展版压测分库分表场景

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lizhitao/article/details/72179582

背景

使用sysbench基准工具对Mycat和Atlas进行压测,通过综合比较从中选择一个作为今后选择的方向,更多背景信息请参考如下:

sysbench介绍

SysBench是一个模块化的、跨平台、多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况。它主要包括以下几种方式的测试:

  1. 列表内容
  2. cpu性能
  3. 磁盘io性能
  4. 调度程序性能
  5. 内存分配及传输速度
  6. POSIX线程性能
  7. 数据库性能(OLTP基准测试)

sysbench压测用法参考如下:

结合sysbench-sharding一起使用,扩展版insert时增加2个参数,其他都一样。

安装sysbench

sysbench国外个人开发的,基本无文档,国内有些博客可以参考,不同版本参数不一,用法也有稍许差异,它有0.4、0.5、1.0,其中0.4功能较弱,1.0网上缺少相关文档缺少,另外我们对sysbench功能也没有极致的要求,综合考虑选择0.5版本

注意:安装sysbench前,先安装lua库和mysql客户端mysql++-devel.x86_64或mysql++-devel.i686

安装sysbench:
1.下载(官方提供)
https://pan.baidu.com/s/1qYdO2oW
2.解压
tar xzvf sysbench-0.5.tar.gz
3.安装
cd sysbench-0.5
./autogen.sh
./configure –with-mysql-includes=/usr/include/mysql –with-mysql-libs=/usr/lib64/mysql
make
make install

sysbench项目工程不大,其实不必安装(不用执行make install,看个人,我就是这样做的),编译后源码目录下生成执行文件sysbench,直接带上相关参数就可以执行了。简单方便,容易修改代码。

sysbench扩展版,支持分库分表测试

sysbench-sharding扩展版下载

sysbench-0.5-sharding.tar.gz百度下载地址:https://pan.baidu.com/s/1MeLoUK8ndyuuOqafvhtUgQ

为什么要扩展sysbench

  • 效率优先、工具化。基于lua开发很多能一键运行的脚本,直接使用sysbench压测,需要写好几种类型脚本,填上许多参数很麻烦且学习成本高
  • 客户端生成全局唯一数字ID。sysbench预处理创建表为自增主键,也支持客户端生成主键但实测算法是有问题的,运行程序会因为出现重复主键报错而终止,就算忽略错误也会影响实测性能,而分库分表场景需要由客户端生成全局唯一ID

商业数据库中间件开发商,全民软件压测工具也是基于sysbench扩展的。不过闭源,可以下载二进制库,用于测试自家开发的OneProxy,却无法兼容Mycat和Atlas,具体原因不详

OneProxy :: 如何准备sysbench的分库分表测试环境?无须DBA手工建分表!
http://www.onexsoft.com/zh/oneproxy-sysbench-sharding.html

修改sysbench代码

全局唯一ID生成规则:一个无锁自增算法,可以指定ID起点值和步长且可配置,新增参数为id-start-val和id-step-val,id-start-val表示id起始值,id-step-val为步长,具体应用请看stress-testing-atlas-insert.sh
sysbench.c文件增加代码

// sb_arg_t结构体增加字段
sb_arg_t general_args[] = {
  {"id-start-val", "generate start value of id", SB_ARG_TYPE_INT, "0"}, 

  {"id-step-val", "generate start value of id", SB_ARG_TYPE_INT, "1"}
}


static int init(void)
{
  // 增加代码片段
  sb_globals.id_start_val = sb_get_value_int("id-start-val");

  sb_globals.id_step_val = sb_get_value_int("id-step-val");
  if(sb_globals.id_step_val == 0)
  {
    log_text(LOG_FATAL, "Invalid value for --id-step-val: %d.\n", sb_globals.id_step_val);
    return 1;      
  }

}

// 此方法生成全局唯一ID,id_start_val起始ID,id_step_val步长
int sb_global_unique_id() 
{
   return __sync_fetch_and_add( &sb_globals.id_start_val, sb_globals.id_step_val);
}

sysbench.h文件中sb_globals_t结构体增加2个字段

typedef struct
{
  unsigned int    id_start_val;  /* 扩展变量、用于指定全局起始id */
  unsigned int    id_step_val;  /* 扩展变量、用于生成全局唯一id的步长  */
} sb_globals_t;

向lua库函数注册sb_global_unique_id函数,提供给lua脚本调用生成全局唯一ID,下面script_lua.c文件增加代码

lua_State *sb_lua_new_state(const char *scriptname, int thread_id)
{
 // 新增代码片段
 lua_pushcfunction(state, sb_lua_global_unique_id);
 lua_setglobal(state, "sb_global_unique_id");

}

int sb_lua_global_unique_id(lua_State *L) 
{
  lua_pushnumber(L, sb_global_unique_id());

  return 1;
}

说明:sysbench-sharding同理sysbench安装

lua脚本修改

使用sysbench对数据库中间件做压测,它提供DB相关一系列lua脚本,但默认脚本并不完全符合要求,所以需要对相关脚本进行修改或新增脚本,以支撑分库分表测试功能。

本次分库分表压测是为了生成全局唯一ID,所以只需要修改insert.lua脚本就可以了。
insert.lua修改版代码如下:

-- 修改event方法中部分片段代码
function event(thread_id)
   local table_name
   local i
   local c_val
   local k_val
   local pad_val

   table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count)

   k_val = sb_rand(1, oltp_table_size)
   c_val = sb_rand_str([[
###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]])
   pad_val = sb_rand_str([[
###########-###########-###########-###########-###########]])

   if (db_driver == "pgsql" and oltp_auto_inc) then
      rs = db_query("INSERT INTO " .. table_name .. " (k, c, pad) VALUES " ..
                       string.format("(%d, '%s', '%s')", k_val, c_val, pad_val))
   else
      if (oltp_auto_inc) then
         i = 0
      else
--         i = sb_rand_uniq(1, oltp_table_size)
       i = sb_global_unique_id();
      end
      rs = db_query("INSERT INTO " .. table_name ..
                       " (id, k, c, pad) VALUES " ..
                       string.format("(%d, %d, '%s', '%s')", i, k_val, c_val,
                                     pad_val))
   end
end

创建自动化脚本

编写lua脚本设置参数时,Mycat与Atlas的区别:
* Mycat携带账号参数,需要使用Mycat的账号,因为Mycat首先是逻辑库概念,对物理库进行了隔离且有资源管理,就是权限控制
* Atlas携带账号参数,直接使用MySQL的账号,因为Atlas没有权限管理,也没有对MySQL物理资源进行管理

lua脚本存储路径


lua脚本与sysbench可执行同一目录(sysbench编译后自动生成到该目录)

删除表数据

batch-mysql-truncate.sh内容如下:

#!/bin/bash
mysql -uzhitao -p123456 -hIP01 -P3306 -e "truncate table dbproxy.sbtest1;" 
sleep 2
mysql -uzhitao -p123456 -hIP02 -P3306 -e "truncate table dbproxy.sbtest1;"
sleep 2
mysql -uzhitao -p123456 -hIP03 -P3306 -e "truncate table dbproxy.sbtest1;"
sleep 2
mysql -uzhitao -p123456 -hIP04 -P3306 -e "truncate table dbproxy.sbtest1;"
sleep 2

插入数据压测脚本

Atlas的insert脚本stress-testing-atlas-insert.sh如下

#!/bin/bash
./batch-mysql-truncate.sh
# 默认8线程
NUMTHREADS=8

echo -e "线程数赋值前 $1"

NUMTHREADS=$1
#判断如果$1为空
if [ -z $1 ]; then 
    NUMTHREADS=8
fi

echo -e "线程数赋值后 $1"

MAXTIME=$2

if [ -z $2 ]; then
    MAXTIME=120
fi

./sysbench --test=/home/zhitao.li/sysbench-0.5/sysbench/tests/db/insert.lua --mysql-host=dbproxyIP --mysql-port=1234  \
--mysql-user=zhitao --mysql-password=123456 --mysql-db=dbproxy --oltp-tables-count=1 --oltp-table-size=10000    \
--report-interval=10 --rand-init=on --max-requests=0  --report-interval=10 --oltp_auto_inc=off \
--oltp-read-only=off --max-time=$MAXTIME --num-threads=$NUMTHREADS  --mysql-ignore-duplicates=on --mysql-ignore-errors \
# 新增参数,用于调节生成全局唯一ID,id-start-val和id-step-val参数可选,id-start-val表示id起始值,id-step-val为步长
--id-start-val=1 --id-step-val=4  \
run

#--oltp-read-only=off --max-time=120 --num-threads=$NUMTHREADS --mysql-ignore-duplicates=on --mysql-ignore-errors

执行命令为:./stress-testing-atlas-insert.sh 线程数 执行持续时间(单位秒)

Mycat的insert脚本stress-testing-mycat-insert.sh如下

#!/bin/bash
./batch-mysql-truncate.sh
sleep 5
# 默认8线程
NUMTHREADS=8

echo -e "线程数赋值前 $1"

NUMTHREADS=$1
#判断如果$1为空
if [ -z $1 ]; then 
    NUMTHREADS=8
fi

echo -e "线程数赋值后 $1"

MAXTIME=$2

if [ -z $2 ]; then
    MAXTIME=120
fi

./sysbench --test=/home/zhitao.li/sysbench-0.5/sysbench/tests/db/insert.lua --mysql-host=dbproxyIP --mysql-port=8066  \
--mysql-user=root --mysql-password=123456 --mysql-db=testdb --oltp-tables-count=1 --oltp-table-size=1000000  --oltp_auto_inc=off  \
--report-interval=10 --rand-init=on --max-requests=0 --oltp-test-mode=nontrx --oltp-nontrx-mode=select  --report-interval=10 \
--oltp-read-only=off --max-time=$MAXTIME --num-threads=$NUMTHREADS --mysql-ignore-duplicates=on --mysql-ignore-errors  \
run

#--oltp-read-only=off --max-time=120 --num-threads=$NUMTHREADS --mysql-ignore-duplicates=on --mysql-ignore-errors

执行命令为:./stress-testing-mycat-insert.sh 线程数 执行持续时间(单位秒)

查询压测脚本

Atlas的select脚本stress-testing-atlas-select.sh如下

#!/bin/bash
# 默认8线程
NUMTHREADS=8
echo -e "线程数赋值前 $1"

NUMTHREADS=$1
#判断如果$1为空
if [ -z $1 ]; then 
    NUMTHREADS=8
fi

echo -e "线程数赋值后 $1"

MAXTIME=$2

if [ -z $2 ]; then
    MAXTIME=120
fi

./sysbench --mysql-host=dbproxyIP --mysql-port=1234 --mysql-user=zhitao --mysql-password=123456  \
--mysql-db=dbproxy --max-requests=0 --test=/home/zhitao.li/sysbench-0.5/sysbench/tests/db/select.lua  --num-threads=$NUMTHREADS \
--oltp_tables_count=1 --oltp-table-size=1000000 --rand-init=on  --max-time=$MAXTIME  --report-interval=10 \
--oltp-test-mode=nontrx --oltp-nontrx-mode=select --oltp-read-only=on --oltp-skip-trx=on \
run

执行命令为:./stress-testing-atlas-select.sh 线程数 执行持续时间(单位秒)

Mycat的select脚本stress-testing-mycat-select.sh如下:

#!/bin/bash
# 默认8线程
NUMTHREADS=8

echo -e "线程数赋值前 $1"

NUMTHREADS=$1
#判断如果$1为空
if [ -z $1 ]; then 
    NUMTHREADS=8
fi

echo -e "线程数赋值后 $1"

MAXTIME=$2

if [ -z $2 ]; then
    MAXTIME=120
fi

./sysbench --test=/home/zhitao.li/sysbench-0.5/sysbench/tests/db/select.lua --mysql-host=dbproxyIP --mysql-port=8066  \
--mysql-user=root --mysql-password=123456 --mysql-db=testdb --oltp-tables-count=1 --oltp-table-size=1000000  --oltp_auto_inc=off  \
--report-interval=10 --rand-init=on --max-requests=0 --oltp-test-mode=nontrx --oltp-nontrx-mode=select  --report-interval=10 \
--oltp-read-only=off --max-time=$MAXTIME --num-threads=$NUMTHREADS --mysql-ignore-duplicates=on --mysql-ignore-errors  \
run

#--oltp-read-only=off --max-time=120 --num-threads=$NUMTHREADS --mysql-ignore-duplicates=on --mysql-ignore-errors

执行命令为:./stress-testing-mycat-select.sh 线程数 执行持续时间(单位秒)

修改数据压测脚本

Atlas的update脚本stress-testing-atlas-update.sh如下

#!/bin/bash

NUMTHREADS=8

echo -e "线程数赋值前 $1"

NUMTHREADS=$1
#判断如果$1为空
if [ -z $1 ]; then 
    NUMTHREADS=8
fi

echo -e "线程数赋值后 $1"

MAXTIME=$2

if [ -z $2 ]; then
    MAXTIME=120
fi

./sysbench --test=/home/zhitao.li/sysbench-0.5/sysbench/tests/db/update_non_index.lua --mysql-host=dbproxyIP --mysql-port=1234  \
--mysql-user=zhitao --mysql-password=123456 --mysql-db=dbproxy --oltp-tables-count=1 --oltp-table-size=1000000      \
--report-interval=10 --rand-init=on --max-requests=0  --report-interval=10 --oltp_auto_inc=off \
--oltp-read-only=off --max-time=$MAXTIME --num-threads=$NUMTHREADS  --mysql-ignore-duplicates=on --mysql-ignore-errors  \
run

执行命令为:./stress-testing-atlas-update.sh 线程数 执行持续时间(单位秒)

Mycat的update脚本stress-testing-mycat-update.sh如下

#!/bin/bash

sleep 5

NUMTHREADS=8

echo -e "线程数赋值前 $1"

NUMTHREADS=$1
#判断如果$1为空
if [ -z $1 ]; then 
    NUMTHREADS=8
fi

echo -e "线程数赋值后 $1"

MAXTIME=$2

if [ -z $2 ]; then
    MAXTIME=120
fi


./sysbench --test=/home/zhitao.li/sysbench-0.5/sysbench/tests/db/update_non_index.lua --mysql-host=dbproxyIP --mysql-port=8066  \
--mysql-user=root --mysql-password=123456 --mysql-db=testdb --oltp-tables-count=1 --oltp-table-size=1000000  --oltp_auto_inc=off  \
--report-interval=10 --rand-init=on --max-requests=0 --oltp-test-mode=nontrx --oltp-nontrx-mode=select  --report-interval=10 \
--oltp-read-only=off --max-time=$MAXTIME --num-threads=$NUMTHREADS --mysql-ignore-duplicates=on --mysql-ignore-errors  \
run

#--oltp-read-only=off --max-time=120 --num-threads=$NUMTHREADS --mysql-ignore-duplicates=on --mysql-ignore-errors

执行命令为:./stress-testing-mycat-update.sh 线程数 执行持续时间(单位秒)

lua批量化脚本,利用sysbench在不同线程数下进行压力测试的自动化脚本

批量化插入数据压测脚本

脚本batch-atlas-insert.sh如下

#!/bin/bash
# 执行持续时间(单位秒)
MAXTIME=180

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-insert.sh 2 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-insert.sh 4 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-insert.sh 8 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-insert.sh 16 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-insert.sh 32 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-insert.sh 64 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-insert.sh 128 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-insert.sh 256 $MAXTIME

执行命令为:./batch-atlas-insert.sh

脚本batch-mycat-insert.sh如下

#!/bin/bash
# 执行持续时间(单位秒)
MAXTIME=180

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-insert.sh 2 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-insert.sh 4 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-insert.sh 8 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-insert.sh 16 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-insert.sh 32 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-insert.sh 64 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-insert.sh 128 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-insert.sh 256 $MAXTIME

执行命令为:

批量化查询数据压测脚本

脚本batch-atlas-select.sh如下

#!/bin/bash
# 执行持续时间(单位秒)
MAXTIME=180

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-select.sh 2 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-select.sh 4 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-select.sh 8 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-select.sh 16 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-select.sh 32 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-select.sh 64 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-select.sh 128 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-select.sh 256 $MAXTIME

执行命令为:./batch-atlas-select.sh

脚本batch-mycat-select.sh如下

#!/bin/bash

MAXTIME=180

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-select.sh 2 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-select.sh 4 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-select.sh 8 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-select.sh 16 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-select.sh 32 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-select.sh 64 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-select.sh 128 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-select.sh 256 $MAXTIME

执行命令为:

批量化修改数据压测脚本

脚本batch-atlas-update.sh如下

#!/bin/bash

MAXTIME=180

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-update.sh 2 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-update.sh 4 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-update.sh 8 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-update.sh 16 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-update.sh 32 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-update.sh 64 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-update.sh 128 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-atlas-update.sh 256 $MAXTIME

执行命令为:./batch-atlas-update.sh

脚本batch-mycat-update.sh如下

#!/bin/bash

MAXTIME=180

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-update.sh 2 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-update.sh 4 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-update.sh 8 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-update.sh 16 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-update.sh 32 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-update.sh 64 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-update.sh 128 $MAXTIME

date "+%Y-%m-%d %H:%M:%S"

./stress-testing-mycat-update.sh 256 $MAXTIME

执行命令为:./batch-mycat-update.sh

压测运行

脚本batch-stress-testing.sh如下

./batch-atlas-insert.sh
./batch-mycat-insert.sh
./batch-atlas-select.sh
./batch-mycat-select.sh
./batch-atlas-update.sh
./batch-mycat-update.sh

以上脚本输出结果格式,请参照: 使用sysbench对mysql压力测试 “结果解读”部分

展开阅读全文

没有更多推荐了,返回首页