一篇文带你彻底解决mysql的主从复制延迟问题,javajvm调优面试

– 查看并行的slave的线程的个数,默认是0.表示单线程

show global variables like ‘slave_parallel_workers’;

– 根据实际情况保证开启多少线程

set global slave_parallel_workers = 4;

– 设置并发复制的方式,默认是一个线程处理一个库,值为database

show global variables like ‘%slave_parallel_type%’;

– 停止slave

stop slave;

– 设置属性值

set global slave_parallel_type=‘logical_check’;

– 开启slave

start slave

– 查看线程数

show full processlist;

通过上述的配置可以完成我们说的并行复制,但是此时你需要思考几个问题

1、在并行操作的时候,可能会有并发的事务问题,我们的备库在执行的时候可以按照轮训的方式发送给各个worker吗?

答案是不行的,因为事务被分发给worker以后,不同的worker就开始独立执行了,但是,由于CPU的不同调度策略,很可能第二个事务最终比第一个事务先执行,而如果刚刚好他们修改的是同一行数据,那么因为执行顺序的问题,可能导致主备的数据不一致

2、同一个事务的多个更新语句,能不能分给不同的worker来执行呢?

答案是也不行,举个例子,一个事务更新了表t1和表t2中的各一行,如果这两条更新语句被分到不同worker的话,虽然最终的结果是主备一致的,但如果表t1执行完成的瞬间,备库上有一个查询,就会看到这个事务更新了一半的结果,破坏了事务逻辑的隔离性。

我们通过讲解上述两个问题的最主要目的是为了说明一件事,就是coordinator在进行分发的时候,需要遵循的策略是什么?

1、不能造成更新覆盖。这就要求更新同一行的两个事务,必须被分发到同一个worker中。

2、同一个事务不能被拆开,必须放到同一个worker中。

听完上面的描述,我们来说一下具体实现的原理和过程

如果让我们自己来设计的话,我们应该如何操作呢?这是一个值得思考的问题。其实如果按照实际的操作的话,我们可以按照粒度进行分类,分为按库分发,按表分发,按行分发。

其实不管按照什么方式进行分发,大家需要注意的就是在分发的时候必须要满足我们上面说的两条规则,所以当我们进行分发的时候要在每一个worker上定义一个hash表,用来保存当前这个work正在执行的事务所涉及到的表。hash表的key值按照不同的粒度需要存储不同的值:

按库分发:key值是数据库的名字,这个比较简单

按表分发:key值是库名+表名

按行分发:key值是库名+表名+唯一键

1、MySQL5.6版本的并行复制策略


其实从mysql的5.6版本开始就已经支持了并行复制,只是支持的粒度是按库并行,这也是为什么现在的版本中可以选择类型为database,其实说的就是支持按照库进行并行复制。

但是其实用过的同学应该都知道,这个策略的并行效果,取决于压力模型。如果在主库上有多个DB,并且各个DB的压力均衡,使用这个策略的效果会很好,但是如果主库的所有表都放在同一DB上,那么所有的操作都会分发给一个worker,变成单线程操作了,那么这个策略的效果就不好了,因此在实际的生产环境中,用的并不是特别多

2、mariaDB的并行复制策略


在mysql5.7的时候采用的是基于组提交的并行复制,换句话说,slave服务器的回放与主机是一致的,即主库是如何并行执行的那么slave就如何怎样进行并行回放,这点其实是参考了mariaDB的并行复制,下面我们来看下其实现原理。

mariaDB的并行复制策略利用的就是这个特性:

1、能够在同一组里提交的事务,一定不会修改同一行;

2、主库上可以并行执行的事务,备库上也一定是可以并行执行的。

在实现上,mariaDB是这么做的:

1、在一组里面一起提交的事务,有一个相同的commit_id,下一组就是commit_id+1;

2、commit_id直接写到binlog里面;

3、传到备库应用的时候,相同commit_id的事务会分发到多个worker执行;

4、这一组全部执行完成后,coordinator再去取下一批。

这是mariaDB的并行复制策略,大体上看起来是没有问题的,但是你仔细观察的话会发现他并没有实现“真正的模拟主库并发度”这个目标,在主库上,一组事务在commit的时候,下一组事务是同时处于“执行中”状态的。

我们真正想要达到的并行复制应该是如下的状态,也就是说当第一组事务提交的是,下一组事务是运行的状态,当第一组事务提交完成之后,下一组事务会立刻变成commit状态

image

但是按照mariaDB的并行复制策略,那么备库上的执行状态会变成如下所示:

image

可以看到,这张图跟上面这张图的最大区别在于,备库上执行的时候必须要等第一组事务执行完成之后,第二组事务才能开始执行,这样系统的吞吐量就不够了。而且这个方案很容易被大事务拖后腿,如果trx2是一个大事务,那么在备库应用的时候,trx1和trx3执行完成之后,就只能等trx2完全执行完成,下一组才能开始执行,这段时间,只有一个worker线程在工作,是对资源的浪费。

3、mysql5.7的并行复制策略


mysql5.7版本的时候,根据mariaDB的并行复制策略,做了相应的优化调整后,提供了自己的并行复制策略,并且可以通过参数slave-parallel-type来控制并行复制的策略:

1、当配置的值为DATABASE的时候,表示使用5.6版本的按库并行策略;

2、当配置的值为LOGICAL_CLOCK的时候,表示跟mariaDB相同的策略。

此时,大家需要思考一个问题:同时处于执行状态的所有事务,是否可以并行?

答案是不行的,因为多个执行中的事务是有可能出现锁冲突的,锁冲突之后就会产生锁等待问题。

在mariaDB中,所有处于commit状态的事务是可以并行,因为如果能commit的话就说明已经没有锁的问题,但是大家回想下,我们mysql的日志提交是两阶段提交,如下图,其实只要处于prepare状态就已经表示没有锁的问题了。

image

因此,mysql5.7的并行复制策略的思想是:

1、同时处于prepare状态的事务,在备库执行是可以并行的。

2、处于prepare状态的事务,与处于commit状态的事务之间,在备库上执行也是可以并行的。

基于这样的处理机制,我们可以将大部分的日志处于prepare状态,因此可以设置

1、binlog_group_commit_sync_delay 参数,表示延迟多少微秒后才调用 fsync;

2、binlog_group_commit_sync_no_delay_count 参数,表示累积多少次以后才调用 fsync。

5、基于GTID的主从复制问题


在我们之前讲解的主从复制实操中,每次想要复制,必须要在备机上执行对应的命令,如下所示:

change master to master_host=‘192.168.85.11’,master_user=‘root’,master_password=‘123456’,master_port=3306,master_log_file=‘master-bin.000001’,master_log_pos=154;

在此配置中我们必须要知道具体的binlog是哪个文件,同时在文件的哪个位置开始复制,正常情况下也没有问题,但是如果是一个主备主从集群,那么如果主机宕机,当从机开始工作的时候,那么备机就要同步从机的位置,此时位置可能跟主机的位置是不同的,因此在这种情况下,再去找位置就会比较麻烦,所以在5.6版本之后出来一个基于GTID的主从复制。

GTID(global transaction id)是对于一个已提交事务的编号,并且是一个全局唯一的编号。GTID实际上是由UUID+TID组成的,其中UUID是mysql实例的唯一标识,TID表示该实例上已经提交的事务数量,并且随着事务提交单调递增。这种方式保证事务在集群中有唯一的ID,强化了主备一致及故障恢复能力

1、基于GTID的搭建


1、修改mysql配置文件,添加如下配置

gtid_mode=on

enforce-gtid-consistency=true

2、重启主从的服务

3、从库执行如下命令

change master to master_host=‘192.168.85.111’,master_user=‘root’,master_password=‘123456’

,master_auto_position=1;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后总结

ActiveMQ+Kafka+RabbitMQ学习笔记PDF

image.png

  • RabbitMQ实战指南

image.png

  • 手写RocketMQ笔记

image.png

  • 手写“Kafka笔记”

image

关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦
img-76kxZK69-1711813322129)]

  • 手写RocketMQ笔记

[外链图片转存中…(img-EFvvSZEo-1711813322129)]

  • 手写“Kafka笔记”

[外链图片转存中…(img-a6BBjwvf-1711813322130)]

关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值