MySql 主从复制延迟

主从复制原理

我们先来看下主从复制的原理:
在这里插入图片描述
当Master有数据改动之后,会将数据写入自己的bin log文件,Slave上会有一个I/O thread 线程,拉取Master的bin log文件,写入自己的Relay log(中继日志),再由Slave上的SQL thread来读取解析加载Relay log中的数据

延迟原因

我们按照上面原理图来分析下主从复制同步延迟耗时的原因:

  1. 从Master写入bin log 耗时
  2. Slave的I/O thread拉取Master bin log的网络耗时
  3. I/O thread写入Relay log的磁盘等待耗时
  4. SQL thread读取解析处理Relay log的耗时

具体到实际应用场景,还有哪些可能会造成同步延时呢:

  • Slave的机器性能比Master的性能差很多,导致数据的产生和数据的消费速度相差很大,机器性能不足会影响Slave的同步效率
  • Salve充当读库,一般情况下主要写的压力在主库,Salve会分摊一部分读的压力,但是如果Slave查询的压力过大,会消耗大量Salve的系统资源(cpu,磁盘I/O等),会影响数据同步
  • 大事务执行,如果Master一个事务执行了5分钟,那bin log必须等事务执行完成之后,才会传入Slave,此时已经延迟了5分钟。
  • Master是顺序写入bin log,Slave单线程去Master顺序读取bin log,Slave读取到bin log之后再本地执行。MySql的主从复制都是单线程操作,由于Master是顺序写,所以效率会很高。Slave也是顺序读取bin log,此时效率也会很高,但是数据拉取之后执行就变成了随机操作,此时的成本会很高。
    对应于上面的步骤1,2,3,这些都是顺序写和顺序读,一般耗时会很低,执行的效率很高。但是对于步骤4,由于是随机操作,效率会很低。

解释一下为什么步骤4是随机操作:比如现在对orderid=1和orderid=100的记录进行更新。Master写入bin log的顺序是orderid=1,orderid=100,直接向后append就可以了,Salve读取也是这个顺序,但是在实际执行更新数据时,可能就需要先去磁盘A扇区去更新orderid=1,然后再去磁盘B扇区更新orderid=100,完全是随机操作,效率会很低。

  • Slave同步的同时,可能跟其他查询线程发送锁竞争,也会发生锁等待而耗时
  • 当Master的QPS并发非常高的时候,产生的DDL数量超过一个线程所能承受的范围时,也可能会带来延迟
  • 在bin log日志传输时,如果网络宽带不是很好,由于网络延迟也可能造成数据同步延迟

数据一致性

我们先抛开其他外部因素,单从同步上来讲,最直接影响同步效率的便是第4步Slave解析执行sql的步骤,如果是单线程进行执行,由于是随机操作,效率得不到保障。如果换成多线程来执行会是什么情况呢?
这里面就会涉及到数据一致性问题了。

假设Master的SQL执行顺序是A->B ,先将一个数据列改成的10,如何再改成5。
假设现在Salve采用多线程方式进行解析执行,一个线程执行SQL A,一个线程执行SQL B。可能的结果是B先执行完,再执行A,最终的结果是先将数据改成5,再修改为10,这样同步完成后,Slave的数据与Master数据时不一致的。

所以,同步时,Master如何执行,Slave也必须如何执行,必须有顺序保障。

组提交

综上,为了解决同步延迟问题,主要就是解决第4步随机问题。单线程执行必然是不合适的,多线程情况下需要解决数据一致性问题。所以在执行同步时,Slave执行的至少是以一个事务的维度进行操作,通过事务的方式,保证执行顺序和结果,与Master保持一致。当有多个事务一同提交、执行,这便就是组提交了。

将事务按组进行提交,此时就可以并发执行同步了,但是需要主要,一个组的事务不能相互干扰,需要是相互独立。

查看同步延迟

使用“show slave status”查看具体参数,有几个参数比较重要:
master_log_file:slave中的IO线程正读取的Master服务器二进制日志文件名称
read_master_log_pos:在当前Master服务器二进制日志中,slave中IO线程已经读取的位置
relay_log_file:sql线程当前正在读取和执行的中继文件的名称
relay_log_pos:在当前的中继日志中,sql线程已经读取和执行的位置
relay_master_log_file:由sql线程执行的包换多数近期事件的Master主服务器二进制日志文件名称
slave_io_runnig:IO线程是否被启动且成功连接到Master
slave_sql_running:sql线程是否被启动
seconds_behind_master:slave的sql线程和slave的IO线程之间的时间差距,以秒记

必须slave_io_runnig和slave_sql_running都是yes的时候,才能开始进行主从同步。seconds_behind_master这个参数就表示当前slave和master同步延迟了多长时间,那么这个时间是怎么计算出来的呢?

我们来看下几个关键的时间点:

  1. Master执行完事务,写入binlog,此时这个时刻为T1
  2. 将binlog传给slave,slave接收完这个binlog的时刻记为T2
  3. slave执行事务完毕,这个时刻记为T3

所谓的主从同步延迟,就是同一个事务,在slave完成时间和master执行完的时间差值,也就是T3 - T1。seconds_behind_master在计算时也是按照这个方式,每个事务的binlog中都有一个时间字段,用于记录Master写入时间,slave取当前正在执行的事务时间,计算她和当前系统时间的差值,从而计算出seconds_behind_master。

解决延迟问题

  1. 采用分库架构,让不同业务分散到不同的数据库服务器上,减轻单台机器的压力
  2. 升级硬件,主频更高的cpu,更快的ssd等,提升服务器的性能,使用专线进行网络通信等
  3. 修改配置:
    我们先理清楚binlog写入磁盘的流程:
    在这里插入图片描述
    每一个事务从开始执行到最后的提交,在内存中都会有自己的binlog cache,但是所有事务共同持有一份binlog ,事务commit完成之后,将各自的binlog数据append进binlog file,最后再由操作系统写入磁盘

在这里插入图片描述
所以MySql的刷盘流程,是先将每个事务的binlog 写入os buffer,也就是将日志写入文件系统的page cache,此时数据并没有持久化到磁盘,纯内存操作,速度非常快。
然后是fsync操作,从os buffer将数据持久化到磁盘。一般情况下,我们可以认为只有fsync操作才会占用磁盘的IOPS。

所以,如果我们一次积攒足够多的数据,然后统一提交一次fsync,相较于一有数据就执行fsync,效率会高出很多。

图中的write和fsync的写入时机,是由参数sync_binlog来控制的:

  • 当sync_binlog=0,表示每次提交事务都只write,不fsync,等os buffer满了之后再自动进行fsync
  • 当sync_binlog=1,表示每次事务提交都执行fsync
  • 当sync_binlog=n,表示每次事务提交都write,但是在积累n个事务之后才fsnyc
    在公司的一般实际应用中,这个参数会设置为1,这样能够保证数据的安全性。但是如果出现主从复制延迟问题,需要考虑将此值设置为n(需要按照实际业务量做配置),非常不建议设置为0,因为设置为0时,没有办法控制什么时候fsnyc到磁盘,在极端情况下,可能会造成很严重的数据丢失,比如积攒了1w条事务commit,此时os buffer还没有满,突然断电了,这些数据还没来得及fsnyc进磁盘,数据就丢失了,无法同步。设置为n时也会有数据丢失问题,但是相对来讲会可控一些。

如果slave机器后面没有再接slave机器,可以考虑禁用slave上的binlog。当slave在做数据同步的时候,slave上的binlog也会进行记录,这样也是会消耗IO资源的。


设置innodb_flush_log_at_trx_commit属性
在前面的章节中,我们有讲过,在innodb存储引擎中,redo log 和binlog共同组成了两阶段提交,是MySql支持事务的基础。innodb_flush_log_at_trx_commit这个属性用来表示每一次的事务提交是否需要将redo log写入磁盘,一共有三个值:
0:存储在当前线程缓存中(log buffer),每一秒由 InnoDB 的主线程执行一次刷盘
1:每一次事务提交都刷盘
2:每次事务提交都写到os buffer,每一秒执行一次刷盘

如果为了保证数据安全性,一般情况下建议数据库配置双1,即rodo log和binlog 都每一次提交都写入磁盘,数据安全性最高,但是由于每一次都会fsync刷盘,占用磁盘的IOPS,可能会影响到同步的效率,导致延迟变高。

对数据同步要求较高时,binlog配置为n,redo log配置为2(此时极端情况下会有1秒的数据丢失),这样可以在延迟和数据安全性上找到较好的平衡点。

  1. 不使用主从复制
    并不是所有场景都适合使用主从复制,一般情况下,是读的场景要远多于写的场景,同时对读的数据时效性要求没那么高。如果实际业务中,当Master更新一笔数据之后,要立即从slave中读出,并且要求数据是最新更新后的,这种场景不适合主从复制,应该强制读取Master,完全避免同步延时是不可能的。
  2. 并行复制(MTS)
    在这里插入图片描述
    MySql 5.6版本开始引入了MTS,也就是并行复制。原来是单线程sql thread执行中继日志的数据同步,现在是由coordinator(协调器)负责读取日志信息以及事务分发,真正的日志执行由worker线程执行,多个线程并行。

“set global slave_parallel_workers=n” ,可以用设置有多少个worker并发执行,一般n可以设置为cpu的核心数。

加入我们设置为4,“show processlist”查看当前的运行列表 :
在这里插入图片描述
我们可以看到当前已经有了4个worker在等待coordinator分配任务。

现在问题来了,这4个worker如何保证同步完的slave和Master的数据一致性呢?
假设现在有2个事务,事务A将数列更新为10,事务B将数据列更新为5。Master执行顺序是A->B,同步时 coordinator将事务A,B分别分派给两个worker,worker1执行A,worker2执行B,由于是并发执行,worker2先完成,worker1后完成,那最终同步结果是先将数据列更新为5,再更新为10。此时问题来了,Master的结果是5,slave同步后结果是10,数据产生不一致。

同步时,我们可以按照库的维度同步,也可以按照表的维护同步,也可以按照行的维度同步,coordinator是怎么分配的呢?默认是一个worker处理一个库,可以通过设置属性的方式调整worker的工作粒度,“set global slave_parallel_type=‘logical_check’ ”,设置为按照行维护同步。

由上面的例子,我们可以得出coordinator在分配任务时,必须遵循下面两个原则:

  • 更新同一行数据的不同事物,必须由一个worker执行
  • 一个事务里面的所有动作,都必须由一个worker执行,不可拆开来由多个worker分别执行

MySql 5.7的MTS基于组提交实现
在这里插入图片描述
我们来看下事务的提交过程,1.redo log prepare阶段,将数据写入内存,2.将binlog写入内存 ,3.redo log prepare阶段,将内存中的数据刷盘,4.binlog进行刷盘,5.redo log commit阶段,更新事务的状态。
在这些事务的执行过程中,1,3,5 ; 2,4每个执行都是时间差,每个时间差之间,可以有n多个事务同时执行。

当Master同时有大量事务并发执行时,我们可以按照事务的执行阶段,对他们进行分组。
事务执行时,可以分为prepare阶段和commit阶段,将事务分组之后,每个组的redo log和bin log在prepare阶段和commit阶段,都是彼此独立的,此时可以按照组的维护分发给多个worker,实现在slave上的并发执行。具体如何实现分组,后续章节介绍。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
MySQL主从复制异常是指在MySQL数据库的主从复制过程中出现了错误或异常情况。主从复制是一种常用的数据库复制技术,通过将主数据库的更新操作同步到从数据库,实现数据的备份和读写分离。 常见的MySQL主从复制异常包括以下几种情况: 1. 主从延迟:主从延迟是指从数据库相对于主数据库存在一定的数据同步延迟。可能的原因包括网络延迟、主库负载过高、从库性能不足等。可以通过优化网络环境、增加从库资源、调整主从同步参数等方式来解决延迟问题。 2. 主从数据不一致:主从数据不一致是指主数据库和从数据库之间的数据出现了不一致的情况。可能的原因包括网络丢包、主库故障、从库故障等。可以通过检查主从同步状态、修复数据不一致的表、重新搭建主从复制等方式来解决数据不一致问题。 3. 主从同步中断:主从同步中断是指主数据库和从数据库之间的同步过程被中断。可能的原因包括网络中断、主库宕机、从库宕机等。可以通过检查主从同步状态、重新启动主从复制、修复宕机的数据库等方式来解决同步中断问题。 4. 主从切换异常:主从切换是指将从数据库切换为主数据库的过程。在切换过程中可能出现数据丢失、数据不一致等异常情况。可以通过备份数据、确保主从同步正常、进行灾备演练等方式来避免主从切换异常。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值