题目
- 写出 MYCAT 读写分离用途、原理,并且划出架构图,将整个操作写成文档。
- 预习 Nginx、LNMP 架构实战。
解答
MyCat 读写分离的用途
- 为业务应用提供负载均衡、读写分离、高可用性、SQL 过滤等服务。
- 简化数据备份还原工作。
- 大幅降低前端业务系统开发难度,提升开发速度和测试进度。
MyCat 读写分离的原理
MyCat 作为 MySQl 主从复制架构的前端代理,负责接收全部的会话事务,然后将事务请求进行分拣:
- 将增、删、改类型的请求转发给 MySQL Master 进行处理。
- 将查询类型的请求转发给 MySQL Slave 进行处理。
MyCat 架构图
读写分离架构:
事务层流程:
搭建实例
实验环境
主机:
- 192.168.0.110: MyCat
- 192.168.0.111: MySQL Master
- 192.168.0.112: MySQL Slave
- 127.0.1.1: MySQL Client
包:
- jdk1.8.0_131.tar.gz:Java 语言运行时库。
- mycat2-install-template-1.21.zip:MyCat 安装包。
- mycat2-1.21-release-jar-with-dependencies.jar:MyCat 依赖 jar 包。
搭建
注意:以下使用 IP 标识操作主机。
步骤:
-
[110]部署 JDK:
- 配置运行时库:
- 解压:
$ tar -xzvf jdk1.8.0_131.tar.gz
- 创建目录:
$ mkdir -p /usr/java/
- 拷贝目录:
$ cp -rf jdk1.8.0_131 /usr/java/
- 解压:
- 配置环境变量:
-
编辑配置文件:
$ vim /etc/profile
# 运行时库路径 export JAVA_HOME=/usr/java/jdk1.8.0_131 # 文件路径 export PATH=$PATH:/usr/java/jdk1.8.0_131/bin:/usr/local/mycat/bin
-
刷新配置:
$ source /etc/profile
-
测试:
$ java -version
-
- 配置运行时库:
-
[110]安装 MyCat:
- 解压安装包:
unzip mycat2-install-template-1.21.zip
- 转移目录:
$ mv mycat /usr/local/
- 解压安装包:
-
[110]部署依赖包:
$ mv mycat2-1.21-release-jar-with-dependencies.jar /usr/local/mycat/lib/
-
[110]授权:
$ chmod o+x /usr/local/mycat/bin/
-
[111]配置数据库:
- 配置 MyCat 用户和原型数据库:
- 创建用户:
> create user 'mycat'@'192.168.0.110' identified with mysql_native_password by 'WahahaAyaya123!';
- 授权:
> grant all privileges on *.* to 'mycat'@'192.168.0.110';
- 刷新权限:
> flush privileges;
- 创建原型数据库:
> create database mycat;
- 创建用户:
- 配置测试用户和数据库:
- 创建测试库:
> create database discuz;
- 授权:
> update mysql.user set host='%' where user='root';
- 设置低版本密码支持:
> alter user 'root'@'%' identified with mysql_native_password by 'WahahaAyaya123!';
- 更新配置:
> flush privileges;
- 创建测试库:
- 配置 MyCat 用户和原型数据库:
-
[110]配置数据源:
-
原型数据库数据源:/usr/local/mycat/conf/datasources/prototypeDs.datasource.json
"dbType":"mysql", // 数据库类型 "idleTimeout":60000, // 空闲超时时间 "initSqls":[], "initSqlsGetConnection":true, "instanceType":"READ_WRITE", // 实例类型 "maxCon":1000, // 最大连接数 "maxConnectTimeout":3000, // 超时时间 "maxRetryCount":5, // 重连次数 "minCon":1, // 最小连接数 "name":"prototypeDs", // 数据源名称 要和文件名保持一致 "password":"WahahaAyaya123!", // 密码 "type":"JDBC", // API 类型 // 原始数据库 // 192.168.0.111:3306 数据库 ip 端口 // mycat 原型数据库名 // useUnicode 编码 // serverTimezone 时区 // characterEncoding 字符集 "url":"jdbc:mysql://192.168.0.111:3306/mycat?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8", "user":"mycat", // 用户名 "weight":0 // 权重
-
拷贝模板:/usr/local/mycat/conf/datasources/
# 有几个主从库就拷贝几份 $ cp prototypeDs.datasource.json master.datasource.json $ cp prototypeDs.datasource.json slave.datasource.json # ...
-
编辑 master 数据源:/usr/local/mycat/conf/datasources/master.datasource.json
"dbType":"mysql", // 数据库类型 "idleTimeout":60000, // 空闲超时时间 "initSqls":[], "initSqlsGetConnection":true, "instanceType":"READ_WRITE", // 实例类型 "maxCon":1000, // 最大连接数 "maxConnectTimeout":3000, // 超时时间 "maxRetryCount":5, // 重连次数 "minCon":1, // 最小连接数 "name":"master", // 数据源名称 "password":"WahahaAyaya123!", // 主库密码 "type":"JDBC", // API 类型 // 192.168.0.111 主库 IP // discuz 业务数据库名 有几个就配置几个 "url":"jdbc:mysql://192.168.0.111:3306/discuz?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8", "user":"root", // 主库用户名 "weight":0 // 权重
-
编辑 slave 数据源:/usr/local/mycat/conf/datasources/slave.datasource.json
"dbType":"mysql", // 数据库类型 "idleTimeout":60000, // 空闲超时时间 "initSqls":[], "initSqlsGetConnection":true, "instanceType":"READ", // 实例类型 "maxCon":1000, // 最大连接数 "maxConnectTimeout":3000, // 超时时间 "maxRetryCount":5, // 重连次数 "minCon":1, // 最小连接数 "name":"slave", // 数据源名称 "password":"WahahaAyaya123!", // 从库密码 "type":"JDBC", // API 类型 // 192.168.0.112 从库 IP // discuz 业务数据库名 有几个就配置几个 "url":"jdbc:mysql://192.168.0.112:3306/discuz?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8", "user":"root", // 从库用户名 "weight":0 // 权重
-
-
[110]配置集群信息:/usr/local/mycat/conf/clusters/
-
拷贝原始集群配置文件:
$ cp prototype.cluster.json master-slave.cluster.json
-
编辑:master-slave.cluster.json
"clusterType":"MASTER_SLAVE", // 集群类型 "heartbeat":{ "heartbeatTimeout":1000, "maxRetry":3, "minSwitchTimeInterval":300, "slaveThreshold":0 }, "masters":[ // 主库数据源 "master" // 要和之前配置的主库数据源匹配 ], "replicas":[ // 从库数据源 "slave" // 要和之前配置的从库数据源匹配 ], "maxCon":200, // 最大连接数 "name":"master-slave", // 集群名称 要和配置文件匹配 // 读写机制类型 // BALANCE_ALL 负载均衡模式 "readBalanceType":"BALANCE_ALL", "switchType":"NOT_SWITCH" // 切换模式
-
创建物理库配置文件:
$ vim /usr/local/mycat/conf/schemas/discuz.schema.json
-
编辑配置文件:discuz.schema.json
{ "schemaName": "discuz", // 物理数据库 即业务库或测试库 "targetName": "master-slave", // 目标集群 "normalTables": {} }
-
-
[110]编辑 MyCar 登录信息:/usr/local/mycat/conf/users/root.user.json
{ "dialect":"mysql", "ip":null, "password":"WahahaAyaya123!", // 修改密码 "transactionType":"xa", // 事务类型 "username":"root" // 用户名 }
-
[110]启动 MyCat:
$ mycat start
-
[110]查看日志:
$ tail -fn 20 /usr/local/mycat/logs/wrapper.log
-
[110]查看进程:
$ netstat -tnlp | grep -aiE java
测试
步骤:
-
使用测试机连接 MyCat:
# 使用远程连接 # root 后端数据库授权用户 # 192.168.0.110 mycat 服务器 ip # 8066 mycat 默认侦听端口 $ mysql -uroot -p'WahahaAyaya123!' -h192.168.0.110 -P8066
-
配置测试数据:
- 切换库:
> use discuz;
- 创建表:
> create table t1 (id int,name varchar(32),job char(64));
- 插入数据:
> insert into t1 values (1,'张三峰','武当掌门'),2,'乔峰','南院大王'),(3,'段誉','大理王子');
- 切换库:
-
查看数据:
-
测试机:127.0.1.1
mysql> select * from t1; +------+-----------+--------------+ | id | name | job | +------+-----------+--------------+ | 1 | 张三峰 | 武当掌门 | | 2 | 乔峰 | 南院大王 | | 3 | 段誉 | 大理王子 | +------+-----------+--------------+ 3 rows in set (0.01 sec)
-
主库:192.168.0.111
mysql> select * from t1; +------+-----------+--------------+ | id | name | job | +------+-----------+--------------+ | 1 | 张三峰 | 武当掌门 | | 2 | 乔峰 | 南院大王 | | 3 | 段誉 | 大理王子 | +------+-----------+--------------+ 3 rows in set (0.00 sec)
-
从库:192.168.0.112
mysql> select * from t1; +------+-----------+--------------+ | id | name | job | +------+-----------+--------------+ | 1 | 张三峰 | 武当掌门 | | 2 | 乔峰 | 南院大王 | | 3 | 段誉 | 大理王子 | +------+-----------+--------------+ 3 rows in set (0.00 sec)
-