MyCAT实现MySQL读写分离

写在前边

为什么我要用 MyCAT

最近一直在做毕业设计,基于 Nginx 的高可用大并发微信电子商城系统设计与实现,该课题中要求数据库主从复制+读写分离,网上的读写分离中间件推荐有

  • MySQL 官方推出的 MySQL-proxy,最新版本是 2014 年 8 月,那个时候我还没读大学,而且版本一直是alpha,尝试了用了一下,经常挂掉,所以放弃了。
  • MySQL 官方推出的 MySQL-router,随着 MySQL 5.7 一起发布的,访问协议与 MySQL 一致,是 MySQL-proxy 的升级版,只有简单的负载均衡功能。
  • 奇虎 360 Atlas,基于 MySQL-proxy 0.8.2,已经停更很久了,而且官方群已经关闭,不过 issues 还有人回复,据说在开发新版本。
  • Mycat 数据库分库分表中间件,基于阿里开源的 Cobar 产品而研发,Cobar 的稳定性、可靠性、优秀的架构和性能以及众多成熟的使用案例使得 MYCAT 一开始就拥有一个很好的起点,社区活跃,文档丰富。

综上所述,我选择了 MyCAT。

环境描述

  • 操作系统: CentOS 7.4 1708
  • 负载均衡服务器:192.168.0.100
  • 主服务器 master:192.168.0.123
  • 从服务器 slave: 192.168.0.124

MySQL 主从复制配置请查看


了解 MyCAT

什么是 MyCAT

  • 一个彻底开源的,面向企业应用开发的大数据库集群
  • 支持事务、ACID、可以替代 MySQL 的加强版数据库
  • 一个可以视为 MySQL 集群的企业级数据库,用来替代昂贵的 Oracle 集群
  • 一个融合内存缓存技术、NoSQL 技术、HDFS 大数据的新型 SQL Server
  • 结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品
  • 一个新颖的数据库中间件产品

MyCAT 关键特性

  • 支持 SQL92 标准
  • 支持 MySQL、Oracle、DB2、SQL Server、PostgreSQL 等 DB 的常见 SQL 语法
  • 遵守 MySQL 原生协议,跨语言,跨平台,跨数据库的通用中间件代理。
  • 基于心跳的自动故障切换,支持读写分离,支持 MySQL 主从,以及 galera cluster 集群。
  • 支持 Galera for MySQL 集群,Percona Cluster 或者 MariaDB cluster
  • 基于 Nio 实现,有效管理线程,解决高并发问题。
  • 支持数据的多片自动路由与聚合,支持 sum,count,max 等常用的聚合函数,支持跨库分页。
  • 支持单库内部任意 join,支持跨库 2 表 join,甚至基于 caltlet 的多表 join。
  • 支持通过全局表,ER 关系的分片策略,实现了高效的多表 join 查询。
  • 支持多租户方案。
  • 支持分布式事务(弱 xa)。
  • 支持 XA 分布式事务(1.6.5)。
  • 支持全局序列号,解决分布式下的主键生成问题。
  • 分片规则丰富,插件化开发,易于扩展。
  • 强大的 web,命令行监控。
  • 支持前端作为 MySQL 通用代理,后端 JDBC 方式支持 Oracle、DB2、SQL Server 、 mongodb 、巨杉。
  • 支持密码加密
  • 支持服务降级
  • 支持 IP 白名单
  • 支持 SQL 黑名单、SQL 注入攻击拦截
  • 支持 prepare 预编译指令(1.6)
  • 支持非堆内存(Direct Memory)聚合计算(1.6)
  • 支持 PostgreSQL 的 native 协议(1.6)
  • 支持 MySQL 和 oracle 存储过程,out 参数、多结果集返回(1.6)
  • 支持 zookeeper 协调主从切换、zk 序列、配置 zk 化(1.6)
  • 支持库内分表(1.6)
  • 集群基于 ZooKeeper 管理,在线升级,扩容,智能优化,大数据处理(2.0 开发版)。

安装 MyCAT (在负载均衡服务器上操作)

MyCAT 是使用 JAVA 语言进行编写开发,使用前需要先安装 JAVA 运行环境(JRE),由于 MyCAT 中使用了 JDK7 中的一些特性,所以要求必须在 JDK7 以上的版本上运行。

安装 JDK

检查是否安装了 JAVA

1
$ java -version

安装 jdk 包

MyCAT 资源站点

创建目录

1
2
$ mkdir /usr/java/
$ cd /usr/java/

最新版本的 jdk8 下载 (2017 年 12 月 26 日)

1
2
3
4
$ wget http://download.oracle.com/otn-pub/java/jdk/8u151-b12/e758a0de34e24606bca991d704f6dcbf/jdk-8u151-linux-x64.tar.gz
$ tar -zxvf jdk-8u151-linux-x64.tar.gz
$ ls #查看目录
jdk1.8.0_151 jdk-8u151-linux-x64.tar.gz

配置环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ vim /etc/profile
...
# 在最后添加
#set java environment
JAVA_HOME=/usr/java/jdk1.8.0_151
JRE_HOME=$JAVA_HOME/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH
...
$ source /etc/profile #刷新生效
$ java -version
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b23, mixed mode)

安装 MyCAT 配置读写分离

MyCAT 资源站点

创建目录

1
2
$ mkdir /usr/mycat/
$ cd /usr/mycat/

下载解压

这里我安装MyCAT 1.6.5
本来安装的是 1.6.0,但是用不成,后来提交了 issues,维护者告知 1.6.0 不支持 Mysql 预处理。

1
2
3
4
5
6
$ wget http://dl.mycat.io/1.6.5/Mycat-server-1.6.5-release-20171117203123-linux.tar.gz
$ tar -zxvf Mycat-server-1.6.5-release-20171117203123-linux.tar.gz
$ ls
mycat Mycat-server-1.6.5-release-20171117203123-linux.tar.gz
$ ls mycat
bin catlet conf lib logs version.txt

配置环境

1
2
3
4
5
6
7
8
9
10
$ vim /etc/profile
...
# 在最后添加
#set mycat
export MYCAT_HOME=/usr/mycat/mycat
export PATH=${MYCAT_HOME}/bin:$PATH
...
$ source /etc/profile #刷新生效
$ mycat -v #MyCAT没有这个命令,但是出现下面提示代表配置成功
Usage: /usr/mycat/mycat/bin/mycat { console | start | stop | restart | status | dump }

配置读写分离

配置文件非常多,如果只是简单配置在不同的服务器上进行读写分离只需要配置两个文件 server.xmlschema.xml,点此查看文档,了解更多

Master 创建用户和数据库

在 Master 服务器操作

1
2
3
4
5
6
7
$ mysql -u root -p
// 创建一个拥有全部权限的用户
mysql> GRANT ALL ON *.* TO 'proxy'@'192.168.0.100' IDENTIFIED BY 'msMlRbj38mRwcc8yDH9iOzJaA0OxXLlv';
// 创建一个拥有只读权限的用户
mysql> GRANT SELECT ON *.* TO 're_proxy'@'192.168.0.100' IDENTIFIED BY 'msMlRbj38mRwcc8yDH9iOzJaA0OxXLlv';
mysql> FLUSH PRIVILEGES;
mysql> create database test;
  • 建议创建 MySQL 用户时不要轻易用%,最好是限制一下权限 ip
  • 如果你的主从复制没有限定数据库,那么你创建的用户会同步到从库。
配置schema.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ vim mycat/conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 定义MyCat的逻辑库 -->
<schema name="test" checkSQLschema="false" sqlMaxLimit="100" dataNode="pcxNode"></schema>
<!-- 定义MyCat的数据节点 -->
<dataNode name="pcxNode" dataHost="dtHost" database="test" />
<!-- 定义数据主机dtHost,连接到MySQL读写分离集群 ,schema中的每一个dataHost中的host属性值必须唯一-->
<!-- dataHost实际上配置就是后台的数据库集群,一个datahost代表一个数据库集群 -->
<!-- balance="1",全部的readHost与stand by writeHost参与select语句的负载均衡-->
<!-- writeType="0",所有写操作发送到配置的第一个writeHost,这里就是我们的hostmaster,第一个挂了切到还生存的第二个writeHost-->
<dataHost name="dtHost" maxCon="500" minCon="20" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<!--心跳检测 -->
<heartbeat>select user()</heartbeat>

<!--配置后台数据库的IP地址和端口号,还有账号密码 -->
<writeHost host="hostM2" url="192.168.0.123:3306" user="proxy" password="msMlRbj38mRwcc8yDH9iOzJaA0OxXLlv">
<readHost host="hostS2" url="192.168.0.124:3306" user="re_proxy" password="msMlRbj38mRwcc8yDH9iOzJaA0OxXLlv"/>
</writeHost>
</dataHost>
</mycat:schema>
配置server.xml

$ vim mycat/conf/server.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<system>
<property name="defaultSqlParser">druidparser</property>
<property name="charset">utf8mb4</property>
</system>
<!-- user 业务代码中用来访问Mycat的帐号 -->
<user name="my_user">
<!-- password 业务代码中用来访问Mycat的密码 -->
<property name="password">abcdefghijklmn</property>
<!-- schemas 与schema.xml中的<schema></schema>的name属性相同 -->
<property name="schemas">test</property>
</user>
<user name="my_readly_user">
<property name="password">abcdefghijklmn</property>
<property name="schemas">test</property>
<property name="readOnly">true</property>
</user>
</mycat:server>

开启 MyCAT

1
$ mycat start

查看端口

1
2
3
4
5
$ netstat -antlp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:8066 0.0.0.0:* LISTEN 14054/java
tcp 0 0 0.0.0.0:9066 0.0.0.0:* LISTEN 14054/java
  • 9066 虚拟 schema 管理端口
  • 8066 虚拟 schema 登陆端口

登录 MyCAT 读写分离服务

1
$ mysql -u my_user -p -h127.0.0.1 -P 8066

登录 MyCAT 管理端

1
2
3
4
$ mysql -u my_user -p -h127.0.0.1 -P 9066
mysql> show @@heartbeat;
RS_CODE为1表示心跳正常
mysql> show @@datasource; --查看读写分离的机器配置情况

MyCAT 读写分离验证

更改日志输出模式
1
2
3
$ vim mycat/conf/log4j.xml
修改<asyncRoot level="info" includeLocation="true">
为 <asyncRoot level="debug" includeLocation="true">
测试
1
2
3
4
5
$ mysql -uroot -p123456 -h127.0.0.1 -P 8066
mysql> create table test (id bigint not null primary key,user varchar(100));
mysql> insert into test(id,user) values(1,abc);
mysql> insert into test(id,user) values(2,xyz);
mysql> select * from test
查询观察日志的变化
1
tail -f mycat/logs/mycat.log

可以观察到实际操作相关的 IP,这里我就不展示了。

文章不错,你都不请我喝杯茶,就是说你呀!
0%
upyun