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日志传输的时候,如果网络带宽也不是很好,那么网络延迟也可能造成数据同步延迟

以上这些就是可能会造成备库延迟的原因。

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

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

1、架构方面

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

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

3)、使用更好的硬件设备,比如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缓存中的数据也会进行持久化。

 这些都是从系统层面解决延时问题,解决的程度很有限,下一篇我们分享从根本上解决复制延时的问题,敬请期待!

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寅灯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值