深入浅出MySQL主从复制与读写分离原理及其实践

目录

一、主从复制

(一)主从复制简介

1.基本概述

2.复制类型

(二)主从复制流程与影响因素

1.主从复制的流程

2.影响因素

(三)实现主从复制

1.搭建时间同步

2.配置master服务器

[2.1 开启二进制日志](#2.1 开启二进制日志)

[2.2 用户授权](#2.2 用户授权)

3.配置slave服务器

[3.1 配置从服务器接收](#3.1 配置从服务器接收)

[3.2 连接主服务器](#3.2 连接主服务器)

二、读写分离

(一)读写分离的概念

1.基本概念

2.读写分离的作用

(二)实现读写分离的方式

1.基于数据库层面

2.中间件代理方式

3.程序代码层面

4.云服务提供商集成方案

(三)实现读写分离

1.基于主从复制

2.部署Amoeba服务器

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

[2.2 安装Amoeba](#2.2 安装Amoeba)

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

3.客户端进行测试

总结


在大型互联网应用中,数据库作为核心组件,其稳定性和性能直接影响着整个系统的健壮性。MySQL作为广泛应用的关系型数据库管理系统,提供了强大的主从复制与读写分离功能,帮助企业搭建高性能、高可用的数据库架构。本文将详细介绍MySQL主从复制与读写分离的原理,并探讨其在实际应用中的实践。

一、主从复制

(一)主从复制简介

1.基本概述

MySQL主从复制是一种数据同步技术,通过在主数据库(Master)和从数据库(Slave)间建立复制关系,使得主数据库的任何数据变更都能自动同步到从数据库中。这种机制极大地增强了数据的安全性和系统的容错能力,也为读写分离提供了技术基础。

2.复制类型

mysq支持的复制类型有以下三种

1.1 STATEMENT:基于语句的复制。在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高。

1.2 ROW:基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一遍。

1.3 MIXED:混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。

(二)主从复制流程与影响因素

1.主从复制的流程

MySQL主从复制的核心在于二进制日志(Binary Log)。主数据库在每一次事务提交时,都会把相关的SQL语句和元数据变化记录在二进制日志中。从数据库通过I/O线程(Dump Thread)连接到主数据库,请求并接收这些二进制日志事件

  1. 当Slave库与Master库建立复制关系后,Slave库的I/O线程会连接到Master库,并请求从Master库的二进制日志的特定位置(如当前Slave库已知的最后一个事件的下一个位置)开始读取事件。

  2. Master库响应Slave库的请求,将二进制日志中的事件传送给Slave库的I/O线程。

  3. I/O线程接收到Master库发来的二进制日志事件后,将这些事件写入到Slave库本地的中继日志中。

  4. 一旦事件被写入到中继日志,Slave库的SQL线程就会从中继日志中读取这些事件,并在Slave库上执行这些事件,从而实现数据的同步。

2.影响因素

在主从复制的过程中,有些因素可能导致主从复制延迟或者失败

二进制日志配置

binlog_format:二进制日志的格式,如STATEMENT、ROW或MIXED,不同的格式会影响复制的精确度和兼容性。

log-bin:是否启用二进制日志,这是主从复制的基础。

server_id:每个MySQL实例都需要一个唯一的server_id,用于标识主从关系。

复制用户权限: 从服务器的复制用户需要有足够的权限从主服务器读取二进制日志,并在从服务器上执行这些日志中的SQL语句。

网络稳定性: 主从之间的网络通信质量至关重要,网络中断或延迟可能导致主从数据不一致或复制延迟。

主从数据库版本兼容性: 主从服务器的MySQL版本应当尽可能接近,跨大版本的复制可能带来未知的风险和问题。

主从数据库架构一致性: 主从数据库的表结构、字符集等需要保持一致,否则可能导致复制失败。

主从数据库同步延迟: 由于主从复制通常是异步或半同步模式,因此从库的数据会有一定程度的延迟。如果应用不能容忍这种延迟,则需要评估是否适合采用主从复制方案。

主库性能: 主库的写入压力和性能会影响到复制的速度和稳定性,特别是在高并发写入场景下。

中继日志与事务安全: 从服务器的中继日志(relay log)管理,包括中继日志的清理策略、磁盘空间充足性等都会影响复制的正常运行。

GTID(全局事务标识符): 如果启用了GTID,主从间的事务管理和故障切换会更加便捷,但同时也引入了额外的配置和管理复杂性。

复制过滤: 有时可能需要对某些数据库或表设置复制过滤规则,但这可能导致主从数据不一致,需要谨慎设置和管理。

(三)实现主从复制

环境准备

|---------------|-------------------|
| MASTER服务器 | 192.168.83.20 |
| SLAVE1服务器 | 192.168.83.40 |
| SLAVE2服务器 | 192.168.83.60 |

1.搭建时间同步

在构建MySQL主从复制架构时,确保主从服务器之间的系统时间同步是非常重要的。这是因为MySQL在处理事务和记录二进制日志时依赖于系统时间戳,时间不一致可能会导致主从复制出现问题,如数据不一致或复制中断

cs 复制代码
##主服务器设置##
yum install ntp -y
#下载ntp服务

vim /etc/ntp.conf
--末尾添加--
server 127.127.10.0							#设置本地是时钟源,注意修改网段
fudge 127.127.10.0 stratum 8				#设置时间层级为8(限制在15内)

systemctl start ntpd
#启动服务


##从服务器设置##
yum install ntp ntpdate -y

systemctl start ntpd
#启动服务

/usr/sbin/ntpdate 192.168.83.20
#进行时间同步,192.168.83.20为master服务器ip地址

crontab -e
*/30 * * * * /usr/sbin/ntpdate 192.168.83.20
#制定计划任务,每半小时进行一次时间同步

2.配置master服务器

2.1 开启二进制日志

在/etc/my.cnf文件中添加以下字段

cs 复制代码
server-id = 1
#这个参数是为MySQL服务器分配的一个唯一标识号。在主从复制环境中,无论是主服务器还
#是从服务器,都必须设置一个唯一的server-id。

log-bin=master-bin
#log-bin用于开启二进制日志,这是实现MySQL主从复制的关键特性。这里的master-bin是指定
#二进制日志的前缀名称,二进制日志文件将以master-bin.000001,master-bin.000002等格式生成。

binlog_format = MIXED
#binlog_format 参数用于设置二进制日志记录格式。可能的值包括 STATEMENT、ROW 和 MIXED。
#MIXED 是一种混合模式,根据实际情况自动在STATEMENT和ROW模式之间切换。

log-slave-updates=true
#当设置 log-slave-updates参数为true时,从服务器在执行主服务器传过来的更新时,也会把这些
#更新记录到自己的二进制日志中。这样一来,如果从服务器又被其他从服务器复制,那么这个从服务
#器也可以成为新的主服务器,形成级联复制链。

修改完毕之后重新启动服务:systemctl restart mysqld

2.2 用户授权

登录MySQL服务,给用户授权

cs 复制代码
grant #SQL命令,用于授予用户特定的权限。

replication slave #指定要授予的权限类型,这里是与主从复制相关的权限

on *.* #指定了授权范围,*分别代表所有数据库和所有表即此用户在任何数据库的所有表上都有复制权限。

'myslave'@'192.168.83.%'
#定义了用户名及其允许连接的IP地址范围。这里创建了一个名为 'myslave' 的用户,并且允许来自
#192.168.83.0/24网段内的任何IP地址连接。百分号 % 表示任意主机名或IP地址。

IDENTIFIED BY '123456' 
#设置用户的密码为'123456',当从服务器尝试连接主服务器进行同步时,需要使用该密码进行身份验证。

使用:show master status; 指令查询主服务器二进制日志状态的命令

File:当前二进制日志(Binary Log)文件的名称

Position:在当前二进制日志文件中的下一个事件(event)的位置。这个位置值对于从服务器而言至关重要,因为它需要从这个位置开始读取和执行主服务器上的事件,从而保持数据同步。

3.配置slave服务器

3.1 配置从服务器接收

在/etc/my.cnf文件中添加以下字段

cs 复制代码
server-id = 2
#该从服务器唯一标识符2

relay-log=relay-log-bin
#relay-log用于设置中继日志(Relay Log)的文件名前缀。
#接收到主服务器的二进制日志事件后,这些事件会先写入到中继日志中,然后再从中继日志中读取并执行
#这里设置为relay-log-bin,那么生成的中继日志文件会是类似于relay-log-bin.000001这样的格式。

relay-log-index=slave-relay-bin.index
#relay-log-index用于设置中继日志索引文件的名称。中继日志索引文件记录了每个中继日志文件及其
#对应的第一条和最后一条事件的位置信息,便于从服务器快速定位到需要执行的事件。

relay_log_recovery = 1
#relay_log_recovery用于决定在从服务器启动时是否自动从最后一个完整的事务处恢复中继日志的执行。
#当设置为1时,从服务器在启动时如果检测到中继日志中有未完成的事务,它会尝试从最后一个完成的事务
#开始继续执行,以保证数据的一致性和完整性。

修改完毕之后重新启动服务:systemctl restart mysqld

3.2 连接主服务器

通过执行SQL语句

cs 复制代码
master_host='192.168.83.20'
#指定主服务器的IP地址或主机名,这里设置为主服务器的IP地址192.168.83.20。

master_user='myslave'
#设置主服务器上用于复制的用户账号名称,这里使用的是名为'myslave'的账户。

master_password='123456'
#提供主服务器上的复制用户对应的密码,此处仅为示例,实际环境中请使用安全强度更高的密码。

master_log_file='master-bin.000001'
#指定主服务器上从哪里开始复制二进制日志,这里的值'master-bin.000001'是主服务器的一个具
#体的二进制日志文件名。

master_log_pos=603
#与master_log_file配合使用,指定从主服务器二进制日志文件的哪个位置开始读取和执行事件,
#这里的值603代表从该文件的第603个字节位置开始。

查看状态时需要确认 IO 和 SQL 线程都是 Yes,代表同步正常

Slave_IO_Running: Yes #负责与主机的I/O通信
Slave_SQL_Running: Yes #负责自己的slave mysql进程

另一台从服务器同样操作

slave2配置

主从复制服务已经配置完毕,在主服务器上进行SQL语句的操作,那么从服务器上就会通过获取二进制日志文件同步操作

二、读写分离

读写分离策略主要解决的是在高并发的情况下,解决数据库面临的读写压力

(一)读写分离的概念

1.基本概念

读写分离是数据库架构优化的一种常用手段,其核心思想是将数据库的读操作和写操作分离开,通过多个数据库节点分摊压力。在MySQL中,通常会有一个主数据库(Master)负责处理所有写入请求,多个从数据库(Slave)负责处理读取请求。

主从复制:MySQL的读写分离依赖于其内置的主从复制机制。主数据库执行的写操作将通过二进制日志同步到从数据库,确保数据的一致性。

负载均衡:通过负载均衡器将应用程序的读请求分发到各个从数据库,从而减轻主数据库的压力,提高整体的读取性能

2.读写分离的作用

首先要了解为什么要进行读写分离。

在工作环境中对数据库的操作,往往查询操作要远远多于增、删、改。写数据的操作往往要比查询更加耗费资源,影响查询的效率,所以需要进行读写分离

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

(二)实现读写分离的方式

1.基于数据库层面

MySQL主从复制 :主数据库负责处理写操作,并通过二进制日志将变更同步到从数据库,从数据库负责处理读操作。可以配置多个从库以实现读负载均衡。Oracle RAC与DG:Oracle数据库提供了Real Application Clusters (RAC) 和Data Guard两种技术实现读写分离,前者通过集群实现读写共享,后者通过数据同步实现读写分离。

2.中间件代理方式

MySQL Proxy:作为一个轻量级的MySQL中间件,可以根据SQL语句类型自动路由到主库或从库。

MyCat、ShardingSphere:这些数据库中间件支持读写分离和分库分表等功能,可以灵活地将读请求分发到多个从库。

Amoeba :由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。

3.程序代码层面

自定义数据库连接池 :在应用程序中,根据SQL语句类型(读/写)使用不同的数据库连接池,读操作连接到从库,写操作连接到主库。ORM框架支持:一些ORM框架(如Hibernate、MyBatis等)提供了读写分离的支持,开发者可以通过配置轻松实现读写分离。

4.云服务提供商集成方案

AWS Aurora阿里云RDS等云数据库服务通常提供内置的读写分离功能,只需简单配置即可启用。

5.负载均衡器

软件负载均衡器(如HAProxy、Nginx等)可以配合MySQL主从复制实现读写分离,通过配置规则将读请求转发到从库群组,写请求始终发送到主库。

(三)实现读写分离

使用中间代理层实现读写分离

由于使用MySQL Proxy 需要写大量的Lua脚本,这些Lua并不是现成的,而是需要自己去写。这对于并不熟悉MySQL Proxy 内置变量和MySQL Protocol 的人来说是非常困难的。

Amoeba是一个非常容易使用、可移植性非常强的软件。因此它在生产环境中被广泛应用于数据库的代理层

环境准备

|---------------|--------------------|
| MASTER服务器 | 192.168.83.20 |
| SLAVE1服务器 | 192.168.83.40 |
| SLAVE2服务器 | 192.168.83.60 |
| Amoeba服务器 | 192.168.83.100 |
| 客户端 | 192.168.83.50 |

1.基于主从复制

首先部署好主从复制环境,这是实现读写分离的基础

读写分离可以使用一主一从实现,但是读写分离的作用主要就是缓解读的压力,所以一般从服务器都在两台及以上

2.部署Amoeba服务器

因为 Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用

2.1 安装jdk
cs 复制代码
[root@zqsl opt]#ls
jdk-6u14-linux-x64.bin
#准备好安装脚本
[root@zqsl opt]#cp jdk-6u14-linux-x64.bin /usr/local/
[root@zqsl opt]#cd /usr/local/
[root@zqsl local]#chmod +x jdk-6u14-linux-x64.bin
[root@zqsl local]#./jdk-6u14-linux-x64.bin    #执行该文件进行安装
#按回车到yes/no选择界面,输入yes进行安装,而后继续回车
[root@zqsl local]#ls
bin  etc  games  include  jdk1.6.0_14  jdk-6u14-linux-x64.bin  lib  lib64  libexec  sbin  share  src
#生成jdk1.6.0_14目录文件

也可以进行基于tar包的二进制安装

2.2 安装Amoeba
cs 复制代码
[root@zqsl opt]#ls
amoeba-mysql-binary-2.2.0.tar.gz  jdk-6u14-linux-x64.bin
[root@zqsl opt]#mkdir /usr/local/amoeba
#创建安装目录
[root@zqsl opt]#tar xf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
#将amoeba的tar包解压到安装目录
[root@zqsl opt]#ls /usr/local/
amoeba  bin  etc  games  include  jdk1.6  jdk-6u14-linux-x64.bin  lib  lib64  libexec  sbin  share  src
[root@zqsl opt]#chmod -R 755 /usr/local/amoeba/
#设置权限
[root@zqsl opt]#/usr/local/amoeba/bin/amoeba
amoeba start|stop
#绝对路径执行amoeba命令,显示amoeba start|stop说明安装成功
2.3 配置Amoeba读写分离

首先在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问

修改amoeba配置文件

修改amoeba.xml文件

首先是第30行与32行的用户与密码

cs 复制代码
<property name="defaultPool">master</property>:
#这一行设置了默认的数据库连接池为"master"。这意味着,除非明确指定读写类型,否则所有的
#数据库操作(读写)都会通过连接到名为"master"的数据库进行。

<property name="writePool">master</property>:
#这一配置指定了所有的写操作。应当通过名为"master"的数据库连接池进行。

<property name="readPool">slaves</property>:
#这一行则定义了所有的读操作应当通过名为"slaves"的数据库连接池进行。
#这里的"slaves"可能是指一组从库,即读操作会通过负载均衡的方式分散到多个从库上,
#以此提高读取性能和系统吞吐量。

修改dbServers.xml文件

cs 复制代码
dbServer标签定义了三个数据库服务器,分别是master、slave1和slave2,它们都继承
自abstractServer配置。

master服务器的数据库IP地址为192.168.83.20 #通常用于处理写入操作。

slave1服务器的数据库IP地址为192.168.83.40。
slave2服务器的数据库IP地址为192.168.83.60,
#它们通常用于处理读取操作,以实现读写分离和负载均衡。



定义了一个虚拟的数据库服务器slaves,它实际上不是一个真实的数据库服务器,
而是代表了前面定义的slave1和slave2两个从服务器。

<property name="loadbalance">1</property> 表示负载均衡策略为轮询(ROUNDROBIN)。
<property name="poolNames">slave1,slave2</property> 
指定了组成slaves虚拟服务器的实体从服务器列表,即读操作将在这两个从服务器之间进行轮询分配。

启用之后重新打开一个终端,查看是否开启成功

监听本机的8066端口,同时连接主从服务器的3306端口

3.客户端进行测试

MySQL客户端使用amoeba用户登录MySQL数据库

mysql -u amoeba #指定amoeba.xml文件31行定义的用户

-p :amoeba.xml文件定义的密码

-h:amoeba服务器地址

-P:连接端口

通过amoeba服务器代理访问mysql ,在通过客户端连接mysql后写入的数据只有主服务会记录,然后同步给从--从服务器

测试轮询

测试开启后自动同步

总结

主从复制与读写分离是MySQL服务当中重要的调优部分,会增加读写性能与抗高并发。

不过需要注意的是

1.在修改配置文件时,注意文件的备份,很多新手小白在修改配置文件时,没有备份,配置文件修改错误之后,无法恢复

2.使用主从复制时,从服务器的MySQL版本一定要高于主服务器的版本,因为高版本可以向下兼容,若主版本高于从版本,可能无法兼容,导致同步失败

3.不论是读写分离还是主从复制,都会有一定因素影响它们正常运行,比如网络延迟、错误的SQL语句,导致某一台从服务器掉线,防火墙与核心防护是否开启,都可能导致运行出现错误,需要有一定经验去排查错误

相关推荐
苏-言几秒前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring
Ljw...7 分钟前
索引(MySQL)
数据库·mysql·索引
菠萝咕噜肉i20 分钟前
超详细:Redis分布式锁
数据库·redis·分布式·缓存·分布式锁
长风清留扬23 分钟前
一篇文章了解何为 “大数据治理“ 理论与实践
大数据·数据库·面试·数据治理
OpsEye36 分钟前
MySQL 8.0.40版本自动升级异常的预警提示
数据库·mysql·数据库升级
Ljw...36 分钟前
表的增删改查(MySQL)
数据库·后端·mysql·表的增删查改
远歌已逝4 小时前
维护在线重做日志(二)
数据库·oracle
qq_433099405 小时前
Ubuntu20.04从零安装IsaacSim/IsaacLab
数据库
Dlwyz5 小时前
redis-击穿、穿透、雪崩
数据库·redis·缓存
工业甲酰苯胺7 小时前
Redis性能优化的18招
数据库·redis·性能优化