MySQL读写分离
什么是读写分离
让主数据库(master)处理增、删、改操作(INSERT、UPDATE、DELETE),而从数据库(slave)处理查询的操作(SHOW、SELECT)。
为什么要读写分离呢
在实际的生产环境中,对数据库的读和写都在一个数据库服务器中,是不能满足实际需求的。无论是在安全性、高可用性,还是高并发性等各个方面是不能满足实际需求的。因此,通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力。
数据库的写(写10000条数据到数据库中可能要几分钟)操作是比较耗时的
但是数据库中的读(从数据库读10000条数据可能几秒钟)
所以读写分离解决的是,数据库的写入,影响了查询的效率
Mycat
Mycat是数据库中间件,中间件就是一类连接软件组件和应用计算机软件,以便于软件各部件之间的沟通。
Mycat能干什么?
- 读写分离
-
数据分片
-
多数据源整合
Mycat原理
Mycat 的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的 SQL 语句,首先对 SQL
语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此 SQL 发
往后端的真实数据库, 并将返回的结果做适当的处理,最终再返回给用户
部署MysSQL读写分离
IP | 主机名 | 节点 |
---|---|---|
192.168.200.10 | master | master主数据库 |
192.168.200.20 | slave | slave从数据库 |
192.168.200.30 | mycat | mycat中间件 |
MySQL读写分离是基于主从复制的基础上的
配置主从数据库
1. 更改主机名
[root@localhost ~]# hostnamectl set-hostname master
[root@localhost ~]# bash
[root@master ~]#
[root@localhost ~]# hostnamectl set-hostname slave
[root@localhost ~]# bash
[root@slave ~]#
2. 使用yum安装mariadb(master和slave节点都执行)
yum install -y mariadb-server
4.开启mysql服务并设置开机自启(master和slave节点都执行)
systemctl enable mariadb --now
6.设置密码(master和slave节点都执行)
mysql_secure_installation # 初始化数据库
7. 设置root访问权限(master和slave节点都执行)
mysql -uroot -p000000 -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '000000';flush privileges;"
6. 关闭防火墙(master和slave节点都执行)
systemctl stop firewalld && systemctl disable firewalld && setenforce 0
8. 配置master主数据库,修改mysql数据库配置文件,配置完重启服务
[root@master ~]# vim /etc/my.cnf
# [mysqld]添加如下信息
server-id=10
log_bin
# 设置不要复制的数据库(可设置多个)
binlog-ignore-db=mysql
# 设置需要复制的数据库
binlog-do-db=testdb
# 设置logbin格式
binlog_format=STATEMENT
[root@master ~]# systemctl restart mariadb
9. 登录mysql创建用于复制的账户并授权
[root@master ~]# mysql -uroot -p000000
MariaDB [(none)]> grant replication slave on *.* to 'csq'@'192.168.200.%' identified by '000000';
10. 显示主节点上的二进制日志文件列表
# 下面的Log_name和File_size是需要我们记住的
MariaDB [(none)]> show master logs;
+--------------------+-----------+
| Log_name | File_size |
+--------------------+-----------+
| mariadb-bin.000001 | 398 |
+--------------------+-----------+
11.配置从数据库slave,修改mysql数据库配置文件,配置完重启服务
[root@slave ~]# vim /etc/my.cnf
# [mysqld]添加如下信息
server-id=20
relay-log=mysql-relay
[root@slave ~]# systemctl restart mariadb
12. 登录数据库,配置连接主数据库的信息
[root@slave ~]# mysql -uroot -p000000
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='192.168.200.10',
-> MASTER_USER='csq',
-> MASTER_PASSWORD='000000',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mariadb-bin.000001',
-> MASTER_LOG_POS=398;
# MASTER_LOG_FILE 和 MASTER_LOG_POS
# 这两个参数就是指定主数据库的二进制日志文件名称和位置
13. 启动从节点的主从复制
MariaDB [(none)]> start slave;
14. 查看主从复制的状态
MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.200.10
Master_User: csq
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000001
Read_Master_Log_Pos: 398
Relay_Log_File: mysql-relay.000002
Relay_Log_Pos: 531
Relay_Master_Log_File: mariadb-bin.000001
Slave_IO_Running: Yes # 两个都为YES即为配置主从复制成功
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 398
Relay_Log_Space: 821
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 10
15. 测试创建testdb库
# 主节点创建testdb数据库
[root@master ~]# mysql -uroot -p000000 -e "create database testdb;"
# 从节点查看是否同步
[root@slave ~]# mysql -uroot -p000000 -e "show databases;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| testdb |
+--------------------+
# master主数据库中的testdb数据库创建一张表写入一些内容,查看从数据库是否能查询到
[root@master ~]# mysql -uroot -p000000 -e "use testdb; create table mytbl(id int,name varchar(20));insert into mytbl values(1,'csq');"
[root@slave ~]# mysql -uroot -p000000 -e "use testdb;select * from mytbl;"
+------+------+
| id | name |
+------+------+
| 1 | csq |
+------+------+
# 可以看到创建的数据,数据同步成功
安装JDK
在Mycat节点安装JDK
第一步:更改主机名,下载JDK到Linux根目录下
[root@localhost ~]# hostnamectl set-hostname mycat
[root@localhost ~]# bash
[root@mycat ~]# ls
anaconda-ks.cfg jdk-8u144-linux-x64.tar.gz
第二步:解压到/usr/local/目录下
[root@mycat ~]# tar -zxf jdk-8u144-linux-x64.tar.gz -C /usr/local/
[root@mycat ~]# cd /usr/local/jdk1.8.0_144/
[root@mycat jdk1.8.0_144]# pwd
/usr/local/jdk1.8.0_144
第三步:配置环境变量
[root@mycat jdk1.8.0_144]# vim /etc/profile
JAVA_HOME=/usr/local/jdk1.8.0_144/
PATH=${PATH}:${JAVA_HOME}/bin
export JAVA_HOME PATH
[root@mycat jdk1.8.0_144]# source /etc/profile
第四步:测试
[root@mycat jdk1.8.0_144]# java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
安装Mycat并配置读写分离
第一步:下载
[root@mycat ~]# wget http://dl.mycat.org.cn/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
第二步:解压到 /usr/local/目录下
[root@mycat ~]# tar -zxf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/
[root@mycat ~]# cd /usr/local/mycat/
[root@mycat mycat]# ls
bin catlet conf lib logs version.txt
[root@mycat mycat]# cd conf/
- bin:该目录包含了Mycat的可执行文件和相关脚本文件
- catlet:该目录下存放了Mycat的插件模块文件,主要用于自定义一些特定的功能和扩展
- conf:该目录包含了Mycat的配置文件,用于配置Mycat的各项参数和规则
- lib:该目录包含了Mycat的依赖库文件,用于支持Mycat运行所需的各种功能
- logs:该目录包含了Mycat的日志文件,记录了Mycat的运行日志和错误信息
- version.txt:该文件记录了Mycat的版本号信息,用于查看当前安装的Mycat的版本号
第三步:mycat配置
-
server.xml:定义用户以及系统相关变量,如端口等
-
rule.xml:定义分片规则
-
schema.xml:定义逻辑库,表、分片节点等内容
修改配置文件server.xml
在文件的最下面
修改配置文件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="host1" database="testdb" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.200.10:3306" user="root"
password="000000">
<readHost host="hostS1" url="192.168.200.20:3306" user="root" password="000000" />
</writeHost>
</dataHost>
</mycat:schema>
注意:
-
schema节点中的“name”的值和server.xml文件中user节点中的“schemas”值一样。
-
dataNode节点中的“database”为需要复制的数据库名称。
-
dateNode节点中的"dateHost"要和dateHost中的name值一样
修改的balance属性,通过此属性配置读写分离的类型
负载均衡类型,目前的取值有4种:
(1)balance=“0”,不开启读写分离机制,所以读操作都发送到当前可用的writeHost上
(2)balance=“1”,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡
(3)balance=“2”,所有读操作都随机的在writeHost、readhost上分发。
(4)balance=“3”,所有读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力。
开启Mycat
开启Mycat
[root@mycat ~]# cd /usr/local/mycat/bin/
[root@master bin]# ./mycat start
# 测试是否开启成功
[root@mycat bin]# ps -ef |grep mycat
[root@mycat bin]# netstat -ltnp |grep java
登录mycat管理端口
[root@mycat bin]# yum install -y mariadb-server mariadb
[root@mycat bin]# mysql -uroot -p000000 -h127.0.0.1 -P 9066
查看读写配置情况
MySQL [(none)]> show @@datasource;
+----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+
| DATANODE | NAME | TYPE | HOST | PORT | W/R | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
+----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+
| dn1 | hostM1 | mysql | 192.168.200.10 | 3306 | W | 0 | 10 | 1000 | 57 | 0 | 0 |
| dn1 | hostS2 | mysql | 192.168.200.20 | 3306 | R | 0 | 5 | 1000 | 56 | 3 | 0 |
+----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+
查看心跳信息
MySQL [(none)]> show @@heartbeat;
+--------+-------+----------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
| NAME | TYPE | HOST | PORT | RS_CODE | RETRY | STATUS | TIMEOUT | EXECUTE_TIME | LAST_ACTIVE_TIME | STOP |
+--------+-------+----------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
| hostM1 | mysql | 192.168.200.10 | 3306 | 1 | 0 | idle | 0 | 1,1,1 | 2023-07-27 21:56:53 | false |
| hostS2 | mysql | 192.168.200.20 | 3306 | 1 | 0 | idle | 0 | 0,0,0 | 2023-07-27 21:56:53 | false |
+--------+-------+----------------+------+---------+-------+--------+---------+--------------+---------------------+-------+
读写分离验证
登录mycat数据端口
[root@mycat bin]# mysql -uroot -p000000 -h127.0.0.1 -P 8066
MySQL [(none)]> use TESTDB;
MySQL [TESTDB]> select * from mytbl; # 下面的数据是我们之前主从复制写的数据
+------+------+
| id | name |
+------+------+
| 1 | csq |
+------+------+
# 验证读写分离,我们直接插入一条数据
MySQL [TESTDB]> insert into mytbl values(1,@@hostname);
# 插入成功然后再次查询一下
MySQL [TESTDB]> select * from mytbl;
+------+-------+
| id | name |
+------+-------+
| 1 | csq |
| 1 | slave |
+------+-------+
# 可以看到跳转到了从库
我们使用192.168.200.10数据库访问一下
[root@master ~]# mysql -uroot -p000000 -e "use testdb;select * from mytbl;"
+------+--------+
| id | name |
+------+--------+
| 1 | csq |
| 1 | master |
+------+--------+
我们使用192.168.200.20数据库访问一下
[root@slave ~]# mysql -uroot -p000000 -e "use testdb;select * from mytbl;"
+------+-------+
| id | name |
+------+-------+
| 1 | csq |
| 1 | slave |
+------+-------+
测试完成读写分离成功