oneproxy for mysql_使用oneproxy对mysql进行分库分表

数据库分库分表是一把双刃剑,它可以在一定程度上加快查询速度,另外在一些需要查询历史数据、跨分区查询中,又会带来一些效率问题,因此,只有在有经验的DBA的带领下才能实施,否则,这可能是一个巨大的工程,而且未必能带来明显效率的提升。

一、数据库分库分表的几种方式:

1、在同一台数据库服务器上将表分割成多张:

5d425f421e9cc9db5d588c8bd5bac5fb.png

如上:

将一份大的数据分割到同一数据库的其他表中,这种方式有一种特殊的情况,将历史数据定时归档,存放到一张历史表中,表中只存储最近的数据,以便统计等查询。

2、在同一台数据库上把同一项目的不同的业务放到不同的数据库中

8410c011979407269aa26ce6297e95b2.png

如图,将用户、订单和产品分别存储到不同的数据库中

3、将同一台数据库上的数据库表根据业务的划分分散到不同的独立服务器上

a0d64a7f83f5376c8b8f28330249cdad.png

4、将同一张表分散到不同的独立的服务器上

60ba138ad389593f448099ccbd053c5d.png

二、分库分表(水平拆分)前的准备

1、选择分区键分区键要尽可能避免跨分片查询的发生

分区键要尽量使各个分片的数据平均

2、如何存储无需分片的表

如一些公共的数据

每个分片中存储一份相同的数据

将无需分片的表使用额外的节点统一存储

3、如何在节点上部署分片每个分片使用单一数据库,并且数据库名也相同,比如都叫user

将多个分片表存储在一个数据库中,并在表名上加入分片号后缀,如user_1,user_2等

在一个节点中部署多个数据库,每个数据库包含一个分片

4、如何分配分片中的数据

这和MySQL的分区类似,有按范围(Range)、按值、按哈希算法进行分区

按分区键的hash值取模来分配分片数据

按分区键的范围来分配分片数据

利用分区键和分片的映射表来分配分片数据

5、如何生成全局唯一ID使用auto_increment_increment和auto_increment_offset参数

使用全局节点来生成ID

使用Redis等缓存服务器来创建全局ID

三、使用oneproxy进行分库分表

1、对单个表进行分库分表(1)确定要分区的表,在各个节点上建立结构相同但表名不同的表(表前缀相同,后缀不同)

在节点1上执行:

CREATE TABLE`m_user_info_1`(

`uid`int(11)NOT NULL,

`account`char(30)NOT NULL DEFAULT'',

`password`char(32)NOT NULL DEFAULT'',

`create_time`timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

PRIMARY KEY(`uid`)

)ENGINE=InnoDBDEFAULT CHARSET=utf8;

CREATE TABLE`m_user_info_2`(

`uid`int(11)NOT NULL,

`account`char(30)NOT NULL DEFAULT'',

`password`char(32)NOT NULL DEFAULT'',

`create_time`timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

PRIMARY KEY(`uid`)

)ENGINE=InnoDBDEFAULT CHARSET=utf8;

在节点2上执行:

CREATE TABLE`m_user_info_3`(

`uid`int(11)NOT NULL,

`account`char(30)NOT NULL DEFAULT'',

`password`char(32)NOT NULL DEFAULT'',

`create_time`timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

PRIMARY KEY(`uid`)

)ENGINE=InnoDBDEFAULT CHARSET=utf8;

CREATE TABLE`m_user_info_4`(

`uid`int(11)NOT NULL,

`account`char(30)NOT NULL DEFAULT'',

`password`char(32)NOT NULL DEFAULT'',

`create_time`timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

PRIMARY KEY(`uid`)

)ENGINE=InnoDBDEFAULT CHARSET=utf8;

(2)建立分区规则模板

在oneproxy的conf目录下建立user_part.txt,也可以复制template.txt文件进行修改:

[

{

"table":"m_user_info",

"pkey":"uid",

"type":"int",

"method":"range",

"partitions":

[

{"suffix":"_1","group":"user1","value":100000},

{"suffix":"_2","group":"user1","value":200000},

{"suffix":"_3","group":"user2","value":300000},

{"suffix":"_4","group":"user2","value":null}

]

}

]

注:

table表示表名(表前缀)

pkey表示表的主键

type表示主键的类型

method表示分区键的规则策略(有范围range,值list和hash)

partions为分区的规则suffix为后缀

group为服务器组名

value表示范围的最大值(并不包括这个值)

name为完整的表名

(3)修改oneproxy配置,并重启oneproxy服务

2f2502da6b017b38d6090d5a95650f91.png

完整配置:

[oneproxy]

keepalive=1

event-threads=4

log-file=log/oneproxy.log

pid-file=log/oneproxy.pid

lck-file=log/oneproxy.lck

#proxy-auto-readonly = 1

proxy-forward-clientip=1

proxy-trans-debug=1

proxy-address=:3307

mysql-version=5.7.16

proxy-master-addresses.1=192.168.0.101:3306@user1

proxy-master-addresses.2=192.168.0.102:3306@user2

proxy-user-list=proxyadmin/4841E43E59A4337D61C5D14291D737EAA1A38B4E@user_db

#proxy-part-template = conf/user_part.txt

proxy-part-tables=conf/user_part.txt

#proxy-part-tables.1 = conf/part.txt

#proxy-part-tables.2 = conf/part2.txt

#proxy-part-tables.3 = conf/cust1.txt

proxy-charset=utf8_general_ci

proxy-group-policy=user1:0

(4)使用客户端进行分区测试

执行插入操作

这里通过php作为客户端来插入400000条数据

$conf=array(

'host'=>'192.168.0.100',

'port'=>3307,

'user'=>'proxyadmin',

'password'=>'oneproxy',

'database'=>'user_db'

);

$dsn='mysql:dbname='.$conf['database'].';host='.$conf['host'].';port='.$conf['port'].';charset=UTF8';

try{

$dbh=newPDO($dsn,$conf['user'],$conf['password'],array(PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES \'UTF8\''));

}catch(PDOException$e){

echo'ERROR: '.$e->getMessage();

exit;

}

$idx=0;

for($i=1;$i<=400000;$i++){

$account='shixinke'.$i;

$password=md5($account.$i);

$sql='INSERT INTO m_user_info(uid, account, password) VALUES('.$i.', "'.$account.'", "'.$password.'")';

$res=$dbh->exec($sql);

if($res){

$idx++;

}else{

var_dump($dbh->errorInfo());

}

}

echo $idx;

执行查询操作

在oneproxy代理服务器上查看总记录数:

f6160cac49a44d749bdcc036d70c16f6.png

在各节点服务器上查看各分区记录数:

节点1:

![]

f6cd64bed596d11d81a1aecd74fba1ad.png

节点2:

eb4e38e7a4e194171a291334a2695779.png

为什么m_user_1这张表只有9999条记录呢,因为分区规则上它的上限是100000,而且是不能包含这个。

在oneproxy代理服务器上查询某条记录:

bf15b42060c0e944d5adde02547ea30c.png

2、对多个表进行分库分表

多个表与单个表分库分表并没有什么差别,只需要多添加一条分区规则即可,不同这里讨论一个特殊的情况,就是一个不需要分区的表的情况,那它在各个节点都会保留一份相同的数据(当然个人认为把它放到一个单独的节点上更好,不过对于联表查询来说不方便)

这里以配置表m_options为例

这里只列举一下规则配置:

[

{

"table":"m_user_info",

"pkey":"uid",

"type":"int",

"method":"range",

"partitions":

[

{"suffix":"_1","group":"user1","value":100000},

{"suffix":"_2","group":"user1","value":200000},

{"suffix":"_3","group":"user2","value":300000},

{"suffix":"_4","group":"user2","value":null}

]

},

{

"table":"m_options",

"pkey":"key",

"type":"char",

"method":"global",

"partitions":

[

{"suffix":"","group":"user1"},

{"suffix":"","group":"user2"}

]

}

]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值