简介

MyCat MyCat是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户使用MySQL客户端工具和命令行对数据库进行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信 MyCat的核心功能是分表分库,即将一个大表水平分割为多个小表,存储在后端不同的MySQL服务器中 工作原理 Mycat的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析:如分 片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户 读写分离(Read/Write Splitting) 让一部分数据库服务器处理事务性增、改、删操作(INSERT、UPDATE、DELETE),另一部分数据库服务器处理SELECT查询操作 分库分表 当数据库达到一定规模后(比如说大几千万以上),对库和表进行切分是必须要考虑的,一般来说我们首先要进行垂直切分,即按业务分割,比如说用户相关、订单相关、统计相关等等都可以单独成库,然后进行水平切分进一步分散数据

前期准备

准备四台Centos7虚拟机,关闭防火墙和selinux,配置IP地址和hostname,同步系统时间,配置IP地址和Hostname映射

hostname ip
mid 192.168.29.133
node1 192.168.29.132
node2 192.168.29.138
node3 192.168.29.131

其中mid机器安装mycat中间件,其余node结点机器安装MySQL MySQL配置

#在三个node结点创建mydb库和mycat_test用户用于测试
mysql>create database mydb charset utf8;
mysql>grant all privileges on mydb.* to 'mycat_test'@'192.168.29.%' identified by 'your_password';
mysql>flush privileges;
#在node1,node2的mydb库中创建test表
mysql>use mydb;
mysql>create table test(id int primary key);
#准备少量数据
mysql> select * from test;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
+----+
5 rows in set (0.01 sec)
#在node2,node3的mydb库中创建test1表
mysql>use mydb;
mysql>create table test1(id int primary key,name varchar(20) not null);
#准备少量数据
mysql> select * from test1;
+----+------+
| id | name |
+----+------+
|  1 | Jack |
|  2 | Tom  |
+----+------+
2 rows in set (0.00 sec)

部署mycat

安装openjdk

[root@mid ~]# yum install java -y
#从mycat官网中下载mycat压缩包并解压
[root@mid ~]# tar -xvf Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz -C /usr/local/mycat
#配置Mycat启动管理文件
[root@mid ~]# vi /usr/lib/systemd/system/mycat.service
[Unit]
Description=mycat
After=syslog.target network.target
[Service]
Type=forking
Environment=CATALINA_HOME=/usr/local/mycat
Environment=CATALINA_BASE=/usr/local/mycat
ExecStart=/usr/local/mycat/bin/mycat start
ExecStop=/usr/local/mycat/bin/mycat stop
User=root
Group=root
[Install]
WantedBy=multi-user.target
#更新启动管理文件
[root@mid ~]# systemctl daemon-reload
#mycat部署完成

读写分离,分库分表配置

server.xml配置文件

[root@mid ~]# vi /usr/local/mycat/conf/server.xml 
<user name="root" defaultAccount="true">
		<property name="password">123456</property>
		<property name="schemas">TESTDB</property>
		<property name="defaultSchema">TESTDB</property>

配置schema.xml文件

[root@mid ~]# cat /usr/local/mycat/conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
	#对应server.xml中的name="schemas"属性的值
	<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" >
		#分表,对应后台数据库中的表,表名要保持一致
		<table name="test" primaryKey="id" type="global" dataNode="dn1" />
		<table name="test1" primaryKey="id" type="global" dataNode="dn2" />
	</schema>
	#分表对应的数据结点,database属性对应后台数据库的数据库
	<dataNode name="dn1" dataHost="localhost1" database="mydb" />
	<dataNode name="dn2" dataHost="localhost2" database="mydb" />
	#根据数据结点进行对应配置,name要对应dataNode属性中的dataHost
	<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		#配置写结点
		<writeHost host="hostM1" url="192.168.29.132:3306" user="mycat_test" password="your_password">
			#配置读结点
			<readHost host="hostS2" url="192.168.29.138:3306" user="mycat_test" password="your_password" />
		</writeHost>
	</dataHost>
	<dataHost name="localhost2" maxCon="1000" minCon="10" balance="1"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="hostM1" url="192.168.29.138:3306" user="mycat_test" password="your_password">
			<readHost host="hostS2" url="192.168.29.131:3306" user="mycat_test" password="your_password" />
		</writeHost>
	</dataHost>
</mycat:schema>

启动mycat服务

[root@mid ~]# systemctl start  mycat.service
#查看启动情况
[root@mid ~]# netstat -tnlp |egrep '8066|9066'
tcp6       0      0 :::8066                 :::*                    LISTEN      3794/java           
tcp6       0      0 :::9066                 :::*                    LISTEN      3794/java  
#服务启动成功        

测试验证

测试在宿主机进行

#连接数据库
>mysql -u root -P 8066 -h 192.168.29.133 -p
#查看数据库情况
mysql> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB   |
+----------+
1 row in set (0.06 sec)
mysql> use TESTDB;
Database changed
mysql> show tables;
+------------------+
| Tables in TESTDB |
+------------------+
| test             |
| test1            |
+------------------+
2 rows in set (0.00 sec)

测试test表读写分离

#查看数据
mysql> select * from test;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
+----+
5 rows in set (0.03 sec)
#插入数据
mysql> insert into test values(6);
mysql> insert into test values(7);
#再次查看数据
mysql> select * from test;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
+----+
5 rows in set (0.03 sec)
#在node1上查看数据
mysql> mysql> select * ft;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
|  6 |
|  7 |
+----+
7 rows in set (0.01 sec)
#在node2上查看数据
mysql> mysql> select * ft;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
+----+
5 rows in set (0.00 sec)
#可见添加的数据写入node1中,而读取数据时从node2中读取

测试test1表读写分离

#查看数据
mysql> select * from test1;
+----+------+
| id | name |
+----+------+
|  1 | Jack |
|  2 | Tom  |
+----+------+
2 rows in set (0.00 sec)
#插入数据
mysql> insert into test1 values(3,'Jerry');
#再次查看数据
mysql> select * from test1;
+----+------+
| id | name |
+----+------+
|  1 | Jack |
|  2 | Tom  |
+----+------+
2 rows in set (0.01 sec)
#node2上查看数据
mysql> select * from test1;
+----+-------+
| id | name  |
+----+-------+
|  1 | Jack  |
|  2 | Tom   |
|  3 | Jerry |
+----+-------+
3 rows in set (0.00 sec)
#node3上查看数据
mysql> select * from test1;
+----+------+
| id | name |
+----+------+
|  1 | Jack |
|  2 | Tom  |
+----+------+
2 rows in set (0.00 sec)
#可见添加的数据写入node1中,而读取数据时从node2中读取

以上两项测试与mycat中配置写结点和读结点相符,实现了读写分离和分库分表的部署 结合MySQL数据库的主从复制即可实现在保证数据一致性同时提升读写效率的效果 传统主从复制部署可参考::https://blog.51cto.com/14832653/2500735 基于GTID主从复制部署可参考:https://blog.51cto.com/14832653/2508733