MySQL-26:备库并行复制

如果备库执行日志的速度持续低于主库生成日志的速度,那这个延迟就有可能成了小时级别。 而且对于一个压力持续比较高的主库来说,备库很可能永远都追不上主库的节奏。

那么备库并行复制能力就是关键了。

img

谈到主备的并行复制能力,我们要关注的是图中黑色的两个箭头。一个箭头代表了客户端写入主库,另一箭头代表的是备库上 sql_thread 执行中转日志(relay log)。

在主库上,影响并发度的原因就是各种锁了。由于 InnoDB 引擎支持行锁,除了所有并发事务都在更新同一行(热点行)这种极端场景外,它对业务并发度的支持还是很友好的。

而日志在备库上的执行,就是图中备库上 sql_thread 更新数据 (DATA) 的逻辑。如果是用单线程的话,就会导致备库应用日志不够快,造成主备延迟。

在官方的 5.6 版本之前,MySQL 只支持单线程复制,由此在主库并发高、TPS 高时就会出现严重的主备延迟问题。

其实说到底,所有的多线程复制机制,都是要把图 1 中只有一个线程的 sql_thread,拆成多个线程,也就是都符合下面的这个模型:

img

图 2 中,coordinator 就是原来的 sql_thread, 不过现在它不再直接更新数据了,只负责读取中转日志和分发事务。真正更新日志的,变成了 worker 线程。而 work 线程的个数,就是由参数slave_parallel_workers 决定的 。

接下来,我们就思考如下几个问题:

  1. 事务能不能按照轮询的方式分发给各个worker?
  2. 同一个事务的多个更新语句,能不能分配给不同的worker来执行?

所以,coordinator 在分发的时候,需要满足以下这两个基本要求:

  1. 不能造成更新覆盖。这就要求更新同一行的两个事务,必须被分发到同一个 worker 中。
  2. 同一个事务不能被拆开,必须放到同一个 worker 中。
26.1 MySQL 5.6 版本的并行复制策略

官方 MySQL5.6 版本,支持了并行复制,只是支持的粒度是按库并行。

img

在每个 worker 线程对应一个 hash 表,用于保存当前正在这个 worker 的“执行队列”里的事务所涉及的库。hash 表的 key 是“库名”,value 是一个数字,表示队列中有多少个事务修改这个库。

当一个事务进来的时候,根据上面的的分发规则将事务加入到worker的hash表中,如果存在一个以上的表冲突,则coordinator会暂时挂起,worker会将hash表中的事务一个一个消费掉。

这里的实现原理感觉是线程池加队列的方式。

这个策略的并行效果取决于压力模型,如果库上的多个BD的压力比较平均,则效果会很好,如果不同BD之间热点不同,那效果不佳,可以还会恢复到类似单线程模式的状态。

26.2 MariaDB 的并行复制策略

MariaDB 的并行复制策略利用redo log 组提交 (group commit) 优化特性:

  1. 能够在同一组里提交的事务,一定不会修改同一行;
  2. 主库上可以并行执行的事务,备库上也一定是可以并行执行的。

MariaDB 的实行:

  1. 在一组里面一起提交的事务,有一个相同的 commit_id,下一组就是 commit_id+1;
  2. commit_id 直接写到 binlog 里面;
  3. 传到备库应用的时候,相同 commit_id 的事务分发到多个 worker 执行;
  4. 这一组全部执行完成后,coordinator 再去取下一批。

但,这个策略有个问题就是 在备库上执行的时候,要等第一组事务完全执行完成后,第二组事务才能开始执行,这样系统的吞吐量就不够,而且很容易地被大事务拖后腿,一个大事务的等待提交就会造成资源的浪费。

26.3 MySQL 5.7 的并行复制策略

在 MariaDB 并行复制实现之后,官方的 MySQL5.7 版本也提供了类似的功能,由参数 slave-parallel-type 来控制并行复制策略:

  1. 配置为 DATABASE,表示使用 MySQL 5.6 版本的按库并行策略;
  2. 配置为 LOGICAL_CLOCK,表示的就是类似 MariaDB 的策略。不过,MySQL 5.7 这个策略,针对并行度做了优化。这个优化的思路也很有趣儿。

MySQL 5.7 并行复制策略的思想是:

  1. 同时处于 prepare 状态的事务,在备库执行时是可以并行的;
  2. 处于 prepare 状态的事务,与处于 commit 状态的事务之间,在备库执行时也是可以并行的。

binlog 的组提交涉及的两个参数:

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

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

这两个参数是用于故意拉长 binlog 从 write 到 fsync 的时间,以此减少 binlog 的写盘次数。在 MySQL 5.7 的并行复制策略里,它们可以用来制造更多的“同时处于 prepare 阶段的事务”。这样就增加了备库复制的并行度。

26.2 MySQL 5.7.22 的并行复制策略

MySQL 5.7.22 版本里增加了一个新的并行复制策略,基于 WRITESET 的并行复制,同时也新增了一个参数 binlog-transaction-dependency-tracking,用来控制是否启用这个新策略。这个参数的可选值有以下三种:

  1. COMMIT_ORDER,表示的就是前面介绍的,根据同时进入 prepare 和 commit 来判断是否可以并行的策略。
  2. WRITESET,表示的是对于事务涉及更新的每一行,计算出这一行的 hash 值,组成集合 writeset。如果两个事务没有操作相同的行,也就是说它们的 writeset 没有交集,就可以并行。
  3. WRITESET_SESSION,是在 WRITESET 的基础上多了一个约束,即在主库上同一个线程先后执行的两个事务,在备库执行的时候,要保证相同的先后顺序。

hash 值是通过“库名 + 表名 + 索引名 + 值”计算出来的,看来它就是按行分配调度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值