MyCat入门

MyCat架构

MyCat作为一款分布式数据库中间件,用于解决单机关系型数据库扩展性问题,具备轻量(无状态)、灵活、稳定、高效等特性。

MyCat对上层应用提供MySQL服务,使得应用可以像使用单机MySQL一样查询MyCat。对下层可以接入各种关系型数据库。MyCat接收应用的SQL,根据预先配置好的路由规则将SQL下发给底层数据库,汇总后返回给上层应用。

初始化MyCat

2.1 底层数据库信息配置

从架构图上可以了解到MyCat是一款数据库中间件,所以首先需要配置schema与底层的数据库节点上具体业务库的关系。

配置的前提条件:1、所有底层数据库已正确安装并启动;2、MyCat可以通过指定的用户名、密码连接所有底层数据库;3、所有底层数据库已创建好业务库。

以上3点都满足的情况下,可以通过 $MyCat_HOME/conf/schema.xml 文件来配置底层数据库。需要配置 dataNode 和 dataHost 2个标签。

dataNode为数据库分片对应的是逻辑库,dataHost是数据库实例对应物理数据库(或读写分离、高可用集群)。所以dataNode需要基于dataHost,而dataHost配置可以分为单主、主从、主备等。

2.1.1 dataNode标签

name:定义数据节点的名字,这个名字需要是唯一的,我们需要在table 标签上应用这个名字,来建立表与分片对应的关系。建议直接命名为dn1、dn2 …… dnN。

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

database:该属性用于定义该分片属于数据库实例上的哪个具体库。配置的库必须在数据库实例上已存在,MyCat不会自动创建。

2.1.2 dataHost标签

name:唯一标识dataHost 标签,供上层的dataNode标签使用。

maxCon、minCon:最大、最小连接数,没有特殊需求不要改动。

balance:负载均衡类型:

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 上分发。

4. balance=”3″,所有读请求随机的分发到writeHost对应的readHost 执行,writeHost不负担读压力

writeType:负载均衡类型,配置为0。

dbType:数据库类型指定后端连接的数据库类型,目前支持二进制的mysql、postgresql协议,还有其他使用JDBC 连接的数据库。例如:mongodb、oracle、spark 等。

dbDriver:指定连接后端数据库使用的Driver,目前可选的值有native 和JDBC。除mysql、postgresql配置native以外,其他数据库种类都配置JDBC。

switchType:故障切换类型,-1 表示不自动切换,1 默认值,自动切换。没有特殊需求请配置为1。

2.1.3 heartbeat标签

这个标签内指明用于和后端数据库进行心跳检查的语句。每个数据库不尽相同,例:

数据库heartbeat语句
postgresqlselect 1
mysqlselect 1
oracleselect 1 from dual

2.1.4 writeHost、readHost标签

这两个标签都指定后端数据库的相关配置给MyCat,用于实例化后端连接池。唯一不同的是,writeHost 指定写实例、readHost 指定读实例。

在一个dataHost 内可以定义多个writeHost 和readHost。但是,如果writeHost 指定的后端数据库宕机,那么这个writeHost 绑定的所有readHost 都将不可用。另一方面,由于这个writeHost 宕机系统会自动的检测到,并切换到备用的writeHost 上去。

host:用于标识不同实例,建议一般writeHost 使用hostM1、hostM2…hostMN,readHost 用hostS1、hostS2…hostSN。

url:后端实例连接地址,如果是使用native 的dbDriver,则一般为address:port 这种形式。用JDBC 或其他的dbDriver,则需要特殊指定。当使用JDBC 时则可以这么写:jdbc:mysql://localhost:3306/。

user:后端存储实例需要的用户名。

password:后端存储实例需要的密码。

2.1.5 配置样例

注意:MyCat不会实时读取修改后的配置文件!配置完成后请重启MyCat使配置生效。如何重启MyCat请参考3.2.3 重启MyCat。

单主

1主+2只读从库(读写分离,读操作全下发到readHost上):

1主+1standby主库(高可用+读写分离:hostM1正常时:写操作发往hostM1,读操作随机发往hostM1、hostM2;hostM1不可用后会读写都自动切换到hostM2):

2.2 MyCat服务管理

底层数据库信息全部配置完成后需要重启MyCat服务才能使配置生效。

2.2.1 启动MyCat

# MyCat start

2.2.2 停止MyCat

# MyCat stop

2.2.3 重启MyCat

# MyCat restart

2.2.4 查看MyCat状态

# MyCat status

用户权限配置

MyCat用户权限通过$MyCat_HOME/conf/server.xml文件进行配置。

3.1 创建用户

通过在server.xml文件中新增一个user标签来新增一个用户。例:

创建了一个用户名为test的用户。其他属性含义如下:

password:密码

schemas:用户可访问的全部schema

readOnly:是否只读,不配该项则默认为否

benchmark:当前端的整体connection 数达到配置的值时, 对来自该账户的请求开始拒绝连接,不配该项则默认为不限制

3.2 表级别权限

表级别的权限控制通过privileges标签来控制:

对用户的schema 及下级的table 进行精细化的DML 权限控制,privileges 节点中的check 属性是用于标识是否开启DML 权限检查, 默认false 标识不检查,当然privileges 节点不配置,等同check=false,由于MyCat 一个用户的schemas 属性可配置多个schema ,所以privileges 的下级节点schema 节点同样可配置多个,对多库多表进行细粒度的DML 权限控制。

Schema/Table 上的dml 的4个数字分别对应insert,update,select,delete4个权限,如0010表示只能进行select操作,1010表示只能进行select和insert,但是不能delete或update。

若设置了schema , 但只设置了个别 table 或未设置 table 的DML,自动继承schema 的DML 属性。

逻辑表配置

4.1 schema配置

schema 标签用于定义MyCat 实例中的逻辑库,MyCat 可以有多个逻辑库,每个逻辑库都有自己的相关配置。可以使用schema 标签来划分这些不同的逻辑库。每张表都属于某一个逻辑库,所以table标签从属在schema标签内。

4.1.1 schema标签

schema 标签位于$MyCat_HOME/conf/schema.xml 文件中。

name:定义逻辑的名字,这个名字需要是唯一的。

checkSQLschema:MyCat下发SQL时是否会自动删除schema名,必须配置为true。

sqlMaxLimit:每条执行的SQL语句,如果没有加上limit语句,MyCat会自动的加上所对应的值。建议配置为100。

4.2 表路由规则配置

MyCat创建表需要先配置table标签。

4.2.1 table标签

name:定义逻辑表的表名,这个名字就如同在数据库中执行create table 命令指定的名字一样,同个schema 标签中定义的名字必须唯一。

dataNode:定义这个逻辑表所属的dataNode, 该属性的值需要和dataNode 标签中name 属性的值相互对应。

rule:该属性用于指定逻辑表要使用的规则名字,规则名字在rule.xml中定义(分片规则参见下一小节5.3 分片规则),必须与tableRule 标签中name 属性属性值一一对应。

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

4.3 路由规则配置

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

4.3.1 tableRule标签

name:定义表分发规则名,供table标签引用。定义的名字必须唯一,建议采用“表名-分发键-分发规则”的方式命名。

rule:包含columns和algorithm,指定对表中的哪一列进行拆分和使用什么路由算法

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

algorithm:对应function标签中的name属性。指定使用的具体路由算法。

4.3.2 function标签

除murmur算法中的count property以外,其他function标签不建议自行修改,如需修改请咨询DBA。

name:定义路由算法名,供tableRule标签引用。定义的名字必须唯一。

class:指定路由算法具体的类名字。

property:具体算法需要用到的一些属性。对于murmurhash算法,只需要根据dataNode数量来设置count属性值。

4.4 最佳实践

4.4.1 路由规则选择

MyCat支持多种路由规则,且配置较为复杂,若配置不当则数据分布不均衡,导致性能很低,无法线性扩展。

只推荐一般用户采用两种路由规则:1、全局表 2、Hash表。

建议小表(如字典表)且不经常更新的使用全局表。大表使用Hash表。分发字段选择参考下一小节5.4.2 分发键选择。

全局表即每个节点都有完整数据,仅需配置schema.xml 中的table标签,例:

一致性Hash需要配置rule.xml中的tableRule标签和schema.xml 中的table标签,例:

rule.xml:

schema.xml:

4.4.2 分发键选择

MyCat作为一个分布式中间件,数据是分布在各个数据节点上的。分发键的选择对于后期使用的性能影响非常大,所以必须要选择合适的分发键。

1、多表关联的查询,因为关联会下发到数据节点执行,所以必须保证所有表的分发规则与分发键完全一致(除全局表),并且在关联条件中包含分发键的相等条件。否则可能会导致查询结果不正确。

2、尽可能选择能使数据均匀分布在各个节点的分发键,如主键。如果数据分布不均匀,性能瓶颈就会出现在数据最多的节点上,导致其他节点很空闲,而都在等待该节点执行完成,造成性能低及资源浪费。

例如人员主题库类的业务,表之间查询、关联都是以人员为单位,而区分人员则使用的是公民身份号码。并且公民身份号码散列度非常高,可以保证数据均匀分布。所以这类业务里的绝大多数表都非常适合使用公民身份号码字段作为分发键。

MyCat基本操作

可以使用任意支持MySQL协议的客户端工具连接MyCat执行操作,如mysql client、Navicat for MySQL、HeidiSQL等,本文档不再赘述。

MyCAT支持SQL92标准,支持MySQL、PostgreSQL、Oracle、DB2、SQL Server等数据库的常见SQL用法。

5.1 create table

在第5节 逻辑表配置中已经定义了表的路由规则后,还需要在MyCat定义具体的表结构,通过create table语句实现。例:

5.2 insert

MyCat中的insert语法与标准SQL稍有不同,不支持不带列名的insert语句,必须在表名后显式的指定需要插入的列名。例:

5.3 select

select语句符合SQL92标准。例:

当从一个表查询数据时候,MyCat数据展现顺序是以MyCat先接收到的数据的顺序,每个dataNode的数据到达MyCat的顺序是不确定的,所以select的结果的顺序是不确定的,即使表中数据没有一点变化,这一点和单机数据库是不一样的,要想有序的输出结果,必须显示的加一个order by语句,强制输出的结果排序。

如果查询条件中包含分发字段,则MyCat会将SQL语句只下发到对应的节点;否则会下发到所有节点,可通过explain语句查看:

注意:多表关联的查询,因为关联会下发到数据节点执行,所以必须保证所有表的分发规则与分发键完全一致(除全局表),并且在关联条件中包含分发键的相等条件。否则可能会导致查询结果不正确。

5.4 update

update语句符合SQL92标准。例:

5.5 delete

delete语句符合SQL92标准。例:

java连接MyCat

6.1 设置CLASSPATH

将mysql-connector-java-8.0.15.jar添加到项目CLASSPATH中。

6.2 加载驱动

驱动名:com.mysql.cj.jdbc.Driver

连接URL:jdbc:mysql://hostname:[port]/[database]

例:

jdbc:mysql://172.16.105.8:8066/TESTDB

6.3 样例代码

开源数据库中间件对比

  • 流行中间件
 Mycatsharding-JDBCdbletddlcetuskingshardmaxscaleproxysqlpgpool
后端节点支持多种数据库多种数据库mysqlmysql、oraclemysqlmysqlmysqlmysqlpostgresql
水平拆分支持支持支持支持支持支持不支持不支持不支持
读写分离、负载均衡支持支持支持支持支持支持支持支持支持
元数据管理方式xml文件yaml文件xml文件diamond配置中心json文件配置文件配置文件配置文件配置文件
支持协议向上mysql协议,向下mysql、pg协议、jdbc协议jdbcmysql协议jdbcmysql协议mysql协议mysql协议mysql协议pg协议
备注基于cobar开发以jar包方式提供服务,严格意义上不等价于中间件基于mycat做了部分功能增强,但是只支持mysql去掉了其他数据库的支持开源版本7年前已不维护读写分离和分库是两个版本。原atlas成员使用Go开发mariadb发布的中间件  

还有一些未开源商用中间件,如:网易DDB、阿里DRDS、京东CDS、平民软件oneproxy等未纳入对比中。

大多数中间件只支持MySQL,仅Mycat与sharding-JDBC后端支持连接多种数据库。

  • 重点对比
 Mycatsharding-JDBC
开源
SQL 92标准支持80%的sql
后端支持的数据库MySQL,Oracle,SQLServer,db2和PostgreSQL等支持jdbc的数据库支持MySQL,Oracle,SQLServer和PostgreSQL等支持jdbc的数据库
NoSQL数据库支持(mongodb)不支持
架构Proxy形式基于 JDBC 的扩展
高可用性支持,主从关系需要在数据库层面配置不支持,主从切换以及主从数据同步为数据库范畴
读写分离支持,通过配置文件支持,通过配置文件
分库分表支持,通过配置文件支持,通过配置文件
分布式事务支持支持
扩容支持修改路由规则,但不支持数据重分布支持修改路由规则,但不支持数据重分布
子查询不支持复杂子查询不支持
分片策略枚举法、固定分片hash算法、范围约定、求模法、日期列分区法、一致性hash等等号、between、in、多分片键/Hash + Mod、Range、Tag
不足Insert into、复杂子查询、3表及以上跨库join等不支持,不适合 OLAP 的场景不适合 OLAP 的场景、不适合事务强一致的要求,仅支持java
管理配置界面
支持语言Java、python等支持mysql协议的语言仅java

PG索引对导入性能影响

测试环境

1.1 硬件环境

CPU内存数据
2路Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz 共24个逻辑核64G 2T sata*8

1.2 软件环境

操作系统:Red Hat Enterprise Linux Server release 7.4 (Maipo) 内核:3.10.0-693.el7.x86_64

PG:PostgreSQL 10.6

1.3 测试表

基础表结构:

CREATE TABLE test (

 a varchar(64),

 b varchar(64),

 c varchar(64),

 d varchar(64),

 e varchar(64),

 f varchar(64),

 g varchar(64),

 h varchar(64),

 i varchar(64),

 j varchar(64),

 k varchar(64),

 l TIMESTAMP

) ;

索引:

create index idx_1 on test(a);

create index idx_2 on test(b);

create index idx_3 on test(f);

create index idx_4 on test(i);

create index idx_5 on test(l);

数据样例:

9dfdd3a8-b65a-4705-a0ff-daf1819861d2 1111111111111111111 阿大 13888888888 陕H11111 546687257794821 460073102018579 a7:8e:c5:d3:2d:6c 4212922510 T1n5C9011216 2018-10-08 10:55:47

入库性能

2.1 总体结果

使用copy命令入库,每个文件1000W条,行长约180B。分别测试无索引、1个索引、3个索引、5个索引的导入性能。

2.1.1 测试结果

表中存量数据(千万)012345678910111213141516171819
no index2222222322232522252223222222222223232323
1 index(raid0*8)61797172741247678156781301297920280221209113247259
3 index(raid0*8)153214182275192324192362390419562121419142539328341694548500054638309
5 index(raid0*8)22622532725538743046798926002670295827863452426464821123619992   
3 index(单盘)136176185223177363202321207341309563329504       
5 index(单盘)185264282335242376419456355211663          

续:

表中存量数据(千万)2021222324252627282930313233343536
no index2222222222222322222223232322232223
1 index(raid0*8)271389396509567719875103697410161435158419731860207921187809

2.1.2 总结

  1. 索引对PG导入性能影响非常大。
  2. 在表数据量到达拐点之后(根据索引数及磁盘IO能力决定,即使只有1个索引),导入时间呈指数级增长。
  3. 更好的磁盘IO只能延缓拐点的到来,无法避免性能急剧降低。
  4. 根据上述实验结果,单表的数据量在小于7000W时,导入性能略有下降,但基本还算稳定。所以建议:
    • 实际使用时如果索引小于等于5个,单表数据量大于5000W条就必须采取如分区、分库、分表等措施,同时每个分区也不得超过5000W。
    • 如果索引大于5个,优先考虑降低索引个数,如过实在不能降低,则单个分区数据量不得大于2000W条。