开始使用MyCAT
MyCAT是基于阿里巴巴开源数据库中间件Cobar开发并维护的数据库中间件,弥补了Cobar无人维护的尴尬境地。详细介绍可以参考官网:http://mycat.io/
相比Cobar来说,MyCAT的坑算是少很多了,下面是开始使用MyCAT的一些步骤。
准备数据库
创建MySQL数据库实例
用Docker启动,其他安装方式不再介绍。
1 | docker run --name mysql-001 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.6 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci |
修改MySQL服务器配置
1 | [mysqld] |
其中lower-case-table-names=1
和max_allowed_packet=32M
为非默认参数:
lower-case-table-names=1
忽略表格名字大小写,否则MyCAT会无法找到表格max_allowed_packet=32M
该参数需要配合mysqldump,参考使用mysqldump
导出。
准备MyCAT
设置MyCAT虚拟schema
定义虚拟schema:schema.xml
1 |
|
<schema>
标签:
name="irenshi"
定义的数据库名称为irenshi
checkSQLschema="false"
不对select语句中的schema名称做处理。该值置为true
时,如果我们执行询句select * from TESTDB.travelrecord;
则MyCat会把询句修改为select * from travelrecord;
。即把表示schema字符去捧,避免发送到后端数据库执行时报:(ERROR1146 (42S02): Table ‘testdb.travelrecord’ doesn’t exist)。sqlMaxLimit="10000"
在selecct语句不指定limit
的时候,最多返回10000条数据dataNode="dn001"
在不使用<table>
指明的情况下,数据库表存放到dn001
节点
<table>
标签:<table>
标签不指定的数据库表均以<schema>
的设置为准,指定的话以指定的为准。
name="tab_sign_record_info"
指定要设置的数据库表primaryKey="id"
指定数据库表的主键。设置该值之后,如果MyCAT第一次执行主键查询时,会把请求发送到所有后端服务器,并且将主键所对应的数据库位置缓存,下次查询的时候直接根据该缓存向对应的数据库发送请求dataNode="dn001,dn002,dn003"
表明该表将被存放到dn001,dn002,dn003
三个MySQL中rule="sharding-by-company-id"
给出表中的数据如何分布到上边给定的三个MySQL中
<dataNode>
标签:<dataNode
标签定义MyCAT的数据节点。每个数据节点定位到某个MySQL主机的某个数据库schema上。
<dataHost>
标签:<dataHost>
定义MySQL物理节点以及其连接方式。具体可以参考《MyCAT权威指南》。
设置MyCAT读写分离
MyCAT的读写分离通过schema.xml
中的<dataNode>
标签来定义。其中一个<dataNode>
可以对应一个或者多个<writeHost>
,而一个<writeHost>
又可以有零个或者多个<readHost>
。
其中<writeHost>
之间可以互为备份,取决于balance="0"
的设置;当一个<writeNode>
挂掉的时候,它下边的所有<readHost>
也不可访问。
balance
参数可取的值:
balance="0"
, 不开启读写分离机制,所有读操作都都发送到当前可用的writeHost
上balance="1"
,全部readHost
与stand by writeHost
参与select
语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且 M1 与 M2 互为主备),正常情冴下,M2,S1,S2 都参与select
语句的负载均衡balance="2"
,所有读操作都随机在writeHost
、readhost
上分发balance="3"
,所有读请求随机分发到wiriterHost
对应的readhost
执行,writerHost
不负担读压力,注意balance=3
只在1.4 及其以后版本有,1.3没有
设置MyCAT水平切分
使用字符串前缀切分
<table>
指定了数据库表tab_sign_record_info
的水平切分方式:
1 | <schema name="irenshi" checkSQLschema="false" sqlMaxLimit="10000" dataNode="dn001"> |
其中的数据由rule="sharding-by-company-id"
指定的算法切分。
在rule.xml
中我们可以看到sharding-by-company-id
的定义:
1 | <tableRule name="sharding-by-company-id"> |
由于CompanyID使用了UUID,为字符串类型。所以使用PartitionByPrefixPattern
来进行计算:
prefixLength
将CompanyId中的前5个字母以ASCII的方式求和patternValue
将求和之后数值MOD 64得出最终结果mapFile
将计算的最终结果按照partition-pattern.txt
文件给定的分片规则进行分片
其中partition-pattern.txt内容如下:
1 | # range start-end ,data node index |
结合dataNode="dn001,dn002,dn003"
设置,结果为0-20的数据将分布在dn001中,21-40的数据将分布到dn002中,41-63的数据将分布到dn003中。
使用一致性哈希切分
<table>
标签的配置如下:
1 | <schema name="linahr" checkSQLschema="false" sqlMaxLimit="10000" dataNode="dn004"> |
同样查看rule.xml中sharding-by-company-id-murmur
的定义:
1 | <tableRule name="sharding-by-company-id-murmur"> |
其中:
<property name="seed">0</property>
指定了murmur算法的种子。一般不需要改,使用默认的0即可<property name="count">2</property>
表示物理节点的个数,对应实际dataNode的数量。如上配置中,dataNode为dn004,dn005
,则此处值为2<property name="virtualBucketTimes">160</property>
指定一致性哈希中虚拟bucket的数量。默认为160,在这里节点数为2,那么虚拟bucket的数量为320个(假设下边介绍的weight值为默认值1)。若扩容把count的数量改为3,则虚拟bucket的数量变为480。<property name="weightMapFile">weightMapFile</property>
默认值为1。每个节点对应一个weight值,假设第i个节点的weight值为weight[i]
,则第i个节点对应的虚拟bucket数量为weight[i]*virtualBucketTimes
。所有虚拟节点的总数为sum(weight[i]*virtualBucketTimes)
。
当在机器中增加节点时,即增大count值时,对于每一条数据,则要么落到原有节点中、要么落到新节点中。但是如果增大virtualBucketTimes
或者weight
的值,则一致性哈希的这个性质不能被保证。所以对virtualBucketTimes
和weight
的修改一定要谨慎!
之前murmur
的配置中还包含bucketMapPath
参数,但在1.5的代码中该参数相关的代码已经被注释掉,不能使用了:https://github.com/MyCATApache/Mycat-Server/commit/c9cb201992564c315436792572e96c3beaed3b37
导入数据I:使用mysqldump
+source
命令
使用mysqldump
导出
设置mysqldump
的一些参数
1 | [mysqldump] |
当然这些也可以在执行mysqldump
命令的时候指定。
max_allowed_packet
指定了最大允许的包大小。如果不指定则默认为24MB,导入的时候可能会报ERROR 1153 (08S01) at line 1133809: Got a packet bigger than 'max_allowed_packet' bytes
错误,因为MySQL允许的默认大小为1MB。default-character-set
保证在导出数据库的时候使用utf8mb4
编码。关于utf8mb4
可以参考:创建支持emoji表情的MySQL数据库(utf8mb4)。
导出命令:
1 | mysqldump -h192.168.1.3 -ulinahr -plinahr -c --skip-add-locks --skip-extended-insert --no-autocommit linahr > irenshi-data.sql |
其中每个参数都几乎是必选项,-h
, -u
, -p
三个参数不多说,下面介绍其他参数:
-c
,全称为--complete-insert
,告诉mysqldump导出的时候把列名一起导出。这在MyCAT中要求是必选的,因为MyCAT在执行插入的时候只能执行带列名的插入语句--skip-add-locks
默认情况下,mysqldump会在每个表前后分别增加LOCK TABLES
和UNLOCK TABLES
语句,但在MyCAT中使用LOCK TABLES
和UNLOCK TABLES
会造成潜在的死锁风险,所以尽量避免使用--skip-extended-insert
默认情况下,mysqldump会把每个表格的所有数据写到同一个SQL中。但在分库分表情况下执行导入的时候,对于Boolean类型的数据并且值为True
的数据,会报Data too long错误。目前还不能确认是否是MyCAT的Bug。增加该参数,将每行数据输出为一个单独的insert语句,就不会出现类似错误了。--no-autocommit
参数在每个表格所有的插入语句的前后分别增加SET autocommit = 0
和COMMIT
语句。相比没有这个参数,插入速度能差出至少200倍,分别是10000QPS和50QPS。
如果需要在mysqldump的时候忽略一些表格,可以使用--ignore-table
参数。如果需要一次性忽略一批表格,可以使用这个脚本:
1 |
|
使用mysql
命令导入
首先需要修改[mysqld]
的max_allowed_packet
参数。这个参数默认为1MB,但mysqldump导出的最大允许为16MB,会造成错误,见使用mysqldump
导出章节
1 | [mysqld] |
开始导入:
1 | mysql -ulinahr -plinahr -h192.168.1.4 -P8066 irenshi < irenshi-data.sql |
或者也可以执行SQL命令:
1 | source irenshi-data.sql |
导入数据II:使用mysqldump
+LOAD DATA INFILE
命令
注意:以下内容适合导入单个表,如果需要批量导入大量表,可以参考:http://www.xiaotanzhu.com/2016/08/24/import-data-into-mycat.html
在某些数据库表比较大的情况下,使用以上方法导入的速度就比较难以接受了。MyCAT1.4以后还提供了类似MySQL的LOAD DATA INFILE
命令,供导入大批量数据使用。据说这种方式比insert
语句要快20倍。
同样使用mysqldump
导出
对于小表,使用上面的导入方式还是比较方便的。我们只针对大表使用LOAD DATA INFILE
。
1 | mysqldump -h192.168.1.3 -uroot -proot --fields-optionally-enclosed-by='"' --fields-terminated-by=',' --tab /tmp/irenshi/ --lines-terminated-by='\n' linahr tab_sign_record_info |
这个命令会将irenshi
库中的tab_sign_record_info
以文件形式导入到/tmp/irenshi/
目录下。对于每一个导出的数据库表,将生成两个文件:tab_sign_record_info.sql和tab_sign_record_info.txt,其中tab_sign_record_info.sql存放了数据库表DDL,tab_sign_record_info.txt存放数据库表中的数据。
--fields-optionally-enclosed-by='"'
,--fields-terminated-by=','
和--lines-terminated-by='\n'
分别指定了数据库文件的格式。这几个命令应和LOAD DATA INFILE
给定的参数一致。
执行此命令需要注意几点:
mysqldump
必须在MySQL服务器同一台主机上执行- 必须拥有写文件权限
- MySQL服务器必须对给定的目录
/tmp/irenshi/
有写权限
使用LOAD DATA INFILE
导入数据
1 | LOAD DATA local INFILE '/tmp/irenshi/tab_sign_record_info.txt' |
其中:
local
表示从执行该命令的机器上获取文件。如果没有该参数,则从MySQL服务器上获取文件IGNORE
指定了在服务器上如果已经存在了相同数据则忽略该行。还可以为REPLACE
,表示替换已经存在的数据CHARACTER SET 'utf8mb4'
指定数据库表的编码集。这里需要和数据的编码保持一致,否则可能会出现乱码甚至执行失败FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'
和mysqldump
中的参数对应(column1, column2, column3, ...)
给定数据库的列。在MyCAT中必须要给定所有列,并且列的顺序要和建表时的顺序一致
使用local
文件加载数据时,需指定local-infile = 1
参数。如果不指定可能会报以下错误:
在MySQL上报以下错误:
1 | ERROR 1148 (42000): The used command is not allowed with this MySQL version |
而在MyCAT上则会报:
1 | ERROR 2027 (HY000): Malformed packet |
这个错误着实让人莫名其妙。
使用该参数的方法有三种:
直接在
mysql
命令中指定:mysql -h192.168.1.4 -ulinahr –local-infile=1 -plinahr -P 8066 irenshi
在mysql客户端的配置文件中设置:
[client]
local-infile = 1在mysql连接之后的session中执行SQL命令:
SET local_infile=1;
数据库扩容
<等用到的时候我再写吧>
监控
MyCAT官方提供了MyCAT-Eye作为监控软件。如图所示:
启动MyCAT-Eye需要指定ZooKeeper的服务路径,修改$MYCAT_WEB_DIR/mycat-web/WEB-INF/classes/mycat.properties
:
1 | - zookeeper=localhost:2181 |
然后进入MyCAT-Eye所在目录,执行./start.sh
即可启动MyCAT-Eye。MyCAT-Eye默认服务路径为:
1 | http://localhost:8082/mycat/ |
进入后可以对MyCAT和MySQL等进行配置。
转载请注明出处:开始使用MyCAT
原文地址:https://www.xiaotanzhu.com/%E6%95%B0%E6%8D%AE%E5%BA%93/2016-08-17-mycat-startup.html