对于MySql的一些梳理之架构篇

时间:2024-03-16 20:06:04

MySQL的主从同步(复制)


复制是将主数据库的 DDL 和 DML 操作通过二进制日志传到复制服务器 (也叫从库上),然后在从库上对这些日志重新执行 (也叫重做),从而使得从库和主库的数据保持同步。MySQL支持一台主库同时向多台从库进行复制,从库同时也可以作为其他服务器的主库,实现链状的复制

MySQL 复制的优点主要包括以下三个方面:

  1. 如果主库出现问题,可以快速切换到从库提供服务 (提升性能)
  2. 可以在从库上执行查询操作,降低主库的访问压力 (读写分离,主库写,从库读,降压)
  3. 可以在从库上执行备份,以避免备份期间影响主库的服务 (确保数据安全)

MySQL支持哪些复制:

  1. 基于语句的复制:在主服务器上执行的sql语句,在从服务器上执行同样的语句。mysql默认采用基于语句的复制,效率比较高,一旦发现没法精确复制时,会自动选择基于行的复制
  2. 基于行的复制:把改变的内容复制过去,而不是命令在从服务器上执行一遍,从mysql 5.0 开始支持
  3. 混合类型的复制:默认采用基于语句的复制,一旦发现基于语句的无法精确复制时,就会采用基于行的复制

下面是整个复制过程的原理图:

对于MySql的一些梳理之架构篇

主从复制需要三个线程,Master(binlog dump thread)、Slave(I/O thread、SQL thread
原理大致如下:

  1. 首先,MySQL主库在事务提交时会把数据变更作为事件Events记录在二进制日志文件Binlog中;MySQL主库上的sync_binlog参数控制Binlog日志刷新到磁盘
  2. 主库推送二进制日志文件Binlog中的事件到从库的中继日志Relay Log,之后从库根据中继日志Relay Log重做数据变更操作,通过逻辑复制以此来达到主库和从库的数据一致

MySQL通过3个线程来完成主从库间的数据复制:其中Binlog Dump线程跑在主库上,I/O线程和SQL线程跑在从库上。当在从库上启动复制(START SLAVE)时,首先创建I/O线程连接主库,主库随后创建Binlog Dump线程读取数据库事件并发送给I/O线程,I/O线程获取到事件数据后更新到从库的中继日志Relay Log中取,之后从库上的SQL线程读取中继日志Relay Log中更新的数据库事件并应用

复制中的各类文件

从复制流程涉及了两类非常重要的日志文件:二进制日志文件(Binlog)和中继日志文件(Relay Log)
二进制日志文件(Binlog)会把MySQL中的所有数据修改操作以二进制的形式记录到日志文件中,包括Create、Drop、Insert、Update、Delete操作等,但二进制日志文件(Binlog)不会记录Select操作,因为Select操作并不需修改数据

Binlog支持Statement、Row、Mixed三种格式,也对应了MySQL的3种复制技术。中继日志文件Relay Log的文件格式、内容和二进制日志文件Binlog一样,唯一的区别在于从库上的SQL线程在执行完当前中继日志文件Relay Log中的事件之后,SQL线程会自动删除当前中继日志文件Relay Log,避免从库上的中继日志文件Relay Log占用过多的磁盘空间

为了保证从库Crash重启之后,从库的I/O线程和SQL线程仍然能够知道从哪里开始复制,从库上默认还会创建两个日志文件master.inforelay-log.info用来保存复制的进度。这两个文件在磁盘上以文件形式分别记录了从库的I/O线程当前读取主库二进制日志Binlog的进度和SQL线程应用中继日志Relay Log的进度。

其中master.info记录的是I/O线程连接主库的一些参数,主要包括 SHOW SLAVE STATUS,下面列出较重要的5项

  • Master Host:主库的IP
  • Master User:主库上,主从复制使用的用户账号
  • Master Port:主库MySQL的端口号
  • Master_Log_File:从库的I/O线程当前正在读取的主库Binlog的文件名
  • Read_Master_Log_Pos:从库I/O线程当前读取到的位置

而 relay-log.info 记录的是SQL线程应用中继日志Relay Log的一些参数,主要包括以下重要的4项

  • Relay_Log_File:从库SQL线程正在读取和应用的中继日志Relay Log的文件名
  • Relay_Log_Pos:从库SQL线程当前读取并应用的中继日志Relay Log的位置
  • Relay_Master_Log_File:从库SQL线程正在读取和应用的Relay Log对应于主库Binlog的文件名
  • Exec_Master_Log_Pos:中继日志Relay Log中Relay_Log_Pos位置对应于主库Binlog的位置

复制的3种常见架构

一主多从复制架构
对于MySql的一些梳理之架构篇

在主库读取请求压力非常大的情况下,可以通过配置一主多从复制架构实现读写分离,把大量对实时性要求不是特别高的读请求通过负载均衡分布到多个从库上,降低主库的读取压力。在主库出现异常宕机的情况下,可以把一个从库切换为主库继续提供服务

多级复制架构

对于MySql的一些梳理之架构篇

一主多从的架构能够解决大部分读请求压力特别大的场景的需求,考虑到MySQL的复制是主库"推送"Binlog日志到从库,主库的I/O压力和网络压力会随着从库的增加而增长(每个从库都会在主库上有一个独立的Binlog Dump线程来发送事件),而多级复制架构解决了一主多从场景下,主库额外的I/O和网络压力。对比一主多从,它仅仅是在中间增加了一个二级主库Master2,这样主库Master1只需要给一个从库Master2推送Binlog日志即可,减轻主库的推送压力。二级主库再“推送”Binlog日志给从库。多级复制解决了一主多从场景下,主库的I/O负载和网络压力,缺点是:M有SQL的复制是异步复制,多级复制场景下主库的数据是经历两次复制才到达从库,期间的延时比一主多从复制场景下只经历一次复制的要大。Master2并不承担读写请求,仅仅负责将Binlog日志尽快传送给从库

双主复制/Dual Master架构(略)

两种复制方式:

异步复制:MySQL主从异步复制是最常见和最简单的复制场景,复制的3个线程Binlog Dump、I/O、SQL之间都是独立的,相互之间没有依赖关系。数据的完整性完全依赖于主库的Binlog的不丢失,只要主库的Binlog不丢失,那么就算主库宕机了,还以可以通过Binlog把丢失的部分数据通过手工同步到从库上。

半同步复制:MySQL 5.5之前,MySQL的复制是异步操作,主库和从库的数据之间存在一定的延迟,这样存在一个隐患:当在主库上写入一个事务并提交成功,而从库尚未得到主库推送的Binlog日志时,主库宕机了,例如主库可能因为磁盘损坏、内存故障等造成主库上该事务Binlog丢失,此时从库可能损失这个事务,从而造成主从不一致。
为了解决这个问题,5.5后引入了半同步复制机制,为了保证主库上的每一个Binlog事务都能够被可靠的复制到从库上,主库在每次事务成功提交时,并不及时反馈给前端应用用户,而是等待其中一个从库也接收到Binlog事务并成功写入中继日志后,主库才返回Commit操作成功给客户端。半同步复制保证了事务成功提交后,至少有两份日志记录,一份在主库的Binlog日志上,另一份在至少一个从库的中继日志Relay Log上,从而更进一步保证了数据的完整性


MySQL主从同步延迟问题

MySQL的主从复制都是单线程的操作,主库对所有DDL和DML产生的日志写进binlog,由于binlog是顺序写,所以效率很高。Slave的SQL Thread线程将主库的DDL和DML操作事件在slave中重放。DML和DDL的IO操作是随即的,不是顺序的,成本高很多。另一方面,由于SQL Thread也是单线程的,当主库的并发较高时,产生的DML数量超过slave的SQL Thread所能处理的速度,或者当slave中有大型query语句产生了锁等待那么延时就产生了。

常见原因:Master负载过高、Slave负载过高、网络延迟、机器性能太低、MySQL配置不合理。

MySql数据库从库同步的延迟解决方案

1)、架构方面

1.业务的持久化层的实现采用分库架构,mysql服务可平行扩展,分散压力。

2.单个库读写分离,一主多从,主写从读,分散压力。这样从库压力比主库高,保护主库。

3.服务的基础架构在业务和mysql之间加入memcache或者redis的cache层。降低mysql的读压力。

4.不同业务的mysql物理上放在不同机器,分散压力。

5.使用比主库更好的硬件设备作为slave总结,mysql压力小,延迟自然会变小。

2)、硬件方面

1.采用好服务器,比如4u比2u性能明显好,2u比1u性能明显好。

2.存储用ssd或者盘阵或者san,提升随机写的性能。

3.主从间保证处在同一个交换机下面,并且是万兆环境。

总结,硬件强劲,延迟自然会变小。一句话,缩小延迟的解决方案就是花钱和花时间。

 

参考:
深入浅出 MySQL 人民邮电出版社 唐汉明等人
https://blog.csdn.net/hao_yunfeng/article/details/82392261