MySQL主从复制与读写分离

目录

一:案例分析

1:案例概述

2:案例前置知识点

[2.1 MySQL主从复制原理](#2.1 MySQL主从复制原理)

[(1)MySQL 支持的复制类型](#(1)MySQL 支持的复制类型)

(2)复制的工作过程

[2.2 MySQL 读写分离原理](#2.2 MySQL 读写分离原理)

3:案例环境

二:案例实施

1:搭建MySQL主从复制

[1.1 配置防火墙](#1.1 配置防火墙)

[1.2 配置Master主服务器](#1.2 配置Master主服务器)

[1.3 配置Slave从服务器](#1.3 配置Slave从服务器)

[1.4 验证主从复制效果](#1.4 验证主从复制效果)

2:搭建MySQL读写分离

[2.1 安装Mycat2](#2.1 安装Mycat2)

[2.2 安装并配置mycat软件](#2.2 安装并配置mycat软件)

[2.3 配置Mycat读写分离](#2.3 配置Mycat读写分离)

[(1)创建 Mycat2 工作所必须的账号](#(1)创建 Mycat2 工作所必须的账号)

(2)启动Mycat2

(3)Mycat2配置读写分离

[2.3 验证 Mycat 读写分离](#2.3 验证 Mycat 读写分离)


一:案例分析

1:案例概述

在实际的生产环境中,如果对数据库的读和写都在同一个数据库服务器中操作,无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,一般来说都是通过主从复制(Master-Slave)来同步数据,再通过读写分离来提升数据库并发负载能力的方案来进行部署与实施。

如图所示,一台主 MySQL 服务器带两台从 MySQL 服务器做数据复制,前端应用在进行数据库写操作时,对主服务器进行操作,在进行数据库读操作时,对两台从服务器进行操作,这样大量减轻了对主服务器的压力。

2:案例前置知识点

2.1 MySQL主从复制原理

MySQL 的主从复制和 MySQL 的读写分离两者有着紧密联系,首先要部署主从复制,只有主从复制完成了,才能在此基础上进行数据的读写分离。

(1)MySQL 支持的复制类型
  • 基于语句的复制。在主服务器上执行的 SQL 语句,在从服务器上执行同样的语句,MySQL 默认采用基于语句的复制,效率比较高。
  • 基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一遍
  • 混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
(2)复制的工作过程
  • 在每个事务更新数据完成之前,Master 将这些改变记录进二进制日志。写入二进制日志完成后,Master 通知存储引擎提交事务。
  • Slave 将 Master 的 Binary log 复制到其中继日志(Relay log)。首先,Slave 开始一个工作线程--I/0 线程,I/0 线程在 Master 上打开一个普通的连接,然后开始 Binlog dump process。Binlog dump process 从 Master 的二进制日志中读取事件,如果已经跟上 Master,它会睡眠并等待 Master 产生新的事件。I/0 线程将这些事件写入中继日志。
  • SQL slave thread(SQ 从线程)处理该过程的最后一步。SQL 线程从中继日志读取事件,并重放其中的事件而更新 Slave数据,使其与 Master 中的数据保持一致。只要该线程与 I/0 线程保持一致,中继日志通常会位于0S 的缓存中,所以中继日志的开销很小。复制过程有一个很重要的限制,即复制在S1ave 上是串行化的,也就是说 Master 上的并行更新操作不能在 Slave 上并行操作。

2.2 MySQL 读写分离原理

简单来说,读写分离就是只在主服务器上写,只在从服务器上读。基本的原理是让主数据库处理事务性查询,而从数据库处理select 查询。数据库复制被用来把主数据库上事务性查询导致的变更同步到集群中的从数据库。

分类 实现方式 优点 缺点 代表性工具/技术
基于程序代码内部实现 在代码中根据SQL类型路由 - 性能较好 - 无需额外硬件开支 - 需开发人员实现,运维困难 - 对代码改动较大,不适合复杂应用 无特定工具,依赖开发人员编码实现
基于中间代理层实现 通过代理层转发SQL请求 - 对应用透明,无需修改代码 - 适合大型复杂应用 - 需额外维护代理服务器 - 可能引入性能开销 MySQL-Proxy(官方开源,但不建议生产使用) Amoeba(支持生产,但无事务和存储过程) MyCAT(支持分布式SQL查询,兼容MySQL协

3:案例环境

主机 操作系统 IP 地址 应用
Master openEuler 24.03 192.168.10.101 MySQL-server
Slave1 openEuler 24.03 192.168.10.102 MySQL-server
Slave2 openEuler 24.03 192.168.10.103 MySQL-server
Mycat openEuler 24.03 192.168.10.104 Mycat2
客户端 openEuler 24.03 192.168.10.105 mysql

二:案例实施

1:搭建MySQL主从复制

在所有节点进行时间同步

复制代码
​​​​[root@localhost ~]# yum -y install ntpdate

​​[root@localhost ~]# ntpdate ntp1.aliyun.com
 6 Jun 15:34:14 ntpdate[3181]: step time server 47.96.149.233 offset +773136.436461 sec

1.1 配置防火墙

在每台服务器上关闭firewalld或者在防火墙上开放指定的端口和服务

复制代码
​​​​[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# systemctl disable firewalld
[root@localhost ~]# setenforce 0

1.2 配置Master主服务器

(1)在/etc/my.cnf 中修改或者增加下面内容

log-bin=/usr/local/mysql/data/mysql-bin #启用二进制日志(Binary Log)并指定其存储路径

binlog_format = MIXED #定义二进制日志的记录格式为混合模式

server-id=1 #为mysql 实例分配一个唯一的服务器标识符

(2)重启MySQL服务

复制代码
[root@localhost ~]# systemctl restart mysqld

(3)登录MySQL程序,给从服务器授权

复制代码
[root@master ~]# mysql -u root -p
mysql> ALTER USER 'root'@ localhost'IDENTIFIED WITH mysql_native_password BY,123456';
Query Ok, 0 rows affected(0.0l sec)
mysql>CREATE USER 'myslave'@'%'IDENTIFIED BY ,123456';
Query OK, 0 rows affected(0.0l sec)
mySql> GRANT REPLICATION SLAVE ON *.* To 'myslave'@'%';
Query OK, 0 rows affected(0.01 sec)
mysql>ALTER USER 'myslave'@'%'IDENTIFIED WITH mysql_native_passwordBY '123456';

#MySQL 8.0 默认使用 caching_sha2_password 认证插件,将mysql_native_password 替换为旧版认证插件,确保从库能兼容

1.3 配置Slave从服务器

在 Slave1、Slave2 服务器上面分别执行下面步骤

(1)在/etc/my.cnf 中修改或者增加下面内容,这里要注意 server-id 不能相同。

复制代码
[root@localhost # vim /etc/my.cnf
server-id=2 //增加,唯一的服务器标识符,集群内不能冲突

(2)重启 MySQL 服务。

复制代码
[root@localhost ~]# systemctl restart mysqld

(3)登录 MySQL,配置同步

按主服务器结果更改下面命令中 master_log_file 和 master_log_pos 参数

复制代码
[root@localhost ~]#mysql -uroot p
mysql> ALTER USER root'@ localhost'IDENTIFIED WITH mysql native password BY,123456';
Query OK, 0 rows affected(0.01 sec)
mysql> change master to master host='192.168.10.101',master user='myslave', master password='123456',master log file= mysql-bin.000001', master log pos=157;
Query Ok,0 rows affected, 8 warnings(0.01 sec)

(4)启动同步

复制代码
mysql>start slave;
Query OK, 0 rows affected(0.00 sec)

1.4 验证主从复制效果

(1)在主、从服务器上登录 MySQL。

复制代码
[root@localhost # mysql-u root -p
mysql>show databases;

(2)在主服务器上新建数据库 db test。

复制代码
mysql>create database db_test;

(3)在两台从服务器上分别查看数据库,显示数据库相同,则主从复制成功

2:搭建MySQL读写分离

MyCAT是目前最流行的分布式数据库中间插件,是一个开源的分布式数据库系统,是一个实现了 MySQL,协议的服务器。前端用户可以把它看作一个数据库代理,用 MySQL 客户端工具和命令行访问,其后端可以用 MySQL 原生协议与多个 MySQL 服务器通信,也可以用 JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端 MySQL 服务器里或者其他数据库里。

MyCAT 发展到目前,已经不是一个单纯的 MySQL 代理了,它的后端可以支持MySQL、SQL Server、0racle、DB2、PostgreSQl 等主流数据库,也支持 MongoDB 这种新型 NoSQL 方式的存储。未来,它还会支持更多类型的存储。

不过,无论是哪种存储方式,在最终用户看,MyCAT里都是一个传统的数据库表,支持标准的 SQL语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度。

2.1 安装Mycat2

Mycat 需要依赖于 JAVA,因此需要在读写分离代理所在的系统预先安装,JAVA环境

复制代码
[root@localhost ~l# dnf install jdk-8u171-linux-x64.rpm

2.2 安装并配置mycat软件

unzip 解开后 mycat2 安装包,将其移动到目录"/usr/local",并重命名为"mycat".具体的命令如下:

复制代码
[root@localhost ~]# unzip mycat2-install-template-1.20.zip -d /usr/local/
[root@localhost ~]# ls /usr/local/mycat/
bin conf lib logs

为简化输入,可将系统环境变量文件"/etc/profile"最后一行的内容追加 Mycat 安装目录的可执行文件所在绝对路径,更新后的"/etc/profile"文件最后一行的完整内容为:

复制代码
[root@localhost ~]# echo 'export PATH=$PATH:/usr/local/mycat/bin'>>/etc/profile
[root@localhost ~]# source /etc/profile

把依赖包 mycat2-1.21-release-jar-with-dependencies.jar 和 mysql-connector-java-8.0.18.jar,原样移动或者复制到目录"/usr/local/mycat/lib"

复制代码
【root@localhost ~]# cp mycat2-1.21-release-jar-with-dependencies. jar mysql-connector-java-8.0.18.jar /usr/local/mycat/lib

为 Mycat 命令添加执行权限

复制代码
[root@localhost ~]# chmod -R +x /usr/local/mycat/bin

到目前为止,安装的步骤基本上算是完成了,任意命令行下执行指令"mycat -h",!验证安装的正确性

复制代码
[root@localhost ~]#mycat -h
Usage:/usr/local/mycat/bin/mycat { console | start | stop | restart | status | dump }

2.3 配置Mycat读写分离

(1)创建 Mycat2 工作所必须的账号

启动 Mycat2服务,需要有真实的数据库服务器支撑才能运行,因此,需要在 MySQL 服务器(其它被 Mycat2 支持的数据库也如此)创建账号并给账号授权然后在 Mycat2 所在的宿主系统用MySQL, 客户端用创建好的账号远程进行连接,验证账号的有效性和正确性。

在前边的章节,我们已经做好了 MySQL数据库间的主从同步,因此创建 Mycat2所需账号的操作只需也只能在主数据库上进行,具体的指令如下:

复制代码
mysql> create user ,mycat'@'% identified by ,pwd123';
Query Ok, 0 rows affected(0.04 sec)
mysql>grant all on *.* to 'mycat'@'%';
Query Ok, 0 rows affected(0.0l sec)
mysql> ALTER USER 'mycat'@'%'IDENTIFIED WITH mysql native password BY'pwd123';
Query Ok,0 rows affected (0.01 sec)
mysql> flush privileges;
Query Ok, 0 rows affected (0.0l sec)
(2)启动Mycat2

与 Mycat1.x版本相比,Mycat2 的配置基本不需要手动去修改配置文件,而是可以在 Mycat2 启动之后,登录 Mycat 管理后台,用 SQL 指令或者客户端工具进行配置。在启动 Mycat2之前,需要对原型库的数据源做相应的修改,修改的项主要是主数据库的连接信息,一个完整的修改过的原型数据源文件"/usr/1ocal/mycat/conf/datasources/prototypeDs.datasource.json"的内容如下:被修改过的内容,以红色字显示

{

"dbType" :"mysql"

"idleTimeout":60000,

"initSqls":[],

"initSqlsGetConnection":true,

"instanceType":"READ WRITE",

" maxCon":1000,

"maxConnectTimeout":30000,

"maxRetryCount" :5,

"minCon":1,

"name": prototypeDs

"password":"pwd123"

"queryTimeout":0,

"type":"JDBC",

"url":"jdbc:mysql://192.168.10.101:3306/mysql? serverTimezone=Asia

/Shanghai&useUnicode=true&characterEncoding-UTF-8&autoReconnect=true",

"user":"mycat'

"weight":0

}

因为已经对系统变量做了设置,所以在任意路径执行"mycat start"就可以启动 Mycat2。在 Mycat2 的安装目录"/usr/local/mycat"下,存在目录"logs",打开此目录中的日志文件"wrapper.log",可了解 Mycat2 服务的运行状况

复制代码
[root@localhost conf]# mycat start
Starting mycat2...
(3)Mycat2配置读写分离

两种配置 MySQL 读写分离的方法,一种是直接在 Mycat 的配置目录"/usr/1ocal/mycat/conf"的子目录编辑相关的文本文件(Mycat1.x版本只用这种方法)另一种登录到 Mycat 交互界面,用特殊语法的 SQL 命令进行配置。本教程采用第二种方法,直接在 Mycat 的交互界面输入命令。

第一步:Mycat 增加数据源

需要正确输入的数据主要包括: MySQL, 主从数据库的 IP 地址、数据库库名(schema)、数据库账号、数据库密码(生产数据库请使用复杂密码)、实例类型(READ、WRITE 或 READ WRITE)。下边是添加一个主库源和两个从库源的具体指令:

复制代码
[root@localhost ~]# mysql -uroot -p123456 -P8066 -h192.168.10.101

增加主库 master:

复制代码
mysql>/*+ mycat:createDataSource{ "name":"master","url":"jdbc:mysql://192.168.10.101:3306/?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true","instanceType":"WRITE","user":"mycat","password":"pwd123"} */;
Query OK, 0 rows affected (0.01 sec)

增加从库slavel和slave2:

复制代码
mysql>/*+ mycat:createDataSource{ "name":"slave1","url":"jdbc:mysql://192.168.10.102:3306/?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true","instanceType":"READ","user":"mycat","password":"pwd123"} */;
Query OK, 0 rows affected (0.01 sec)
mysql>/*+ mycat:createDataSource{ "name":"slave2","url":"jdbc:mysql://192.168.10.103:3306/?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true","instanceType":"READ","user":"mycat","password":"pwd123"} */;
Query OK, 0 rows affected (0.01 sec)

查看数据源信息:

如数据源配置有误可使用"/*+ mycat:resetConfig{} */;" 进行重置

第二步:创建 Mycat 集群

在本案例中,集群成员包括一个主库与两个从库。根据业务场景,也可以创建多个集群,充分、有效的利用系统资源。创建 Mycat 集群的 SQL,语句如下:

复制代码
mysql>/*! mycat:createCluster{"name":"cls01","masters":["master"],"replicas":["slave1","slave2"]} */;

修改负载均衡的默认轮询

修改配置后重启mycat

复制代码
[root@localhost conf]# mycat restart
Stopping mycat2...
Stopped mycat2...
Starting mycat2...

2.3 验证 Mycat 读写分离

(1)登录 mycat 集群,创建测试库和测试表

复制代码
[root@localhost ~】# mysql -uroot -p123456 -P8066 -h192.168.10.101mysql>create database test;
Query OK, 0 rows affected(0.47 sec)

注意:

创建完库以后在 mycat 的 schemas 目录下会有一个以该库明明的文件,要修改这个文件标注上 mycat 的集群,然后重启 mycat。

复制代码
[root@localhost schemas]# pwd
/usr/local/mycat/conf/schemas
[root@localhost schemas]# 1l
总计 8
-rw-r--r-- 1 root root 143 3月27日 15:09 test.schema. json
[root@localhost schemas# cat test.schema.json
{
    "customTables":{},
    "globalTables":{},
    "normalProcedures":{},
    "normalTables": {},
    "schemaName":"test",
    "targetName":"cls01"
    "shardingTables":{},
    "views":{}
}
#重启mycat
[root@localhost schemas]# mycat restart

mysql> create table test.zang(id int(10),name varchar(10),address varchar(20));
Query Ok, 0 rows affected(0.47 sec)

创建库和表的操作会路由到 master 执行,并被同步到slave 节点

(2)停止salve1和slave2的主从同步

复制代码
[root@localhost# mysql -uroot -p
mysql> stop slave;
Query OK, 0 rows affected, l warning(0.01 sec)

(3)在 master 和 slave1、slave2 创建测试数据

Master 上操作

复制代码
mysql> use test;
Database changed
mysql>insert into test.zang values('1','zhang' ,'this_is_master');
Query OK, l row affected(0.0l sec)

Slave1 上操作

复制代码
mysql> use test;
Database changed
mysql>insert into test.zang values('2','zhang' ,'this_is_slave1');
Query OK, l row affected(0.0l sec)

Slave2 上操作

复制代码
mysql> use test;
Database changed
mysql>insert into test.zang values('3','zhang' ,'this_is_slave2');
Query OK, l row affected(0.0l sec)

(4)测试读操作

登录 mycat 集群,查询 test.zang 的数据

复制代码
​​​​mysql> select * from test.zhang;    #第一次查询
+------+-------+----------------+
| id   | name  | address        |
+------+-------+----------------+
|    2 | zhang | this is slavel |
+------+-------+----------------+
1 row in set (0.01 sec)

​​​​mysql> select * from test.zhang;    #第二次查询
+------+-------+----------------+
| id   | name  | address        |
+------+-------+----------------+
|    3 | zhang | this is slave2 |
+------+-------+----------------+
1 row in set (0.01 sec)

​​​​mysql> select * from test.zhang;    #第三次查询
+------+-------+----------------+
| id   | name  | address        |
+------+-------+----------------+
|    2 | zhang | this is slave3 |
+------+-------+----------------+
1 row in set (0.01 sec)

(5)测试写操作

登录 mycat 集群执行写入操作

复制代码
[root@localhost ]# mysql -uroot -p123456 -P8066 -h192.168.10.101
MySQL [(none)]>insert into zang values('4','zhang ,'write test');
Query OK,l row affected(0.08 sec)

但在 slave1 和 slave2上查询不到,最终只有在 Master 上才能查看到这条语句内容,说明写操作在 Master 服务器上。由此验证,已经实现了 MySQL 读写分离。目前所有的写操作都全部在 Master 主服务器上,用来避免数据的不同步;所有的读操作都分摊给了 Slave 从服务器,用来分担数据库压力。

相关推荐
@小红花34 分钟前
MySQL数据库从0到1
数据库·mysql·oracle
[听得时光枕水眠]1 小时前
MySQL基础(三)DQL(Data Query Language,数据查询语言)
数据库·mysql·oracle
我科绝伦(Huanhuan Zhou)1 小时前
深入解析Oracle SQL调优健康检查工具(SQLHC):从原理到实战优化
数据库·sql·oracle
一只叫煤球的猫5 小时前
MySQL 8.0 SQL优化黑科技,面试官都不一定知道!
后端·sql·mysql
寒山李白5 小时前
MySQL安装与配置详细讲解
数据库·mysql·配置安装
文牧之5 小时前
PostgreSQL 的扩展pg_freespacemap
运维·数据库·postgresql
deriva6 小时前
某水表量每15分钟一报,然后某天示数清0了,重新报示值了 ,如何写sql 计算每日水量
数据库·sql
Leo.yuan7 小时前
数据库同步是什么意思?数据库架构有哪些?
大数据·数据库·oracle·数据分析·数据库架构
zhangzhangkeji7 小时前
(33)课54--??:3 张表的 join-on 连接举例,多表查询总结。
mysql