前言
什么是读写分离?其实所谓的读写分离就是在数据库集群架构中,让主库负责处理写入操作,而从库只负责处理select查询,让两者分工明确达到提高数据库整体读写性能。当然,主数据库另外一个功能就是负责将数据变更同步到从库中,也就是写操作。通过读写分离,可分摊服务器压力,提高机器的系统处理效率,在写入不变,大大分摊了读取,提高了系统性能。另外,当读取被分摊后,又间接提高了写入的性能。所以,总体性能提高了。同时增加冗余,提高服务可用性,当一台数据库服务器宕机后可以调整另外一台从库以最快速度恢复服务。本次通过mycat数据库中间件来实现MySQL的读写分离。
一、Mycat介绍
Mycat 是一个开源的数据库系统,但是由于真正的数据库需要存储引擎,而 Mycat 并没有存储引擎,所以并不是完全意义的数据库系统。 那么 Mycat 是什么?Mycat 是数据库中间件,就是介于数据库与应用之间,进行数据处理与交互的中间服 务是实现对主从数据库的读写分离、读的负载均衡。
常见的数据库中间件:
- MySQL Proxy:MySQL官方
- Atlas:奇虎360
- DBProxy:美团点评
- Amoeba:早期阿里巴巴
- cober:阿里巴巴
- Mycat:阿里巴巴
MyCAT 是使用 JAVA 语言进行编写开发,使用前需要先安装 JAVA 运行环境(JRE),由于 MyCAT 中使用了 JDK7 中的一些特性,所以要求必须在 JDK7 以上的版本上运行。
二、读写分离架构
这里是在MySQL主从复制实现的基础上,利用Mycat实现的读写分离,MySQL的主从复制在我前面的博客中有详细介绍,感兴趣的朋友可以去看一下《MySQL数据库主从复制(同步)原理》、《M-S架构GTID基于事务ID复制》。本次的Mycat读写分离架构图如下所示:
实验环境:
系统:CentOS 7.4
关闭firewalld
关闭selinux
Mycat、Master和Slave三台机器分别互做本地解析
主机 | 功能 |
---|---|
192.168.139.158 | 主库(MySQL-Master)、测试客户端 |
192.168.139.159 | 备库(MySQL-Slave) |
192.168.139.160 | 数据库中间件(Mycat-Proxy) |
三、Mycat配置
3.1 安装JDK
首先下载JDK或上传JDK到服务器中。
-
解压JDK并重命名
[root@mycat ~]# tar xzf jdk-8u191-linux-x64.tar.gz -C /usr/local/ [root@mycat ~]# cd /usr/local/ [root@mycat local]# mv jdk1.8.0_191/ java
-
设置环境变量
[root@mycat local]# vim /etc/profile JAVA_HOME=/usr/local/java PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
-
使环境变量生效
[root@mycat local]# source /etc/profile
3.2 配置Mycat
首先下载或上传Mycat包到服务器中。
先认识一下Mycat的两个重要配置文件:server.xml、schema.xml,MyCAT 目前主要通过配置文件的方式来定义逻辑库和相关配置。
(1)配置server.xml
以下为主要代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<user name="root">
<property name="password">ZRSanqy@123</property>
<property name="schemas">testdb</property>
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
<!--
<user name="user">
<property name="password">user</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
</user>
-->
</mycat:server>
注意:上面的配置中,假如配置了用户访问的逻辑库,那么必须在
schema.xml
文件中也配置这个逻辑库,否则报错,启动 mycat 失败。
(2)配置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" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="localhost1" database="DB" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="master" url="master:3306" user="mycat" password="ZRSanqy@123">
<readHost host="slave" url="slave:3306" user="mycat" password="ZRSanqy@123" />
</writeHost>
</dataHost>
</mycat:schema>
(3)在真实的 master 数据库上给用户授权
注意: Master库里要有DB真实的数据库,因此得提前创建好DB库,在实际生产中,该DB库就是我们项目的数据库数据存储处。
mysql> create database DB;
Query OK, 1 row affected (0.04 sec)
mysql> grant all on DB.* to mycat@'%' identified by 'ZRSanqy@123';
mysql> flush privileges;
注意:上面的授权库为真实数据库,mycat用户为配置文件中定义的用户。
(4)在Mycat机器上测试mycat用户登录
[root@mycat ~]# yum install -y mysql # 安装mysql客户端
[root@mycat ~]# mysql -umycat -p'ZRSanqy@123' -h master
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| DB |
+--------------------+
2 rows in set (0.00 sec)
# 该测试的目的是:测试能否通过mycat用户远程登录master数据库
# -h 参数:后面跟解析的主机名或IP,表示要连接的主机
(5)启动Mycat
启动前调整一下JVM:
[root@mycat ~]# vim /usr/local/mycat/conf/wrapper.conf
wrapper.startup.timeout=300 # 超时时间300秒(需添加)
wrapper.ping.timeout=120 # ping的超时时间(已存在)
启动Mycat
[root@mycat ~]# /usr/local/mycat/bin/mycat start
通过jps查看Mycat是否启动
[root@mycat ~]# jps
1248 Jps
1164 WrapperSimpleApp # 当出现WrapperSimpleApp时,表示已经启动
也可查看Mycat端口
[root@mycat ~]# netstat -lntp | grep java
3.3 测试Mycat
将Master当做Mycat的客户端进行测试。
(1)连接到Mycat进入数据库
[root@master ~]# mysql -uroot -h mycat -p'ZRSanqy@123' -P 8066
# 这里的root用户为我Mycat机器上定义的root逻辑用户
# -h 参数:后面跟解析的主机名或IP,表示要连接的主机
# -p 参数:后面跟的是我mycat定义的逻辑用户对应的逻辑密码
# -P 参数:指定Mycat端口
(2)进去后查看数据库
mysql> show databases;
+----------+
| DATABASE |
+----------+
| testdb | # 这个是我Mycat配置文件中自定义的逻辑库名,它将通过这个逻辑库去访问我真正的DB库
+----------+
1 row in set (0.00 sec)
(3)进入testdb逻辑库并创建一张表
实际上相当于进入的是DB真实数据库,创建的表也就属于DB数据库。
mysql> use testdb;
Database changed
mysql> show tables;
Empty set (0.01 sec)
mysql> create table t1(id int);
Query OK, 0 rows affected (0.18 sec)
mysql> insert into t1 values(1);
Query OK, 1 row affected (0.04 sec)
(4)创建完后去Slave端的DB库上查看是否有t1
表
mysql> use DB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+--------------+
| Tables_in_DB |
+--------------+
| t1 |
+--------------+
1 row in set (0.00 sec) # DB真实数据库中有表
mysql> select * from DB.t1;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec) # DB真实数据库中的表有一条记录,说明读写分离成功
总结
MySQL数据库的读写分离在实际生产中是很重要的,通过读写分离,可分摊服务器压力,提高机器的系统处理效率。以上是在一主一从的基础上做的读写分离,在实际生产中还可以做一主双从,多主多从等,可根据生产实际情况来选择。