mycat是一款开源的数据库分库分表中间件,用来在多数据情况下的水平分表提供统一的接口,实现无需修改应用的情况下即可将mysql数据库从单机服务平滑迁移到集群,mycat是用java开发说以要安装jdk。官网地址:http://www.mycat.io

如下图所示:

mycat.png


安装JDK:

        安装mycat之前要先安装jdk,但是必须要安装JDK7或者跟高的版本:

下载地址:https://pan.baidu.com/s/1kRIy5dGV1okpFCvWwpdC0Q

下载JDK:http://www.oracle.com/technetwork/java/javase/downloads/index.html

mkdir /usr/java
tar xf jdk1.8.0_92.tar.gz -C /usr/java
cd /usr/java
ln -sv jdk1.8.0_92 jdk

添加环境变量:

vi /etc/profile.d/java.sh
export JAVA_HOME=/usr/java/jdk
export PATH=/usr/java/jdk/bin:$PATH

让环境变量生效:

source /etc/profile.d/java.sh

查看java版本:

java -version


安装mariadb:

yum install mariadb-server -y

初始化设置:

mysql_secure_installation

配置mysql忽略大小写,否者会找不到表。

vi /etc/my.cnf
[mysqld]
lower_case_table_names = 1

要想实现负载均衡效果必须要安装两台以上的mariadb,并赋予创建具有远程连接权限的数据库账号:

grant all on *.* to 'qiyang'@'%' identified by 'qiyang';

在再两个数据库中分别创建名称为db1和db2的数据库:

node4

create database db2 character set utf8 collate utf8_bin;

node5

create database db1 character set utf8 collate utf8_bin;

再分别到db1与db2库中创建名称为company的表,结构要一样:

create table company(id int unsigned not null auto_increment primary key)engine=MyISAM default charset utf8;

配置DNS:

vi /etc/hosts
192.168.96.135          node5
192.168.96.134          node4



安装Mycat:

        官网的github上有限制,说以直接到 http://dl.mycat.io 这个地址下载即可,或者直接使用下面的安装包。

wget http://dl.mycat.io/1.6.5-BETA/Mycat-server-1.6.5-release-20171008170112-linux.tar.gz 
tar xf Mycat-server-1.6.5-release-20171008170112-linux.tar.gz -C /usr/local

添加环境变:

vi /etc/profile.d/mycat.sh
MYCAT_HOME=/usr/local/mycat
export PATH=/usr/local/mycat/bin:$PATH

让环境变量生效:

source /etc/profile.d/java.sh

检查环境变量是否生效:

mycat

添加mycat用户,并改变mycat目录属组为mycat。

useradd mycat
chown -R mycat.mycat /usr/local/mycat



配置mycat


        常用的配置文件有三个,server.xml,schema.xml,rule.xml,都放在 mycat/conf 目录中,server.xml文件中配置了所有的系统配置信息,主要有四个 system、user、firewarll、cluster。schema.xml 主要配置数据库的一些信息,分片表分片规则,数据库节点等,数据源。rule.xml 里面就定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法,或者对表使用相同的算法但具体的参数不同。其中最重要的是server.xml文件。下面对具体的配置项进行讲解。


server.xml

        先来简单说说用户这一块,要注意的是 <property name="schemas">testdb</property>标签中的内容要和 schema.xml 文件中的<schema name="testdb">标签中的name属性要对应,且区分大小写,其他项看下面实例即可理解,配置如下:

server.xml文件中:

<user name="root" defaultAccount="true">
	<property name="password">123456</property>
	<property name="schemas">testdb</property>
</user>

schema.xml文件中:

<schema name="testdb" checkSQLschema="false" sqlMaxLimit="100">...</schema>


schema.xml

        先来看一下schema.xml配置文件的大体结构。

<mycat:schema xmlns:mycat="http://io.mycat/">

	<schema name="testdb" checkSQLschema="false" sqlMaxLimit="100">
		<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="" />
	</schema>
	
	<dataNode name="dn1" dataHost="node4" database="db1" />
	<dataNode name="dn2" dataHost="node3" database="db2" />
	<dataNode name="dn3" dataHost="node2" database="db3" />
	
	<dataHost name="node4" maxCon="1000" minCon="10" ... >
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM1" url="192.168.140.134:3306" user="qiyang" password="qiyang">
			<readHost host="hostS2" url="" user="" password="" />
		</writeHost>
		<writeHost host="hostS1" url="" user="" password="" />
	</dataHost>
	<dataHost name="node3"></dataHost>
	<dataHost name="node2"></dataHost>
	
</mycat:schema>


schema标签:

        先说一下这个配置文件的大致结构,最外层的是<mycat:schema>标签,这个就不多介绍了就是个全局包含的标签,跟<html>类似,里面的第一个标签是<schema name="testdb">,标签中的name属性的值就是使用show databases 命令时看到的数据库名称。

xml中的配置:

<schema name="testdb" checkSQLschema="false" sqlMaxLimit="100">
	...
</schema>

mycat中查看到的效果:

mysql -uroot -p123456 -P8066 -h192.168.140.134
Welcome ...
MySQL [(none)]> show databases;
+----------+
| DATABASE |
+----------+
| testdb   |
+----------+


table标签:

        在<schema>里面的子标签<table>标签和字面意思是相同的,就是定义某个数据库里面的table表的标签,也是使用 show tables 命令所能看到的表,有几个<table>标签就能够看到几张表。

xml中的配置:

<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
<table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2" />
<table name="hotnews" ... />
<table name="employee" .../>
<table name="customer" ...>
	<childTable name="orders" primaryKey="ID" joinKey="customer_id" parentKey="id">
		<childTable name="order_items" joinKey="order_id" parentKey="id" />
	</childTable>
	<childTable name="customer_addr" primaryKey="ID" joinKey="customer_id" parentKey="id" />
</table>

mycat中看到的效果:

MySQL [testdb]> show tables;
+------------------+
| Tables in testdb |
+------------------+
| company          |
| customer         |
| customer_addr    |
| employee         |
| goods            |
| hotnews          |
| orders           |
| order_items      |
| travelrecord     |
+------------------+


dataNode标签:

        <dataNode>标签是和<schema>同级别的标签,用来定义数据节点,说白了就是<table>标签中表的数据来源,在<table>标签中有一个属性 dataNode="dn1,dn2,dn3" ,这里面的dn1、dn2、dn3填的就是<dataNode name="dn1">中的name属性值,上面写了三个就必须要有三个<dataNode name="">标签。

xml中的dataNode标签的配置:

<dataNode name="dn1" dataHost="node4" database="db1" />
<dataNode name="dn2" dataHost="node3" database="db2" />
<dataNode name="dn3" dataHost="node2" database="db3" />

xml中table标签的配置:

<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />


dataHost标签:

        dataHost标签就是用来配置数据所在的主机信息,是和<dataNode>、<schema>同级别的标签,用来配置读数据和写数据真实主机的具体信息,账号、密码、端口等信息。<dataHost name="node4">标签中name属性的值就是<dataNode dataHost="node4">标签中dataHost属性的值。

xml中的配置:

<dataHost name="node4" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
	<heartbeat>select user()</heartbeat>
	<writeHost host="hostM1" url="192.168.140.134:3306" user="qiyang" password="123456">
		<readHost host="hostS2" url="192.168.140.134:3306" user="qiyang" password="123456" />
	</writeHost>
	<writeHost host="hostS1" url="192.168.140.134:3306" user="qiyang" password="123456" />
</dataHost>


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">
		<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2" />
	</schema>
	
	<dataNode name="dn1" dataHost="node4" database="db1" />
	<dataNode name="dn2" dataHost="node3" database="db2" />
	
	<dataHost name="node4" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<!-- 当前writeHost宕机后,标签里面的readHost将不可用 -->
		<writeHost host="hostM1" url="192.168.140.134:3306" user="qiyang" password="qiyang">
			<readHost host="hostS2" url="192.168.140.134:3306" user="qiyang" password="qiyang" />
		</writeHost>
		<writeHost host="hostS1" url="192.168.140.134:3306" user="qiyang" password="qiyang" />
	</dataHost>
	
	<dataHost name="node3" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM1" url="192.168.140.133:3306" user="qiyang" password="qiyang">
			<readHost host="hostS2" url="192.168.140.133:3306" user="qiyang" password="qiyang" />
		</writeHost>
		<writeHost host="hostS1" url="192.168.140.133:3306" user="qiyang" password="qiyang" />
	</dataHost>
	
</mycat:schema>


实现负载均衡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">
		<table name="test" primaryKey="ID" type="global" dataNode="dn1" /><!-- name="真实的表名称" -->
	</schema>
	
	<dataNode name="dn1" dataHost="node4" database="test_master" /><!-- database="真实的数据库名称" -->
	
	<dataHost name="node4" maxCon="1000" minCon="10" balance="2" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>show slave status</heartbeat>
		<!-- 当前writeHost宕机后,标签里面的readHost将不可用 -->
		<writeHost host="hostM1" url="192.168.140.134:3306" user="qiyang" password="qiyang">
			<readHost host="hostS1" url="192.168.140.133:3306" user="qiyang" password="qiyang" />
		</writeHost>
	</dataHost>
	
</mycat:schema>

        实现负载均衡要先配置mysql数据库的主从,详情点击 mysql主从复制 ,然后配置 schema.xml 文件,配置中<schema>-><table>中的name属性填写表名称,<dataNode>标签中的database属性填写真实的数据库名称,在<dataHost>标签中的balance属性填写2,<heartbeat>标签中的心跳语句必须为show slave status,然后填写<writeHost>和<readHost>,一主一备。


测试是否成功实现负载均衡:

        mysql数据库在主备情况下只有备的才会去读去主的,而主的是不会去读取备的上的数据。这样在备的上面修改一个数据使其看起来和主的不一样,以便于观察效果。

下面这个例子是先在mycat上插入两条数据分别为1、2,然后在备的上插入3,然后又到mycat上插入4,这样数据看起来就不一样了。连续使用查询命令就可以看到效果。

mysql -uroot -p123456 -P8066 -h192.168.140.134
MySQL [(none)]> show databases;
use testdb;
MySQL [testdb]> select * from test;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
+----+
4 rows in set (0.00 sec)

MySQL [testdb]> select * from test;
+----+
| id |
+----+
|  1 |
|  2 |
|  4 |
+----+


开启 debug 模式日志:

        在 /conf/log4j2.xml 中,找到如下段,将level值改为debug,level有 info,ware 和 debug 三种模式,生产模式下使用非 debug。

<asyncRoot level="debug" includeLocation="true">
    <AppenderRef ref="RollingFile"/>
</asyncRoot>

调试时就可以看 /logs/mycat.log 文件了。


mycat多数据库配置:

        先配置 server.xml 文件再配置 schema.xml 配置文件,具体配置如下:

server.xml文件:

        在 property 标签属性为 schemas 的标签中配置多个想要访问的数据库名称,用逗号分隔。

<user name="root" defaultAccount="true">
		<property name="password">123456</property>
		<property name="schemas">test_master,userdb</property>
</user>

schema.xml配置:

        为 server.xml 中配置中的每一个数据库名创建一个schema标签。dataNode标签是用来配置真实的数据库信息的,根据实际情况配置即可。

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

    <schema name="test_master" checkSQLschema="false" sqlMaxLimit="100">
        <table name="company" primaryKey="ID" type="global" dataNode="dn1" /><!-- name="真实的表名称" -->
    </schema>

    <schema name="userdb" checkSQLschema="false" sqlMaxLimit="100">
        <table name="user" primaryKey="ID" type="global" dataNode="dn2" /><!-- name="真实的表名称" -->
    </schema>


    <dataNode name="dn1" dataHost="node1" database="test_master" /><!-- database="真实的数据库名称" -->
    <dataNode name="dn2" dataHost="node1" database="userdb" /><!-- database="真实的数据库名称" -->

    <dataHost name="node1" maxCon="1000" minCon="10" balance="2" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
        <heartbeat>show slave status</heartbeat>
        <!-- 当前writeHost宕机后,标签里面的readHost将不可用 -->
        <writeHost host="hostM1" url="192.168.8.179:3306" user="write" password="123456">
            <readHost host="hostS1" url="192.168.8.178:3306" user="all" password="123456" />
        </writeHost>
    </dataHost>

</mycat:schema>