一、读写分离
1、什么是读写分离?
读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。
数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。
2、为什么要读写分离呢?
因为数据库的“写”(写10000条数据可能要3分钟)操作是比较耗时的。
但是数据库的“读”(读10000条数据可能只要5秒钟)。
所以读写分离,解决的是,数据库的写入,影响了查询的效率
3、什么时候要读写分离?
数据库不一定要读写分离,如果程序使用数据库较多时,而更新少,查询多的情况下会考虑使用。
4、MySQL 读写分离原理
读写分离就是只在主服务器上写,只在从服务器上读。
主数据库(Master)负责处理所有的写操作,它维护着完整的数据集。
而从数据库(Slave)通过复制主数据库的数据,提供只读的服务。
基本的原理是让主数据库处理事务性操作,而从数据库处理 select 查询。
5、常见的实现方式
1、基于程序代码内部实现
在代码中根据 select、insert 进行路由分类,这类方法也是目前生产环境应用最广泛的。
优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;
缺点是需要开发人员来实现,运维人员无从下手。
但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程序代码中实现读写分离对代码改动就较大。
2、基于中间代理层实现
理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有以下代表性程序。
1)MySQL-Proxy
MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua 脚本进行SQL 判断。
2)Atlas
是由奇虎360的Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。
它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。
360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。
支持事物以及存储过程。
3)Amoeba
由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。
4)Mycat
是一款流行的基于Java语言编写的数据库中间件,是一个实现了MySql协议的服务器,其核心功能是分库分表。配合数据库的主从模式还可以实现读写分离。
由于使用MySQL Proxy 需要写大量的Lua脚本,这些Lua并不是现成的,而是需要自己去写。这对于并不熟悉MySQL Proxy 内置变量和MySQL Protocol 的人来说是非常困难的。
Amoeba是一个非常容易使用、可移植性非常强的软件。因此它在生产环境中被广泛应用于数据库的代理层。
二、读写分离实验
1、配置/etc/hosts,并传输到slave和 mycat主机
[root@master ~]# vim /etc/hosts
[root@master ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.100.10 master.example.com master
192.168.100.40 slave.example.com slave
192.168.100.50 mycat.example.com mycat
[root@master ~]#
[root@master ~]# scp /etc/hosts root@192.168.100.40:/etc/hosts
root@192.168.100.40's password:
hosts 100% 291 131.9KB/s 00:00
[root@master ~]# scp /etc/hosts root@192.168.100.50:/etc/hosts
The authenticity of host '192.168.100.50 (192.168.100.50)' can't be established.
ED25519 key fingerprint is SHA256:Ci2qzv2Hvt2jld5Q8LBu35qRbAnKzC3EaGZRV6Htsw0.
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:1: 192.168.100.40
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.100.50' (ED25519) to the list of known hosts.
root@192.168.100.50's password:
hosts 100% 291 115.9KB/s 00:00
2、下载JAVA包,查看JAVA版本
[root@mycat ~]# yum -y install java java-devel
[root@mycat ~]# java -version
openjdk version "11.0.24" 2024-07-16 LTS
OpenJDK Runtime Environment (Red_Hat-11.0.24.0.8-2) (build 11.0.24+8-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-11.0.24.0.8-2) (build 11.0.24+8-LTS, mixed mode, sharing)
3、解压包
[root@mycat ~]# tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/
[root@mycat ~]# cd /usr/local/
[root@mycat local]# ls
bin etc games include lib lib64 libexec mycat mysql mysql-5.7.37-linux-glibc2.12-x86_64 sbin share src
[root@mycat local]#
4、设置环境变量
[root@mycat local]# vim /etc/profile
export MYCAT_HOME=/usr/local/mycat
[root@mycat local]# source /etc/profile
[root@mycat local]# echo $MYCAT_HOME
/usr/local/mycat/
5、编辑mycat服务读写分离的schema.xml
[root@mycat mycat]# vim /usr/local/mycat/conf/schema.xml
//删除所有内容,添加以下内容
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="USERDB" checkSQLschema="true" sqlMaxLimit="100" dataNode="dn1"></schema>
<dataNode name="dn1" dataHost="localhost1" database="Great " /> //database="Great "是主库和从库都存在的数据库
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3" dbType="mysql" dbDriver="native" writeType="0" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.100.10:3306" user="root" password="redhat"> //主库IP地址
<readHost host="hostS1" url="192.168.100.40:3306" user="root" password="redhat" /> //从库IP地址
</writeHost>
</dataHost>
</mycat:schema>
6、编辑mycat用户
删除以下几行(最后的五行)
<user name="user">
<property name="password">user</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
</user>
修改以下内容
<user name="root">
<property name="password">123456</property>
<property name="schemas">USERDB</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>
7、启动mycat服务并查看是否启动8066、9066端口
[root@mycat ~]# cd /usr/local/mycat/bin/
[root@mycat bin]# ./mycat start
Starting Mycat-server...
[root@mycat bin]# ss -anlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 1 127.0.0.1:32000 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 100 *:9066 *:*
LISTEN 0 50 *:43677 *:*
LISTEN 0 80 *:3306 *:*
LISTEN 0 50 *:34569 *:*
LISTEN 0 50 *:1984 *:*
LISTEN 0 100 *:8066 *:*
8、在master和slave节点分别给root数据库用户授权
应master和slave节点做了主从关系所以只需要master上做一次就可以了
mysql> use mysql;
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> select User,Host from user;
+---------------+----------------+
| User | Host |
+---------------+----------------+
| chenyu | % |
| repl | 192.168.100.40 |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+---------------+----------------+
5 rows in set (0.00 sec)
mysql> grant all privileges on *.* to 'root'@'%' identified by 'redhat' with grant option;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> select User,Host from user;
+---------------+----------------+
| User | Host |
+---------------+----------------+
| chenyu | % |
| root | % |
| repl | 192.168.100.40 |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+---------------+----------------+
6 rows in set (0.00 sec)
9、在本地使用数据端口登录到mysql数据中,查询和插入数据,然后使用管理端口查看读写分离效果
[root@mycat bin]# mysql -uroot -p123456 -P8066 -h127.0.0.1
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server (OpenCloundDB)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+----------+
| DATABASE |
+----------+
| USERDB |
+----------+
1 row in set (0.00 sec)
mysql>
//做查询、添加、删除、修改操作
[root@mycat ~]# mysql -h127.0.0.1 -P9066 -uroot -p123456 -e 'show @@datasource;'
mysql: [Warning] Using a password on the command line interface can be insecure.
+----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+
| DATANODE | NAME | TYPE | HOST | PORT | W/R | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |
+----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+
| dn1 | hostM1 | mysql | 192.168.100.10 | 3306 | W | 0 | 1 | 1000 | 34 | 0 | 1 |
| dn1 | hostS1 | mysql | 192.168.100.40 | 3306 | R | 0 | 1 | 1000 | 17 | 4 | 0 |
+----------+--------+-------+----------------+------+------+--------+------+------+---------+-----------+------------+