MyCAT技术

MyCAT读写分离及分库分表

第1章 MyCAT分布式系统解决方案

1.1 分布式系统介绍:

分布式系统特性:

1.      透明性:

a)        分布式系统对用户来说是透明的,一个分布式系统在用户面前的表现就像一个传统的单机处理机分时系统,可以让用户不比了解内部结构就可以使用

2.      扩展性:

a)        分布式系统的最大特点就是扩展性,它可以分局需求的增加而扩展,可以通过横向扩展使集群的整体性能得到线性提升,也可以通过纵向扩展单台服务器的性能使服务器的集群的性能得到提升

1.2 MyCAT的设计理念:

mycat的原理中最重要的一个动词就是拦截,它拦截了用户发送过来的sql语句,首先对sql语句组了一些特定的分析,如分片分析,路由分析,读写分析,分离分析,缓存分析,然后将此sql语句发往后端的真实数据库,并将返回结果做适当处理,最终返回给用户

1.1 MyCAT软件特点:

1.      遵守mysql原生协议,跨语言,跨数据库的通用中间件代理

2.      基于心跳的自动故障切换,支持读写分离,支持mysql一双主,多从,以及一主多从

3.      有效管理数据源连接,基于数据分库,而不是分表的模式

4.      基于Nio实现,有效管理线程,高并发问题

5.      支持数据的多片自动路由与聚合,支持sum,count,max等常用的聚合函数

6.      支持2表join,甚至基于caltet的多表join

7.      支持通过全局表,ER关系的分片策略,实现了高效的夺标join查询

8.      支持多租户方案

9.      支持分布式事务

10.  支持全局序列号,解决分布式下的主键生成问题

11.  分片规则丰富,插件化开发,易于扩展

12.  强大的web,命令行监控

13.  支持前端作为mysql通用代理,后端JDBC方式支持Oracle,DB2,SQL server,MongoDB

14.  集群基于zookeeper管理,在线升级,扩容,智能优化,大数据处理

1.2 MyCAT典型应用场景:

1.      典型的读写分离,此时配置最为简单,支持读写分离,主从切换

2.      分库分表,对于超过1000万的表进行切分,最大支持1000亿级别的单表分片

3.      多租户应用,每个应用一个库,但应用程序只连接MyCAT,从而改造程序本身,实现多租户化

4.      报表系统,借助于Mycat的分表能力,处理大规模报表的统计

1.3 数据库的切分方式:

何为数据(系统)切分?

简单来说,就是通过某种特定条件,按照某个维度(或库或表级别)将我们存放在同一个数据库中的数据分散存放到多个数据库主机上以达到分散单库(主机)负载的效果

1.3.1 切分模式:

1.3.2 垂直切分:

一个数据由很多表构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力负载到不同的库上面

a)      优点:拆分后业务清晰,拆分规则明确,数据维护简单,系统之间整合或者扩展容易

b)      缺点:部分业务表无法join,只能通过接口方式解决,提高了系统复杂度,受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高,事务处理复杂

1.1.1 水平切分:

相对于垂直切分,水平切分不是将表的数据做分类,而是按照某个字段的某种规则来分散到多个库中,每个表中包含一部分数据,简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,即将表中的某些行切分到一个数据库中,而另外的某些行又切分到其他数据库中,主要有分表,分库两种模式

a)      优点:不存在单库大数据,高并发的性能瓶颈,对应用透明,应用端改造较少,按照合理拆分规则拆分,join操作基本避免跨库,提高了系统的稳定性跟负载能力

b)      缺点:拆分规则难以抽象,分片事务一致性难以解决,数据多次扩展难度跟维护量极大,跨库join性能较差

1.1.1 切分的处理难点:

无论哪种切分方式,他们存在的共同缺点有:引入分布事务的问题,跨节点的join问题,跨节点合并排序分页的问题

1.1.2 针对数据源的管理,目前主要有两种思路:

1.      客户端模式,在每个应用程序模块中配置管理自己需要的一个或者多个数据源,直接访问各个数据库,在模块内完成数据的整合,优点是相对简单,没有性能的损耗

2.      通过中间代理层来统一管理所有数据源,后端数据库集群对前端应用程序透明,优点是比较通用,改造少

1.1.3 切分原则:

1.      尽量不切分,架构是进化而来,数据量也是慢慢增加上来,不是一蹴而就

2.      最大可能的找到最合适的切分难度

3.      由于数据库中间件对数据join实现的优劣难以把握,而且实现高性能难度极大,业务读取尽量少使用多表join

4.      尽量通过数据冗余,分组避免数据跨库的多表join

5.      尽量避免分布式事务

6.      单表切分数据最好在1000万行以内

第2章 Mycat架构说明:

2.1 基本架构:

标准的读写分离主从模式,主节点负责写操作,从节点负责读操作

1.1 mycat服务器配置高可用:

haproxy+mycat,应用简单,又可以避免mycat服务器的单间故障

1.1 多节点分布式集群:

增加集群中的读节点,进行负载,分担数据库压力,同时,解决mysql高可用的问题,实现故障自动切换;

我们今天配置的就是两套这样的集群

第1章 MyCAT基础架构:

1.1 环境准备:

db01 :

mysql多实例 : 5306-5307-5308-5309

db02:

mysql多实例 : 6306-6307-6308-6309

说明:相当于一共八台mysql服务器

1.1.1 所有mysql服务器hosts文件进行解析,不然启动mycat时会报错

cat /etc/hosts
127.0.0.1 db02  localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
db01 10.0.0.51
db02 10.0.0.52
db03 10.0.0.53

说明:虚拟机资源限制,每台机器共四个实例,其中,两个节点互为主从

1.1.2 所有实例的配置文件:除端口不同外其他均相同

[[email protected] 6306]# cat my.cnf
[mysqld]
basedir=/application/mysql
datadir=/data/6306
socket=/data/6306/mysql.sock
log-error=/data/6306/mysql.log
log_bin=/data/6306/mysql-bin
binlog_format=row
skip_name_resolve=1
server_id=6306
port=6306
log_slave_updates=1           强制生成从节点的中继日志

1.2 环境部署:

多实例的部署前面文档有,这里省略

1.2.1 db01和db02初始化数据:

for i in {6..9};do /application/mysql/scripts/mysql_install_db --defaults-file=/data/530${i}/my.cnf --user=mysql --basedir=/application/mysql --datadir=/data/530${i} ; done
for i in {6..9};do /application/mysql/scripts/mysql_install_db --defaults-file=/data/630${i}/my.cnf --user=mysql --basedir=/application/mysql --datadir=/data/630${i} ; done

1.2.2 启动两台机器上的多实例:

for i in {6..9};do mysqld_safe --defaults-file=/data/530${i}/my.cnf --pid-file=/data/530${i}/530${i}.pid  & >/dev/null 2>&1 ;done

1.2.3 检查端口是否开启:

[[email protected] data]# ss -tunlp|grep 530
tcp    LISTEN     0      80       :::5306                 :::*                   users:(("mysqld",pid=4537,fd=11))
tcp    LISTEN     0      80       :::5307                 :::*                   users:(("mysqld",pid=4540,fd=11))
tcp    LISTEN     0      80       :::5308                 :::*                   users:(("mysqld",pid=4539,fd=11))
tcp    LISTEN     0      80       :::5309                 :::*                   users:(("mysqld",pid=4538,fd=11))
[[email protected] data]# ss -tunlp|grep 630
tcp    LISTEN     0      80       :::6306                 :::*                   users:(("mysqld",pid=4225,fd=11))
tcp    LISTEN     0      80       :::6307                 :::*                   users:(("mysqld",pid=4226,fd=11))
tcp    LISTEN     0      80       :::6308                 :::*                   users:(("mysqld",pid=4223,fd=11))
tcp    LISTEN     0      80       :::6309                 :::*                   users:(("mysqld",pid=4227,fd=11))

1.2.4 清除所有实例上的二进制日志:

for i in {6..9};do mysql -S /data/530${i}/mysql.sock -e 'reset master';done
for i in {6..9};do mysql -S /data/630${i}/mysql.sock -e 'reset master';done

1.2.5 检查日志是否刷新:

for i in {6..9};do mysql -S /data/530${i}/mysql.sock -e 'show master status';done
for i in {6..9};do mysql -S /data/630${i}/mysql.sock -e 'show master status';done

1.3 做5306与6306的双主:

db01创建用户:

grant all on *.* to [email protected]'10.0.0.%' identified by '123';

db02操作:

CHANGE MASTER TO
MASTER_HOST='10.0.0.51',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=5306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=120;
start slave;

db01操作:

CHANGE MASTER TO
MASTER_HOST='10.0.0.52',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=6306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=120;
start slave;

db01的5306和db02的6306双主构建完毕

1.4 构建5307指向5306的主从:

db01上操作:

CHANGE MASTER TO
MASTER_HOST='10.0.0.51',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=5306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=120;
start slave;

1.5 构建6307指向6306的主从:

db02上操作:

CHANGE MASTER TO
MASTER_HOST='10.0.0.52',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=6306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=120;
start slave;

1.6 构建db01的5308和db02的6308双主:

db01操作:

grant all on *.* to [email protected]'10.0.0.%' identified by '123';

db02操作:

CHANGE MASTER TO
MASTER_HOST='10.0.0.51',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=5308,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=120;
start slave;

db01操作:

CHANGE MASTER TO
MASTER_HOST='10.0.0.52',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=6308,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=120;
start slave;

1.7 构建5309指向5308的主从:

CHANGE MASTER TO
MASTER_HOST='10.0.0.51',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=5308,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=120;
start slave;

1.8 构建6309指向6308的主从:

CHANGE MASTER TO
MASTER_HOST='10.0.0.52',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=6308,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=120;
start slave;

基本架构部署完毕

第2章 安装mycat:

2.1 环境准备:

安装java运行环境

yum -y install java

下载mycat软件:

http://dl.mycat.io/1.6-RELEASE

2.2 解压mycat:

tar xf Mycat-server-1.6.5-release-20180117003034-linux.tar.gz

2.3 启动服务:

[[email protected] bin]# ./mycat start
Starting Mycat-server...
ss -tunlp|grep 8066
tcp    LISTEN     0      100      :::8066                 :::*                   users:(("java",pid=6581,fd=79))

2.4 conf目录文件说明:

[[email protected] conf]# pwd
/server/tools/mycat/conf
-rwxrwxrwx 1 root root 4794 Jan 17 00:30 rule.xml

分片策略的定义配置

-rwxrwxrwx 1 root root 4219 Jan 17 00:30 schema.xml

逻辑库,高可用,读写分离,分片规则调用

-rwxrwxrwx 1 root root 4623 Jan 17 00:30 server.xml

mycat服务自身相关的配置信息

2.4.1 schema.xml配置文件说明:

<schema>

标签用于定义Mycat实例中的逻辑库,逻辑库的概念和mysql数据库中的database的概念相同

dataNode

dataNode标签定义了MyCat中的数据节点,用于绑定逻辑库到某个具体的database。

<dataNode name="dn1" dataHost="lch3307" database="db1" ></dataNode>

dataNode标签定义了MyCat中的数据节点,也就是我们通常说所的数据分片。一个dataNode标签就是一个独立的数据分片。

例子中所表述的意思为:使用名字为lch3307数据库实例上的db1物理数据库,这就组成一个数据分片,最后,我们使用名字dn1

 checkSQLschema

当该值设置为true时,如果我们执行语句select * from TESTDB.travelrecord;则MyCat会把语句修改为select * from travelrecord;。即把表示schema的字符去掉,避免发送到后端数据库执行时报(ERROR 1146 (42S02): Table ‘testdb.travelrecord’ doesn’t exist)。不过,即使设置该值为true ,如果语句所带的是并非是schema指定的名字,例如:select * from db1.travelrecord;那么MyCat并不会删除db1这个字段,如果没有定义该库的话则会报错,所以在提供SQL语句的最好是不带这个字段。

当设置为false时,则会把语句原封不动的发往最终的MySQL

SQLmaxlimit

当该schema中有分片表时,才会生效

当该值设置为某个数值时。每条执行的SQL语句,如果没有加上limit语句,MyCat也会自动的加上所对应的值。例如设置值为100,执行**select * from TESTDB.travelrecord;**的效果为和执行**select * from TESTDB.travelrecordlimit 100;**

table标签

<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" >
</table>

Table标签定义了MyCat中的逻辑表,所有需要拆分的表都需要在这个标签中定义。

rule属性

该属性用于指定逻辑表要使用的规则名字,规则名字在rule.xml中定义,必须与tableRule标签中name属性属性值一一对应。

type属性

该属性定义了逻辑表的类型,目前逻辑表只有“全局表”和”普通表”两种类型。对应的配置:

全局表:global。

普通表:不指定该值为globla

name属性:

定义数据节点的名字,这个名字需要是唯一的,我们需要在table标签上使用这个名字,来建立表与分片的对应关系

dataHost属性

该属性用于定义该分片属于哪个数据库实例的,属性值是引用dataHost标签上定义的name属性

database属性

该属性用于定义该分片属性哪个具体数据库实例上的具体库,因为这里使用两个维度来定义分片,就是:实例+具体的库,因为每个库上建立的表和表结构是一样的,所以这样做就可以轻松的对表进行水平拆分

hearbeat标签

这个标签内指明用于和后端数据库进行心跳检查的语句,例如:mysql可以使用select user(),Oracle可以使用select 1 from test等

writeHost标签,readHost标签

这两个标签都指定后端数据库的相关配置给mycat,用于实例化后端连接池,唯一不用的是,writeHost指定写实例,readHost指定读实例,在一个dataHost内可以定义多个writeHost和readHost,但是如果writeHost指定的后端数据库宕机,那么这个writeHost绑定的所有readHost都将不可用,另一方面,由于这个writeHost宕机系统会自动的检测到,并切换到备用的writeHost上去

host属性

用于标识不同实例

url属性

后端实例连接地址

user和password属性

mycat登录逻辑库的用户名和密码

weight属性

权重,配置在readHost中作为读节点的权重

balance属性

负载均衡类型,目前的取值有3种:

1. balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。

2. balance="1",全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡。

3. balance="2",所有读操作都随机的在writeHost、readhost

writeType属性

负载均衡类型,目前的取值有2种:

writeType="0", 所有写操作发送到配置的第一个writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties.

2. writeType=“1”,所有写操作都随机的发送到配置的writeHost,但不

switchType属性

-1表示不自动切换

1 默认值,自动切换

2 基于mysql主从同步的状态决定是否切换

temReadHostAvaiable属性

如果配置了这个属性,writeHost下面的readHost仍旧可用,默认0, 1表示开启

2.4.2 server.xml配置文件说明:

server.xml中重点需要关注的标签是用于定义登录mycat的用户和权限

<user name="test">
<property name="password">test</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
<property name="benchmark">11111</property>
<property name="usingDecrypt">1</property>
</user>

上面的例子中,我定义了一个用户,用户名为test、密码也为test,可访问的schema也只有TESTDB一个。如果我在schema.xml中定义了多个schema,那么这个用户是无法访问其他的schema。在mysql客户端看来则是无法使用use切换到这个其他的数据库。

如果使用了use命令,则mycat会报出这样的错误提示:

ERROR 1044 (HY000): Access denied for user 'test' to database 'xxx'

Mysql连接相关属性

初始化mysql前后端连接所涉及到的一些属性:

packetHeaderSize: 指定Mysql协议中的报文头长度。默认4。

maxPacketSize: 指定Mysql协议可以携带的数据最大长度。默认16M。

idleTimeout: 指定连接的空闲超时时间。某连接在发起空闲检查下,发现距离上次使用超过了空闲时间,那么这个连接会被回收,就是被直接的关闭掉。默认30分钟,单位毫秒。

charset: 连接的初始化字符集。默认为utf8。

txIsolation: 前端连接的初始化事务隔离级别,只在初始化的时候使用,后续会根据客户端传递过来的属性对后端数据库连接进行同步。默认为REPEATED_READ,设置值为数字默认3。

READ_UNCOMMITTED = 1;
READ_COMMITTED = 2;
REPEATED_READ = 3;
SERIALIZABLE = 4;

sqlExecuteTimeout:SQL执行超时的时间,Mycat会检查连接上最后一次执行SQL的时间,若超过这个时间则会直接关闭这连接。默认时间为300秒,单位秒。

服务相关的属性

bindIp: mycat服务监听的IP地址,默认值为0.0.0.0。

serverPort: 定义mycat的使用端口,默认值为8066

managerPort: 定义mycat的管理端口,默认值为9066。

2.4.3 rule.xml配置文件说明:

rule.xml里面就定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法,或者对表使用相同的算法但具体的参数不同。这个文件里面主要有tableRule和function这两个标签。在具体使用过程中可以按照需求添加tableRule和function。

?tableRule标签

这个标签定义表规则。

定义的表规则,在schema.xml:

<tableRulename="rule1">
<rule>
<columns>id</columns>
<algorithm>hash-int</algorithm>
</rule>
</tableRule>

name 属性指定唯一的名字,用于标识不同的表规则。

内嵌的rule标签则指定对物理表中的哪一列进行拆分和使用什么路由算法。

columns 内指定要拆分的列名字。

algorithm 使用function标签中的name属性。连接表规则和具体路由算法。当然,多个表规则可以连接到同一个路由算法上。table标签内使用。让逻辑表使用这个规则进行

第3章 配置mycat读写分离:

3.1 案例一:简单读写分离配置

db01上创建用户:

grant all on *.* to [email protected]'10.0.0.%' identified by'123456';

3.1.1 修改schema配置文件:

[[email protected] conf]# vim schema.xml
 
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
 
<dataNode name="dn1" dataHost="localhost1" database= "jiang" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="db1" url="10.0.0.51:5306" user="root" password="123456">
<readHost host="db2" url="10.0.0.51:5307" user="root" password="123456" />
</writeHost>
</dataHost>
</mycat:schema>

重启mycat服务加载配置

[[email protected] conf]# ../bin/mycat  restart

3.1.2 测试是否负载均衡:

[[email protected] mycat]# mysql -uroot -p123456 -h127.0.0.1 -P8066
mysql> show variables like '%server_id%';
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| server_id      | 5307  |               #读节点为5307
| server_id_bits | 32    |
+----------------+-------+
2 rows in set (0.01 sec)

3.1.3 测试写节点是否为db1:

[[email protected] ~]# mysql -S /data/5307/mysql.sock
mysql> set global read_only=1;
[[email protected] mycat]# mysql -uroot -p123456 -h127.0.0.1 -P8066
mysql> use TESTDB;
mysql> create table test(id int);
Query OK, 0 rows affected (0.48 sec)       #写成功

3.2 案例二:四节点读写分离+高可用:

配置文件:

<?xml version="1.0"?> 
<!DOCTYPE mycat:schema SYSTEM "schema.dtd"> 
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema> 
 
<dataNode name="dn1" dataHost="localhost1" database= "mysql" /> 
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat> 
<writeHost host="db1" url="10.0.0.51:5306" user="root" password="123456">
<readHost host="db2" url="10.0.0.51:5307" user="root" password="123456" />
</writeHost>
<writeHost host="db3" url="10.0.0.52:6306" user="root" password="123456">
<readHost host="db4" url="10.0.0.52:6307" user="root" password="123456" />
</writeHost>
</dataHost> 
</mycat:schema>

注:以上配置中,只有db1复制写操作,其他三个节点负责读操作,当db1宕机时,db3会接管db1写操作,db4负责读操作

3.2.1 测试负载均衡是否正常:

mysql> show variables like '%server_id%';
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| server_id      | 5307  |
| server_id_bits | 32    |
+----------------+-------+
2 rows in set (0.01 sec)
 
mysql> show variables like '%server_id%';
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| server_id      | 6307  |
| server_id_bits | 32    |
+----------------+-------+
2 rows in set (0.03 sec)

3.2.2 宕掉db1:

[[email protected] ~]# mysqladmin -S /data/5306/mysql.sock shutdown

3.2.3 测试写操作是否由db3执行:

[[email protected] 6306]# mysql -S /data/6307/mysql.sock         6307设置为只读,然后进行写操作
mysql> set global read_only=1;
mysql> insert into t1 values(1);
Query OK, 1 row affected (0.18 sec)

3.3 垂直分库

修改配置文件:

<?xml version="1.0"?> 
<!DOCTYPE mycat:schema SYSTEM "schema.dtd"> 
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema> 
<schema name="mysql" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn2">
</schema>
    <dataNode name="dn1" dataHost="localhost1" database= "jiang" /> 
    <dataNode name="dn2" dataHost="localhost2" database= "mysql" /> 
    <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1" >
        <heartbeat>select user()</heartbeat> 
    <writeHost host="db1" url="10.0.0.51:5306" user="root" password="123456">
            <readHost host="db2" url="10.0.0.51:5307" user="root" password="123456" />
    </writeHost>
    <writeHost host="db3" url="10.0.0.52:6306" user="root" password="123456">
            <readHost host="db4" url="10.0.0.52:6307" user="root" password="123456" />
    </writeHost>
    </dataHost>
    <dataHost name="localhost2" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1" >
        <heartbeat>select user()</heartbeat> 
    <writeHost host="db11" url="10.0.0.51:5308" user="root" password="123456">
            <readHost host="db22" url="10.0.0.51:5309" user="root" password="123456" />
    </writeHost>
    <writeHost host="db33" url="10.0.0.52:6308" user="root" password="123456">
            <readHost host="db44" url="10.0.0.52:6309" user="root" password="123456" />
    </writeHost>
    </dataHost>
</mycat:schema>
修改server.xml文件:
[[email protected] conf]# vim server.xml
        <user name="root" defaultAccount="true">
                <property name="password">123456</property>
                <property name="schemas">TESTDB,mysql</property>

重启服务:

[[email protected] conf]# ../bin/mycat  restart

检查数据库:

[[email protected] 6306]# mysql -uroot -p123456 -h127.0.0.1 -P8066
mysql> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB   |
| mysql    |
+----------+
2 rows in set (0.03 sec)

3.4 垂直分表:

<?xml version="1.0"?> 
<!DOCTYPE mycat:schema SYSTEM "schema.dtd"> 
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
    <table name="wp_users" dataNode="dn1"/>
    <table name="wp_usermeta" dataNode="dn2"/>
</schema> 
 
    <dataNode name="dn1" dataHost="localhost1" database= "wordpress" />
    <dataNode name="dn2" dataHost="localhost2" database= "wordpress" />
    <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1" >
        <heartbeat>select user()</heartbeat> 
    <writeHost host="db1" url="10.0.0.51:5306" user="root" password="123456">
            <readHost host="db2" url="10.0.0.51:5307" user="root" password="123456" />
    </writeHost>
    <writeHost host="db3" url="10.0.0.52:6306" user="root" password="123456">
            <readHost host="db4" url="10.0.0.52:6307" user="root" password="123456" />
    </writeHost>
    </dataHost>
    <dataHost name="localhost2" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1" >
        <heartbeat>select user()</heartbeat> 
    <writeHost host="db11" url="10.0.0.51:5308" user="root" password="123456">
            <readHost host="db22" url="10.0.0.51:5309" user="root" password="123456" />
    </writeHost>
    <writeHost host="db33" url="10.0.0.52:6308" user="root" password="123456">
            <readHost host="db44" url="10.0.0.52:6309" user="root" password="123456" />
    </writeHost>
    </dataHost>
</mycat:schema>
修改server配置文件:
vim server.xml
                <user name="root" defaultAccount="true">
                <property name="password">123456</property>
                <property name="schemas">TESTDB</property>

3.5 分片设置:

1.      分片节点:

数据切分后,一个大表被分到不同的分片数据库上面,每个表分片所在的数据库就是分片节点

2.      节点主机:

数据切分后,每个分片节点(dataNode)不一定都会独占一台机器,同一机器扇面可以有多个分片数据库,这样一个或多个分片节点,所在的机器就是界定啊主机(dataHost),为了规避节点主机并发数限制,尽量将读写压力高的分片节点均衡的放在不同的节点主机

<?xml version="1.0"?> 
<!DOCTYPE mycat:schema SYSTEM "schema.dtd"> 
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
<table name="wp_usermeta" dataNode="dn1,dn2" rule="auto-sharding-long" >
</table>
</schema> 
 
    <dataNode name="dn1" dataHost="localhost1" database= "wordpress" />
    <dataNode name="dn2" dataHost="localhost2" database= "wordpress" />
    <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1" >
        <heartbeat>select user()</heartbeat> 
    <writeHost host="db1" url="10.0.0.51:5306" user="root" password="123456">
            <readHost host="db2" url="10.0.0.51:5307" user="root" password="123456" />
    </writeHost>
    <writeHost host="db3" url="10.0.0.52:6306" user="root" password="123456">
            <readHost host="db4" url="10.0.0.52:6307" user="root" password="123456" />
    </writeHost>
    </dataHost>
    <dataHost name="localhost2" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1" >
        <heartbeat>select user()</heartbeat> 
    <writeHost host="db11" url="10.0.0.51:5308" user="root" password="123456">
            <readHost host="db22" url="10.0.0.51:5309" user="root" password="123456" />
    </writeHost>
    <writeHost host="db33" url="10.0.0.52:6308" user="root" password="123456">
            <readHost host="db44" url="10.0.0.52:6309" user="root" password="123456" />
    </writeHost>
    </dataHost>
</mycat:schema>

3.6 范围分片:

此分片适用于提前规划好字段某个范围属于哪个分片

vim rule.xml
<tableRule name="auto-sharding-long">
                <rule>
                        <columns>umeta_id</columns>
                        <algorithm>rang-long</algorithm>
                </rule>
vim autopartition-long.txt
1-9=0
10-18=1

3.7 全局表:

在数据切分处理中,特别是水平切分中,中间件最终要的两个处理过程就是数据的切换和数据的聚合,选择合适的切分规则,至关重要,因为他决定了后续数据聚合的难易程度,甚至可以避免跨库的数据聚合处理

3.7.1 Mycat全局表:

如果你的业务中有些数据类似于数据字典,比如配置文件的配置,常用业务的配置或者数据量不大很少变动的表,这些表往往不是特别大,而且大部分的业务场景都会用到,那么这种表适合于Mycat全局表,无须对数据进行切分,只要在所有的分片上保存一份数据即可,Mycat在Join操作中,业务表与全局表进行Join聚合会优先选择相同分片内的全局表join,避免跨库Join,在进行数据插入操作时,mycat将把数据分发到全局表对应

<table name="t_area" primaryKey="id" type="global" dataNode="dn1,dn2" />

3.8 ER分片:

有一类业务,例如订单跟订单明细,明细表会依赖于订单表,也就是说会存在表的主从关系,这类业务的切分可以抽象出合适的切分规则,比如根据用户ID切分,其他相关的表都依赖于用户ID,在或者根据订单的ID切分,总之部分业务总会可以抽象出父子关系的表,这类的表的使用与ER分片表,子表的记录与所关联的父表记录存放在同一个数据分片上,避免数据join跨库操作

<table name="orders" dataNode="dn1,dn2" rule="mod-long">
<childTable name="order_detail" primaryKey="id" joinKey="order_id" parentKey="order_id" />
</table>

3.9 枚举分片:

通过在配置文件中配置可能的枚举id,自己配置分片,本规则适用于特定的场景,比如有些业务需要按照省份或者区县来保存,而全国省份区县都是固定的,这种情况比较适用

<tableRule name="sharding-by-intfile">
<rule> <columns>user_id</columns>
<algorithm>hash-int</algorithm>
</rule>
</tableRule>
<function name="hash-int" class="org.opencloudb.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
<property name="type">0</property>
<property name="defaultNode">0</property>
</function>

修改partition-hash-int.txt 配置:

10000=0
10010=1
DEFAULT_NODE=1

columns 标识将要分片的表字段,algorithm 分片函数, 其中分片函数配置中,mapFile标识配置文件名称

3.10 分片的原则:

?原则一:能不分就不分,1000万以内的表,不建议分片,通过合适的索引,读写分离等方式,可以很好的解决性能问题。

?原则二:分片数量尽量少,分片尽量均匀分布在多个DataHost上,因为一个查询SQL跨分片越多,则总体性能越差,虽然要好于所有数据在一个分片的结果,只在必要的时候进行扩容,增加分片数量。

?原则三:分片规则需要慎重选择,分片规则的选择,需要考虑数据的增长模式,数据的访问模式,分片关联性问题,以及分片扩容问题,最近的分片策略为范围分片,枚举分片,一致性Hash分片,这几种分片都有利于扩容

?原则四:尽量不要在一个事务中的SQL跨越多个分片,分布式事务一直是个不好处理的问题

?原则五:查询条件尽量优化,尽量避免Select * 的方式,大量数据结果集下,会消耗大量带宽和CPU资源,查询尽量避免返回大量结果集,并且尽量为频繁使用的查询语句建立索引。

总体上来说,分片的选择是取决于最频繁的查询SQL的条件,因为不带任何Where语句的查询SQL,会便利所有的分片,性能相对最差,因此这种SQL越多,对系统的影响越大,所以我们要尽量避免这种SQL

原文地址:http://blog.51cto.com/13520772/2103699

时间: 2024-11-09 11:19:28

MyCAT技术的相关文章

读《专访Mycat核心开发成员王金剑 :借助Mycat轻松抵御海量并发》总结

原文网址:http://www.csdn.net/article/2015-12-23/2826546 1.Mycat是一个开源的分布式数据库系统,其核心功能是分表分库,即将一个大表水平分割为多个小表,存储在后端MySQL或者其他数据库里. 2.加入Mycat给我最大的感受是开源团队的工作效率和参与热情是非常高的,这让我深信中国开源产品的发展前景不可限量.核心成员里有两个人给我的印象特别深刻:一个是吴京润(网名坨神),他是来自Wifiin的高级工程师,还有一个是邓立仁(网名聆听),他是来自小米的

net Core 使用MyCat分布式数据库,实现读写分离

net Core 使用MyCat分布式数据库,实现读写分离 目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 MyCat2.0版本很快就发布了,关于MyCat的动态和一些问题,大家可以加一下MyCat的官方QQ群:106088787.我们今天主要介绍一下,在我们的Asp.net Core中如何使用Mycat,这源于一个大神(Amamiya Yuuko)的分享,但是,这中间还是有少许的 坑 : 首先,因为大神是比较忙的,而且主要分享关键技术,所以有些地方很简略,而往往这些简

MYCAT介绍

从定义和分类来看,它是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里. MyCat发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL.SQL Server.Oracle.

mycat 不得不说的缘分

                                  1,愕然回首,它在灯火阑珊处 关于mysql集群中间件,以前写在应用程序里面,由开发人员实现,在配置文件里面写多个数据源,写库一个数据源,读库一个数据源,笨拙不高效,由于程序员的差异化,效果并不是特别理想. 后来,组织了开发人员写了一个自动识别读写的功能模块接口,让开发人员调用,这样能满足特定场景的业务需求,但是适应性比较窄. 后来出了cobar,但是在高并发这里出壳了,后来在一次无意中的演讲中,见到leader在介绍了myca

MySQL分库分表之MyCat实现(五)

一 .分库分表 什么是分库分表? 分库分表就是为了解决由于数据量过大而导致数据库性能降低的问题,将原来独立的数据库拆分成若干数据库组成,将数据大表分成若干数据表组成,使得单一数据库.单一数据表的数据量变小,从而达到提升数据库性能的目的. 2.分库分表的方式 2.1分库: 1.垂直分库:是指按照业务将表进行分类,分布到不同的数据库上面,每个库可以放不同的服务器上,它的核心理念是专库专用. 2水平分库:把同一个表的数据按一定规则拆分到不同的数据库中,每个库可以放不同的服务器上 2.2分表: 1.垂直

架构设计:系统存储(14)——MySQL横向拆分与业务透明化(2)

接上文<架构设计:系统存储(13)--MySQL横向拆分与业务透明化(1)> 4-6.主要分片规则 上文提到MyCat的逻辑表支持多种分片规则,表现于schema配置文件中中table标签的rule属性.本节将以MyCat Version 1.6版为基础,介绍几种经常使用的分片规则,这些分片规则都通过rule.xml文件进行定义和配置. 4-6-1.分片枚举sharding-by-intfile ...... <tableRule name="sharding-by-intfi

数据库中间件__mycat

摘要:MyCat截至到2015年4月,保守估计已经有超过60个项目在使用,主要应用在电信领域.互联网项目,大部分是交易和管理系统,少量是信息系统.比较大的系统中,数据规模单表单月30亿.本文带你全面了解MyCat. 为什么需要MyCat? 虽然云计算时代,传统数据库存在着先天性的弊端,但是NoSQL数据库又无法将其替代.如果传统数据易于扩展,可切分,就可以避免单机(单库)的性能缺陷. MyCat的目标就是:低成本地将现有的单机数据库和应用平滑迁移到"云"端,解决数据存储和业务规模迅速增

QQRobot

昨天在MyCat技术群众看到他们做了一个QQ机器人,能够自动回复群友们的问题以及方便QQ群的管理,遂想弄清楚到底是怎么做出来的,,咨询未果,上网搜索... 解决方案有二: 1.直接使用网上已有软件(但是获取全部功能需注册,不划算),测试了一下,功能很全,但是想破解无从下手,作业太多暂搁. 相关网址: 晨风机器人:http://www.cfxy.me/productinfo.php?id=26 吾爱破解:http://www.52pojie.cn/(需邀请码,¥12一个,这年头都不容易,我还没注册

JavaWeb网站技术架构

JavaWeb网站技术架构总结 题记 工作也有几多年了,无论是身边遇到的还是耳间闻到的,多多少少也积攒了自己的一些经验和思考,当然,博主并没有太多接触高大上的分布式架构实践,相对比较零碎,随时补充(附带架构装逼词汇). 俗话说的好,冰冻三尺非一日之寒,滴水穿石非一日之功,罗马也不是一天就建成的,当然对于我们开发人员来说,一个好的架构也不是一蹴而就的. 初始搭建 开始的开始,就是各种框架一搭,然后扔到Tomcat容器中跑就是了,这时候我们的文件,数据库,应用都在一个服务器上. 服务分离 随着系统的