目录
一、MySQL主从复制概述
1.MySQL主从复制的概念
2.MySQL主从复制工作原理
2.1MySQL主从复制中的日志与线程
2.2MySQL的复制类型
3.MySQL主从复制延迟的原因及解决方法
4.MySQL的同步方式
4.1异步复制
4.2同步复制
4.3半同步复制
4.4增强半同步复制
4.5总结
二、部署MySQL主从复制
1. MySQL主从服务器时间同步
2.主服务器配置
3.两个从服务器配置
4.验证主从复制
三、MySQL读写分离概述
1.MySQL读写分离的概念
2.MySQL读写分离工作原理
四、MySQL读写分离搭建
1. Amoeba服务器配置
2.测试读写分离
一、MySQL主从复制概述
1.MySQL主从复制的概念
MySQL主从复制是实现数据库高可用性和负载均衡的重要技术。它允许将主数据库(Master)的数据实时复制到一个或多个从数据库(Slave),从而使得读取操作可以在从数据库上进行,而写入操作仍然在主数据库上进行
2.MySQL主从复制工作原理
MySQL主从复制的工作原理的详细步骤:
1. 主服务器的准备
启用二进制日志:主服务器需要启用二进制日志(Binary Log),这是记录所有数据修改操作的日志文件
配置服务器 ID:主服务器需要设置一个唯一的服务器 ID,以便在复制过程中识别不同的服务器
创建复制用户:在主服务器上创建一个专门用于复制的用户,并赋予必要的权限(如REPLICATION SLAVE)2. 从服务器的准备
配置服务器 ID:每个从服务器也需要设置一个唯一的服务器 ID,以避免与主服务器冲突
连接主服务器:从服务器需要配置连接主服务器的信息,包括主服务器的地址、复制用户及其密码3. 复制过程(重点)
(1) 事务提交与日志记录
更新操作:
在主服务器上,当客户端执行数据更新操作(如INSERT、UPDATE、DELETE)时,这些操作会在事务完成之前被记录到二进制日志中事务提交:
一旦二进制日志记录成功,主服务器通知存储引擎提交事务。这确保了主服务器的二进制日志中有对应的操作记录,即使主服务器崩溃也能恢复到一致状态(2) 从服务器获取日志
I/O 线程启动:
从服务器启动一个I/O线程,与主服务器建立连接,启动Binlog dump process(日志传输过程)读取二进制日志:
I/O线程从主服务器的二进制日志中读取事件并将其写入到从服务器的中继日志(Relay Log)中
如果I/O线程跟上了主服务器的最新事件,它会进入休眠状态,等待主服务器生成新的事件(3) 重放中继日志
SQL线程处理:
从服务器的SQL线程从中继日志中读取事件,并按顺序执行这些操作以更新从服务器的数据
该过程确保从服务器的数据与主服务器的数据保持一致4. 同步与一致性
串行处理:
从服务器上的复制过程是串行化的。这意味着,在从服务器上应用的操作必须按照主服务器的执行顺序进行,确保数据的一致性延迟处理:
由于I/O线程和SQL线程的不同处理机制,从服务器可能会出现数据延迟,具体表现为从服务器的数据与主服务器之间的不同步5. 监控与管理
状态监控:
管理员可以使用命令如 `SHOW SLAVE STATUS;` 来检查从服务器的复制状态,包括复制延迟和错误信息
故障处理:
在主服务器故障时,从服务器可以迅速提升为主服务器,确保业务的连续性
2.1MySQL主从复制中的日志与线程
在MySQL的主从复制中,两日志和三线程是关键概念,它们确保了数据的高效同步和一致性。以下是对这两个概念的详细解释:
两日志
1. 二进制日志(Binary Log)
定义:二进制日志是主服务器上记录所有修改数据库操作的日志文件。它记录了所有对数据库的写入操作,如INSERT、UPDATE和DELETE
工作流程:
当主服务器上的事务更新数据时,在事务提交之前,会将所有变更记录到二进制日志中
只有在成功写入二进制日志后,主服务器才会通知存储引擎提交事务。这样做确保了即使在主服务器崩溃的情况下,仍然能够恢复最近的变更2. 中继日志(Relay Log)
定义:中继日志是从服务器上存储的日志文件,用于保存从主服务器接收到的二进制日志事件
工作流程:
从服务器的I/O线程会从主服务器的二进制日志中读取事件,并将这些事件写入自己的中继日志
中继日志是从服务器更新其数据副本的基础,确保从服务器的数据与主服务器保持一致三线程
1. I/O线程(I/O Thread)
定义:从服务器上的一个工作线程,负责从主服务器读取二进制日志
工作流程:
I/O线程通过打开一个普通的连接到主服务器,启动Binlog dump process(日志传输过程)
它读取主服务器的二进制日志事件,并将这些事件写入中继日志。如果I/O线程已经跟上主服务器的最新事件,它会进入休眠状态,等待主服务器生成新的事件
2. SQL线程(SQL Thread)
定义:从服务器上的另一个工作线程,负责将中继日志中的事件应用到从服务器的数据库中
工作流程:
SQL线程从中继日志中读取事件,并重放这些事件,从而更新从服务器的数据
该线程的作用是确保从服务器的数据与主服务器保持一致。只要SQL线程与I/O线程保持同步,数据更新将是有效的3. 主服务器线程(Master Thread)
定义:在主服务器上用于处理所有数据库的操作线程,负责写入操作和更新日志
工作流程:
处理所有来自应用程序的写请求,并记录到二进制日志
确保所有数据修改的顺序,并生成供从服务器使用的日志信息复制过程的串行化限制
在MySQL的主从复制中,有一个重要的限制是:从服务器上的复制过程是串行化的。这意味着,主服务器上的并行更新操作不能在从服务器上并行处理
原因:
串行化处理确保了数据一致性,因为从服务器必须按顺序应用事件,以避免数据不一致的情况
这种串行化的特性可能导致在高并发情况下,从服务器的处理能力成为瓶颈
2.2MySQL的复制类型
1. 基于语句的复制(Statement-Based Replication, SBR)
优点
日志空间小:由于只记录SQL语句,相比行复制,二进制日志文件通常更小
易于理解:通过直接记录执行的SQL语句,可以方便地查看复制的操作缺点
不确定性:某些操作在主从服务器上执行的结果可能不一致,例如使用当前时间、UUID等函数的语句
复杂的语句:对于复杂的语句,复制可能会出现不可预见的行为,导致数据不一致适用场景
数据库操作较简单,且没有涉及复杂事务或动态生成数据的应用2. 基于行的复制(Row-Based Replication, RBR)
优点
数据一致性:能够更精确地确保数据在主从服务器间的一致性,特别是对于复杂的数据修改
避免不确定性:不会受到函数调用等影响,任何情况下都能保证从库能准确重放主库的更改缺点
日志空间大:相对于语句复制,记录的行变更信息会更占用日志空间,尤其是对于批量更新
性能开销:对于大数据量的更新操作,行复制可能会造成性能开销适用场景
数据修改频繁、复杂的事务或需要高度一致性的环境3. 混合类型的复制(Mixed-Based Replication, MBR)
优点
灵活性:可以根据具体的SQL语句和执行情况选择最合适的复制方式,从而在保证数据一致性的同时,减少日志空间的使用
性能优化:在适合的场景下,能够提升性能并减少数据不一致的风险缺点
复杂性:混合复制的逻辑更复杂,管理和调试可能会更加困难
兼容性问题:在不同版本或配置的MySQL中,混合复制可能会面临一些兼容性问题适用场景
需要同时兼顾性能和一致性的复杂应用场景,特别是在大多数操作为简单的情况下
3.MySQL主从复制延迟的原因及解决方法
主从复制延迟的原因
1. 主服务器高并发事务
描述:在高并发情况下,主服务器会生成大量的事务。这些事务会迅速写入二进制日志,但从服务器可能无法跟上写入的速度,导致延迟
影响:事务量过大可能使得从服务器的I/O线程无法及时读取和处理更新,造成数据同步延迟2. 网络延迟
描述:主服务器和从服务器之间的网络延迟会直接影响数据传输的速度
影响:如果网络连接不稳定或带宽不足,I/O线程从主服务器读取二进制日志的速度会受到影响,从而引起复制延迟3. 硬件性能瓶颈
CPU性能:
处理器的主频和核心数决定了从服务器处理事务的能力
内存I/O:
内存的大小和速度影响了数据的缓存和读写效率
硬盘I/O:
硬盘的读写速度,尤其是使用机械硬盘时,可能成为性能瓶颈
影响:低性能的硬件可能无法快速处理从主服务器传来的数据,导致延迟4. 复制方式
描述:MySQL的复制方式主要是异步复制。这意味着主服务器在完成写入后并不会等待从服务器的确认
影响:这种机制虽然提高了写入性能,但在从服务器处理较慢时,数据一致性和延迟问题更为明显解决方法
1.从库优化MySQL参数
①增大 `innodb_buffer_pool_size`
通过增加InnoDB缓冲池的大小,可以在内存中处理更多的操作,减少磁盘I/O,从而提高性能
②调整其他MySQL参数
可以根据工作负载调整其他参数,如连接数、查询缓存等,以提高整体性能2.硬件优化
①使用高性能主机
配备强悍的CPU和足够的内存,确保从库能快速处理请求
避免使用虚拟云主机,选择物理主机可以减少虚拟化带来的额外开销②使用SSD磁盘
SSD的读写速度远高于传统机械硬盘,能显著提高I/O性能,减少延迟3.网络优化
①避免跨机房同步
选择在同一机房内部署主从服务器,以降低网络延迟
确保网络带宽充足且稳定4.同步方式
①半同步复制
描述:在半同步复制模式下,主服务器在提交事务后会等待至少一个从服务器的确认,确保数据不会因为主服务器崩溃而丢失
优点:能够提高数据安全性,降低数据丢失风险②并行复制
描述:通过启用并行复制,可以让多个事务同时被从服务器处理,从而提高从库的复制性能
优点:有效减少从库的复制延迟,特别是在主服务器有大量事务生成时5.数据分片与读写分离
分片:将数据分散到多个从服务器上,减少每个从服务器的负担
读写分离:将读操作分散到从服务器上,从而减少主服务器的负担,改善整体性能
4.MySQL的同步方式
4.1异步复制
特点
工作原理:主库在将更新写入二进制日志(Binlog)后,不需要等待从库确认即可继续处理后续请求。主库将事件写入Binlog,但并不知道从库是否或何时接收了这些事件优点
性能优越:由于主库无需等待,从而能够快速处理更多请求,提供了最佳的写入性能。缺点
数据安全风险:如果主库宕机,已提交的事务可能未能传送到从库,导致数据丢失。例如,在主从故障转移时,从库可能会丢失事务适用场景
对性能要求极高且对数据一致性要求不那么严格的应用场景,例如某些缓存层或数据分析场景
4.2同步复制
特点
工作原理:主库在写入Binlog后,需要等待从库成功接收到数据并执行完毕后,才会返回继续处理其他请求优点
数据安全性高:确保数据在从库中得到确认后,才会继续处理其他请求,避免了数据丢失的风险。缺点
性能影响:由于需要等待,从库的处理速度直接影响到主库的响应时间,可能导致性能下降适用场景
对数据一致性和安全性要求极高的场景,如金融交易系统、银行系统等
4.3半同步复制
特点
工作原理:主库在提交更新并写入Binlog后,等待至少一个从库的中继日志(Relay Log)接收到这些数据,然后才能继续处理其他请求。这种方式确保至少有一个从库成功接收到数据优点
折中方案:提供了在性能与数据安全性之间的良好平衡。比异步复制更安全,但比同步复制更高效缺点
依赖从库的响应:如果从库未能及时响应,主库可能会转换为异步复制模式,导致潜在的数据丢失风险适用场景
对数据一致性和性能都有要求的应用场景,尤其是在对部分数据丢失敏感的情况下
4.4增强半同步复制
特点
工作原理:在MySQL 5.7中引入,增强半同步复制将等待ACK的点放在提交(Commit)之前。这意味着数据在提交之前不会对外可见,从而避免了主从切换时可能出现的数据不一致问题优点
数据一致性更高:由于在Commit之前等待ACK,确保在发生主从切换时,从库能够保持老数据,避免用户看到不一致的状态缺点
可能增加延迟:在等待ACK的过程中,可能会造成响应延迟,影响性能适用场景
需要保证在主从切换过程中数据一致性的应用场景
4.5总结
复制方式 | 性能 | 数据安全性 | 适用场景 |
异步复制 | 最优 | 低 | 性能要求高,数据一致性要求低的场景 |
同步复制 | 低 | 高 | 数据一致性和安全性要求极高的场景 |
半同步复制 | 中等 | 中等 | 数据一致性和性能要求都有的场景 |
增强半同步复制 | 中等 | 更高 | 需要避免主从切换中数据不一致的场景 |
二、部署MySQL主从复制
主机名 | IP | 需要安装的服务 |
Master | 172.16.58.10 | MySQL、ntp |
Slave01 | 172.16.58.20 | MySQL、ntpdate |
Slave02 | 172.16.58.30 | MySQL、ntpdate |
1. MySQL主从服务器时间同步
初始化环境
关闭防火墙以及增强功能
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
主服务器设置
安装ntp、修改配置文件
yum install ntp -y
vim /etc/ntp.conf
--末尾添加--
server 127.127.10.0 #设置本地是时钟源,注意修改网段
fudge 127.127.10.0 stratum 8 #设置时间层级为8(限制在15内)
启动服务
service ntpd start
两个从服务器设置
安装ntp、ntpdate服务
yum install ntp ntpdate -y
启动服务
service ntpd start
时间同步
/usr/sbin/ntpdate 172.16.58.10
创建计划任务
crontab -e
*/30 * * * * /usr/sbin/ntpdate 172.16.58.10
2.主服务器配置
安装数据库(可参考下面博客)
https://blog.csdn.net/2201_75444658/article/details/142323843?fromshare=blogdetail&sharetype=blogdetail&sharerId=142323843&sharerefer=PC&sharesource=2201_75444658&sharefrom=from_link编辑MySQL配置文件
vim /etc/my.cnf
server-id = 1
log-bin=master-bin #添加,主服务器开启二进制日志
binlog_format = MIXED
log-slave-updates=true #添加,允许slave从master复制数据时可以写入到自己的二进制日志重启数据库
systemctl restart mysqld登录数据库
mysql -u root -p 123给2个从服务器赋权
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'172.16.58.%' IDENTIFIED BY '123';
刷新权限
FLUSH PRIVILEGES;显示状态参数
show master status; #记录日志名和偏移量
3.两个从服务器配置
安装数据库(可参考下面博客)
https://blog.csdn.net/2201_75444658/article/details/142323843?fromshare=blogdetail&sharetype=blogdetail&sharerId=142323843&sharerefer=PC&sharesource=2201_75444658&sharefrom=from_link编辑MySQL配置文件
vim /etc/my.cnf
server-id = 2\3(2个slaveid) #修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin #添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index #添加,定义中继日志文件的位置和名称,一般和relay-log在同一目录
relay_log_recovery = 1 #选配项#当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 relay-log,并且重新从 master 上获取日志,这样就保证了relay-log 的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启。重启数据库
systemctl restart mysqld登录数据库
mysql -u root -p 123配置同步,注意 master_log_file 和 master_log_pos 的值要与Master查询的一致
CHANGE master to master_host='172.16.58.10',master_user='myslave',master_password='123',master_log_file='master-bin.000001',master_log_pos=603;启动同步,如有报错执行 reset slave
start slave;
查看 Slave 状态
show slave status\G
确保 IO 和 SQL 线程都是 Yes,代表同步正常
Slave_IO_Running: Yes #负责与主机的io通信
Slave_SQL_Running: Yes #负责自己的slave mysql进程
4.验证主从复制
主服务器上进入执行
create database db_test;
去从服务器上查看
show databases;
三、MySQL读写分离概述
1.MySQL读写分离的概念
读写分离是一种数据库架构设计模式,其基本原理是将数据库的写操作(例如INSERT、UPDATE、DELETE)集中在主数据库上,而将所有的读操作(SELECT查询)分配给一个或多个从数据库。这种方式通过数据库复制机制,将主数据库上的数据变化同步到从数据库中,从而实现数据的一致性
2.MySQL读写分离工作原理
MySQL读写分离工作原理的详细说明:
1. 数据库架构
主数据库(Master):负责所有的写操作,包括插入、更新和删除(INSERT、UPDATE、DELETE)
从数据库(Slave):负责所有的读操作(SELECT),并且通过数据复制与主数据库保持同步2. 数据复制
主从复制:主数据库的所有数据变化(写操作)会被记录在二进制日志(binlog)中。这些日志记录了所有的更改操作
同步机制:从数据库会定期从主数据库读取binlog并应用这些变化,以保持数据的一致性3. 读写分离的实现过程
1. 写操作:
所有写请求都发送到主数据库。主数据库处理这些请求并更新数据。
写操作完成后,主数据库会将操作记录到binlog中,随后从数据库会通过binlog进行数据更新2. 读操作:
应用程序将读请求发送到从数据库
从数据库执行查询操作,返回结果给应用程序4. 数据一致性问题
由于主从复制是异步的,写操作在主数据库完成后,数据变化可能需要一定时间才能同步到从数据库。在这一过程中,读请求可能会得到旧的数据版本,因此需要注意数据的一致性5. 负载均衡
在实际应用中,通常会配置多个从数据库来分担读请求的压力。可以通过负载均衡策略将读请求分发到不同的从数据库,提升整体性能6. 实现方式
应用层实现:在应用程序的代码中,根据操作类型(读或写)将请求路由到相应的数据库。这种方式灵活,但需要开发人员编写代码实现
中间件实现:使用中间件(如MySQL-Proxy、ProxySQL、Atlas等)在客户端和数据库之间进行请求转发。中间件会自动识别请求类型并转发到合适的数据库,减少了应用代码的复杂性
四、MySQL读写分离搭建
主机名 | IP | 需要安装的服务 |
Master | 172.16.58.10 | MySQL、ntp |
Slave01 | 172.16.58.20 | MySQL、ntpdate |
Slave02 | 172.16.58.30 | MySQL、ntpdate |
Amoeba | 172.16.58.40 | MySQL、jdk1.6、Amoeba |
1. Amoeba服务器配置
初始化环境
关闭防火墙以及增强功能
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
安装Java环境
因为 Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用
cd /opt
cp jdk-6u14-linux-x64.bin /usr/local/
cd /usr/local/
chmod +x jdk-6u14-linux-x64
./jdk-6u14-linux-x64.bin
//按yes,按entermv jdk1.6.0_14/ /usr/local/jdk1.6编辑配置文件
vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/binsource /etc/profile
java -version
安装 Amoeba软件
创建存放目录
mkdir /usr/local/amoeba
tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
chmod -R 755 /usr/local/amoeba/
/usr/local/amoeba/bin/amoeba
//如显示amoeba start|stop说明安装成功
在Master、Slave01、Slave02的数据库上给Amoeba赋权
grant all on *.* to test@'172.16.58.%' identified by '123';
配置Amoeba服务
cd /usr/local/amoeba/conf/cp amoeba.xml amoeba.xml.bak
vim amoeba.xml
30行
<property name="user">amoeba</property>
32行
<property name="password">123456</property>
115行
<property name="defaultPool">master</property>
117行去掉注释
<property name="writePool">master</property>
<property name="readPool">slaves</property>
修改数据库配置文件
cp dbServers.xml dbServers.xml.bak
vim dbServers.xml
23行注释掉 作用:默认进入test库 以防mysql中没有test库时,会报错
<!-- <property name="schema">test</property> -->
26修改
<property name="user">test</property>
28-30去掉注释
<property name="password">123456</property>
45修改,设置主服务器的名Master
<dbServer name="master" parent="abstractServer">
48修改,设置主服务器的地址
<property name="ipAddress">192.168.10.15</property>
52修改,设置从服务器的名slave1
<dbServer name="slave1" parent="abstractServer">
55修改,设置从服务器1的地址
<property name="ipAddress">192.168.10.14</property>
58复制上面6行粘贴,设置从服务器2的名slave2和地址
<dbServer name="slave2" parent="abstractServer">
<property name="ipAddress">192.168.10.16</property>
65行修改
<dbServer name="slaves" virtual="true">
71行修改
<property name="poolNames">slave1,slave2</property>/usr/local/amoeba/bin/amoeba start& #启动Amoeba软件,按ctrl+c 返回
netstat -anpt | grep java #查看8066端口是否开启,默认端口为TCP 8066
2.测试读写分离
先安装数据库
yum install -y mariadb-server mariadb
systemctl start mariadb.service在客户端服务器上测试
mysql -u amoeba -p123 -h 172.16.58.40 -P8066
通过amoeba服务器代理访问mysql ,在通过客户端连接mysql后写入的数据只有主服务会记录,然后同步
给从服务器在主服务器上:
use db_test;
create table test (id int(10),name varchar(10),address varchar(20));在两台从服务器上:
stop slave; #关闭同步
use db_test;
在slave01上:
insert into test values('1','zhangsan','this_is_slave1');
在slave02上:
insert into test values('2','lisi','this_is_slave2');
在主服务器上:
insert into test values('3','wangwu','this_is_master');
在客户端服务器上:
use db_test;
select * from test;
客户端会分别向slave01和slave02读取数据,显示的只有在两个从服务器
上添加的数据,没有在主服务器上添加的数据insert into test values('4','qianqi','this_is_client'); //只有主服务器上有此数据
在两个从服务器上执行 start slave; 即可实现同步在主服务器上添加的数据
start slave;