一、什么是mycat
mycat是一个开源的数据库中间件 ,它由阿里曾经的开源产品Cobar演变而来。mycat的核心功能是分库分表,可以将一个大表水平分割为N个小表,把数据库分成N个分片,存储在mysql服务器里或者其他数据库里,还可以实现读写分离,容灾备份等。
二、安装mycat并实现mysql分库分表
1.在两台或两台以上Linux服务器上安装mysql并启动(具体步骤省略,推荐mysql是5.5以上版本,启动后注意要设置远程登录权限)
2.mycat安装及启动
下载mycat安装包,下载地址:
https://github.com/MyCATApache/Mycat-download
第一步:将下载好的安装包上传到服务器
第二步:使用命令tar -zxvf Mycat-server-1.4-release-20151019230038-linux.tar.gz mycat将压缩包解压缩
第三步:进入mycat目录的bin目录,启动mycat
mycat的默认端口为:8066
3.mycat分片配置
(1)配置schma.xml
schma.xmls mycat中很重要的配置之一,管理mycat的逻辑库。逻辑表以及对应的分片规则等。
schema标签用于定义mycat实例的逻辑库,Table标签定义mycat中的逻辑表,rule用于指定分片规则,dataNode标签定义mycat中的数据节点,也就是数据分片,dataHost标签定义mycat具体的数据库实例,读写分离配置和心跳语句。
在已安装好mysql的2台服务器上分别创建数据库db1、db2
修改schema.xml如下:
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<!-- auto sharding by id (long) -->
<table name="tb_test" dataNode="dn1,dn2" rule="auto-sharding-long" />
</schema>
<dataNode name="dn1" dataHost="localhost1" database="db1" />
<dataNode name="dn2" dataHost="localhost2" database="db2" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="换成你的mysql服务器1的ip:3306" user="mysql用户名"
password="mysql密码">
<!-- can have multi read hosts -->
</writeHost>
</dataHost>
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="换成你的mysql服务器2的ip:3306" user="mysql用户名"
password="mysql密码">
<!-- can have multi read hosts -->
</writeHost>
</dataHost>
</mycat:schema>
(2)配置server.xml
server.xml几乎保存了所有mycat需要的系统配置信息。最常用的是在此配置用户名、密码及权限。在system中添加UTF-8字符集设置,否则存储中文会出现问号
<property name="charset">utf8</property>
修改user的配置,可修改用户名,密码等(注意schema的属性值要与schema配置文件中一致)
<user name="test">
<property name="password">test</property>
<property name="schemas">TESTDB</property>
</user>
<user name="root">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
</user>
4.mycat分片测试
(1)使用Navicat for MySQL工具连接到mycat
进入到mycat,执行以下语句创建一个表:
CREATE TABLE tb_test (
id BIGINT(20) NOT NULL,
title VARCHAR(100) NOT NULL ,
PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8
插入一些数据:
INSERT INTO TB_TEST(ID,TITLE) VALUES(1,'data1');
INSERT INTO TB_TEST(ID,TITLE) VALUES(2,'data2');
INSERT INTO TB_TEST(ID,TITLE) VALUES(3,'data3');
INSERT INTO TB_TEST(ID,TITLE) VALUES(4,'data4);
注意:如果报错ERROR 3009 (HY000):Java.lang.IllegalArgumentException: Invalid DataSource:0 ,按下面的解决方案解决:
把mysql中的mysql.user表中的root 用户的 host改为%后,重启mysql,mycat连接后就可以操作表了。
我们会发现这些数据被写入到第一个节点中了,那么怎样才能把数据写入到第二个节点呢?插入下面的数据就可以插入到第二个节点了
INSERT INTO TB_TEST(ID,TITLE) VALUES(5000001,'data5000001');
INSERT INTO TB_TEST(ID,TITLE) VALUES(5000002,'data5000002');
因为我们采用的分片规则是每节点存储500万条数据,所以当ID大于5000000则会存储到第二个节点上,分片规则在rule.xml文件中配置
在rule.xml中找到
<tableRule name="auto-sharding-long">
<rule>
<columns>id</columns>
<algorithm>rang-long</algorithm>
</rule>
</tableRule>
接着找rang-long的定义
<function name="rang-long"
class="org.opencloudb.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
</function>
再打开autopartition-long.txt,可以看到这里配置了数据范围
# range start-end ,data node index
# K=1000,M=10000.
0-500M=0
500M-1000M=1
1000M-1500M=2
上面的分片规则适用于主键id是连续的数字,有的表主键是字符串,并不是连续的数字,上面的规则就不适用了。可以使用一致性哈希murmur,将数据平均分在几个分片中,也是在schema文件中进行配置,也比较简单,这里不再叙述。
三、数据库读写分离
对于互联应用来说,数据库的访问量很大,进行读写分离很有必要。实现数据库读写分离,当主节点发生宕机时,还能从从节点查询到数据。mycat基于mysql的主从模式可实现读写分离,一个写节点Master后面跟着多个读节点,当执行增删改操作时向主节点发起请求,执行查询操作时向从节点发起请求,主节点数据发生改变后,基于mysql的主从复制模式,数据会自动同步到从节点。
配置mycat开启读写分离,也是在schema.xml中进行配置,hostM1主节点与hostS1、hostS2从节点组成了一主二从的读写分离模式,参数balance决定了哪些mysql服务器参与到读sql的负载均衡中,0为不开启读写分离
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="2"
writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="localhost:3306" user="root" password="123456">
<!-- can have multi read hosts -->
<readHost host="hostS1" url="localhost2:3306" user="root" password="123456"
/>
<readHost host="hostS2" url="localhost3:3306" user="root" password="123456"
/>
</writeHost>
</dataHost>