一招教你解决mysql的主从复制延迟问题

https://baijiahao.baidu.com/s?id=1716187911729308342&wfr=spider&for=pc

双主双从的mysql集群搭建,在单机应用的时候看起来没有问题,但是在企业的生产环境中,在很多情况下都会有复制延迟的问题 。主从复制的原理我们在此处就不再赘述了,这是一个老生常谈的问题,原理性质的也几乎在面试中问烂了,这些原理性质的东西并不是很难,但是你需要注意了,主从复制的延迟问题会成为一个难点,能非常全面的考验同学们的技术实力。

一、首先我们应该如何查看同步延迟状态?

在从服务器上通过 show slave status 查看具体的参数,有几个参数比较重要:

master_log_file: slave中的IO线程正在读取的主服务器二进制日志文件的名称,read_master_log_pos: 在当前的主服务器二进制日志中,slave中的IO线程已经读取的位置, relay_log_file: sql线程当前正在读取和执行的中继日志文件的名称

relay_log_pos: 在当前的中继日志中,sql线程已经读取和执行的位置

relay_master_log_file: 由sql线程执行的包含多数近期事件的主服务器二进制日志文件的名称

slave_io_running: IO线程是否被启动并成功地连接到主服务器上

slave_sql_running: sql线程是否被启动,seconds_behind_master: 从属服务器sql线程和从属服务器IO线程之间的事件差距,单位以秒计

在观察同步延迟的时候,上述的几个参数都是比较重要的,其中有一个最最重要的参数需要同学们引起注意,那就是seconds_behind_master,这个参数就表示当前备库延迟了多长时间,那么这个值是如何计算的呢?

在进行主从复制的时候,需要注意以下几个关键的时刻:

1、主库A执行完成一个事务,写入binlog,我们把这个时刻记为T1;

2、之后传给备库B,我们把备库B接受完这个binlog的时刻记为T2;

3、备库B执行完成这个事务,我们把这个时刻记为T3;

所谓的主备延迟就是同一个事务,在备库执行完成的时间和主库执行完成的时间之间的差值,也就是T3-T1。SBM在进行计算的时候也是按照这样的方式,每个事务的binlog中都有一个时间字段,用于记录主库写入的时间,备库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值,得到SBM。

如果刚刚的流程听明白了,那么下面我们就要开始分析产生这个时间差值的原因有哪些了,以方便我们更好解决生产环境中存在的问题。

二、主从复制延迟产生的原因有哪些?

1、在某些部署环境中,备库所在的机器性能要比主库所在的机器性能差。此时如果机器的资源不足的话就会影响备库同步的效率;

2、备库充当了读库,一般情况下主要写的压力在于主库,那么备库会提供一部分读的压力,而如果备库的查询压力过大的话,备库的查询消耗了大量的CPU资源,那么必不可少的就会影响同步的速度

3、大事务执行,如果主库的一个事务执行了10分钟,而binlog的写入必须要等待事务完成之后,才会传入备库,那么此时在开始执行的时候就已经延迟了10分钟了

正在上传…重新上传取消

4、主库的写操作是顺序写binlog,从库单线程去主库顺序读binlog,从库取到binlog之后在本地执行。mysql的主从复制都是单线程的操作,但是由于主库是顺序写,所以效率很高,而从库也是顺序读取主库的日志,此时的效率也是比较高的,但是当数据拉取回来之后变成了随机的操作,而不是顺序的,所以此时成本会提高。

5、 从库在同步数据的同时,可能跟其他查询的线程发生锁抢占的情况,此时也会发生延时。

6、 当主库的TPS并发非常高的时候,产生的DDL数量超过了一个线程所能承受的范围的时候,那么也可能带来延迟

7、 在进行binlog日志传输的时候,如果网络带宽也不是很好,那么网络延迟也可能造成数据同步延迟,这些就是可能会造成备库延迟的原因

主从复制简介

在实际的生产中,为了解决Mysql的单点故障已经提高MySQL的整体服务性能,一般都会采用「主从复制」

比如:在复杂的业务系统中,有一句sql执行后导致锁表,并且这条sql的的执行时间有比较长,那么此sql执行的期间导致服务不可用,这样就会严重影响用户的体验度。

主从复制中分为「主服务器(master)「和」从服务器(slave)」「主服务器负责写,而从服务器负责读」,Mysql的主从复制的过程是一个「异步的过程」

这样读写分离的过程能够是整体的服务性能提高,即使写操作时间比较长,也不影响读操作的进行。

三、如何解决复制延迟的问题

先说一些虚的东西,什么叫虚的东西呢?就是一听上去感觉很有道理,但是在实施或者实际的业务场景中可能难度很大或者很难实现,下面我们从几个方面来进行描述:

1、架构方面

①、业务的持久化层的实现采用分库架构,让不同的业务请求分散到不同的数据库服务上,分散单台机器的压力

②、服务的基础架构在业务和mysql之间加入缓存层,减少mysql的读的压力,但是需要注意的是,如果数据经常要发生修改,那么这种设计是不合理的,因为需要频繁地去更新缓存中的数据,保持数据的一致性,导致缓存的命中率很低,所以此时就要慎用缓存了

③、使用更好的硬件设备,比如cpu,ssd等,但是这种方案一般对于公司而言不太能接受,原因也很简单,会增加公司的成本,而一般公司其实都很抠门,所以意义也不大,但是你要知道这也是解决问题的一个方法,只不过你需要评估的是投入产出比而已。

2、从库配置方面

1、修改sync_binlog的参数的值

想要合理设置此参数的值必须要清楚地知道binlog的写盘的流程:

正在上传…重新上传取消

可以看到,每个线程有自己的binlog cache,但是共用同一份binlog。

图中的write,指的就是把日志写入到文件系统的page cache,并没有把数据持久化到磁盘,所以速度快

图中的fsync,才是将数据持久化到磁盘的操作。一般情况下,我们认为fsync才占用磁盘的IOPS

而write和fsync的时机就是由参数sync_binlog来进行控制的。

1、当sync_binlog=0的时候,表示每次提交事务都只write,不fsync

2、当sync_binlog=1的时候,表示每次提交事务都执行fsync

3、当sync_binlog=N的时候,表示每次提交事务都write,但积累N个事务后才fsync。

一般在公司的大部分应用场景中,我们建议将此参数的值设置为1,因为这样的话能够保证数据的安全性,但是如果出现主从复制的延迟问题,可以考虑将此值设置为100~1000中的某个数值,非常不建议设置为0,因为设置为0的时候没有办法控制丢失日志的数据量,但是如果是对安全性要求比较高的业务系统,这个参数产生的意义就不是那么大了。

2、直接禁用salve上的binlog,当从库的数据在做同步的时候,有可能从库的binlog也会进行记录,此时的话肯定也会消耗io的资源,因此可以考虑将其关闭,但是需要注意,如果你搭建的集群是级联的模式的话,那么此时的binlog也会发送到另外一台从库里方便进行数据同步,此时的话,这个配置项也不会起到太大的作用。

3、设置innodb_flush_log_at_trx_commit 属性,这个属性在我讲日志的时候讲过,用来表示每一次的事务提交是否需要把日志都写入磁盘,这是很浪费时间的,一共有三个属性值,分别是0(每次写到服务缓存,一秒钟刷写一次),1(每次事务提交都刷写一次磁盘),2(每次写到os缓存,一秒钟刷写一次),一般情况下我们推荐设置成2,这样就算mysql的服务宕机了,卸载os缓存中的数据也会进行持久化。

三 总结

slave延迟的原因可以归结为slave apply binlog的速度跟不上主库写入的速度,如何解决复制延迟呢?其实也是如何提高MySQL写速度的问题。从目前的硬件和软件的发展来看,硬件存储由之前的HDD机械硬盘发展到现在的SSD,PCI-E SSD,再到NVM Express(NVMe),IO性能一直在提升。MySQL的主从复制也从单线程复制到不同算法的并行复制(基于库,事务,行),应用binlog的速度也越来越快。
本文归纳从几个常见的复制延迟场景,有可能还不完整,也欢迎大家留言讨论

举报/反馈

发表评论

发表

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值