暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL并行复制技术进化史

数据库技术汇 2021-04-25
1301

原创文章,转载请注明出处!

本文的目的


MySQL并行复制技术的进化过程中,提供给我们很多思考,比如并行的粒度、区分可并发Task的技术手段等。希望这些手段也可以用于我们其它系统的设计中。

 

背景


MySQL的复制是典型的Master/Slave模式的架构,或者叫做主/备模式复制。而Slave上的并行回放效率一直是MySQL官方和很多公司头疼的问题。因为一般情况下Master库上是多线程并行执行多个事务,Binlog传输到Slave上之后,并行回放这些事务的速度通常都会打折,打折的关键原因是回放要考虑的问题(一致性、性能和故障恢复准确性等)比较多,这个在文章后面部分来讲。先看一下MySQL并行复制技术的进化史:



1. 串行回放阶段


在MySQL 5.6.2及之前的版本,Slave只有一条SQL线程,无论Master库上的并发有多大,Slave库都是串行回放Binlog。这个阶段,出现了一些工程方案,比如在Slave上进行Relay Log Prefetch(http://yoshinorimatsunobu.blogspot.jp/2011/10/making-slave-pre-fetching-work-better.html)。简单理解就是:为了提高Slave回放过程中Cache的命中率,通过将Binlog中的SQL语句转换成对应的Select语句,将回放所需的数据页预先加载到Buffer Pool中。另外在这个阶段也出现了解析Binlog,将Binlog以多线程的方式写入到Slave库的工具,比如Transfer(https://yq.aliyun.com/articles/8646)。这些工具解决了燃眉之急,只是在数据一致性、维护等方面带来了额外的复杂度,如果对MySQL不够熟练的公司,产生中稳定应用还是有一定的门槛。

2. Database Based并行回放阶段


在MySQL 5.6.3之后的版本,支持多个SQL线程并行回放事务,并行的粒度是Database级别。这个改进的具体思路可以参考:https://dev.mysql.com/worklog/task/?id=5569 也很容易想到,如果你的数据库设计是单库多表方式,那么这个技术不但没有收益,反倒会降低性能,因为协调线程协调了半天,发现最终还得串行回放事务,协调也是要有开销的。当然,上面提到的那些工具和方法也适用这个阶段。

 

仔细看,你会发现按库并行的机制有一个假设前提:没有跨库的事务,或者跨库事务的乱序提交不会对数据(应用)造成恶劣影响。比如数据架构设计的过程中就规避了这种情况的发生,或者Slave干脆仅仅是Backup而不提供Read。

 

3. Commit Parent Based并行回放阶段


在MySQL 5.7.2之后的版本,Slave上提供了一种新的并行回放技术: LOGICAL_CLOCK。据说相比Database级别的并行算法,性能提到了40%。但是很明显,性能这个问题,不同场景不同环境依赖性太强,除非你自己去做业务压测,不要听这些鬼话。这个改进的具体思路可以参考:https://dev.mysql.com/worklog/task/?id=6314。虽然名字叫LOGICAL_CLOCK,简单理解就是:如果一批事务(不一定要同时)进入Prepare阶段时看到的“上一个提交事务”是同一个事务,那么这个“上一个提交事务”的编号(commit_clock)就会被写进这些事务的Binlog中。在Slave回放的过程中,这些事务是可以并行执行的,注意是执行不是提交!注意是执行不是提交!注意是执行不是提交!至于是不是并行提交,这个涉及另外一个话题,我们在后面再说。

 

所以仔细看,这个并行回放的机制,其实和Binlog Group Commit没有啥关系,Binlog Group Commit仅仅是来解决Master上频繁fsync代价太高的问题,把多个fsync合并成一个fsync,对吗?。在MariaDB的实现中,并行回放的机制和Binlog Group Commit是强相关的,具体实现思路可以参考:https://jira.mariadb.org/browse/MDEV-4506。MariaDB中在Binlog Group Commit的时候将一个64位的group commit id写入到Binlog中,group commit id在这个Group提交完成后递增。其次,MariaDB中还有domain_id的概念,不同的domain_id之间是可以并行回放的。从技术层面来讲,我认为MySQL和MariaDB在解决并行回放这个问题上没有谁好谁坏,哪种更好和Master上事务实际提交的情况有关。

 

4. Preserve Commit Order并行回放阶段


在MySQL 5.7.5之后的版本,Slave在保持LOGICAL_CLOCK并行回放的基础上,提供了一个选项:来保障Slave上事务的提交顺序和Master上是完全一致的。具体实现思路可以参考:https://dev.mysql.com/worklog/task/?id=6813。 这就是前面提到的Slave上回放Binlog其实包含两个步骤:执行和提交,并行执行和提交顺序是两码事!MariaDB上也有类似的选项,具体可以参考:https://mariadb.com/kb/en/mariadb/parallel-replication/ 中的slave_parallel_mode参数解释。


https://dev.mysql.com/doc/refman/5.7/en/replication-options-slave.html

Once a multi-threaded slave has been started, transactions can begin to execute in parallel. With slave_preserve_commit_order enabled, the executing thread waits until all previous transactions are committed before committing. While the slave thread is waiting for other workers to commit their transactions it reports its status as Waiting for preceding transaction to commit. (Prior to MySQL 5.7.8, this was shown as Waiting for its turn to commit.) Enabling this mode on a multi-threaded slave ensures that it never enters a state that the master was not in. This makes it well suited to using replication for read scale-out. See Section 18.3.4, “Using Replication for Scale-Out”.

 

现在回到我想强调的一个观点:如果你要保证Slave上的提交顺序和Master完全一致,只能通过Slave内部逻辑来控制!想通过外面程序来多线程灌,不管你按Binlog Group Commit还是LOGICAL_CLOCK,行不通!行不通!行不通!如果期望这个方法提供“最终一致性”,那我们且来看看“最终一致性”的定义和细分。这其中的坑,可以参考:

http://geek.rohitkalhans.com/2013/09/enhancedMTS-deepdive.html

http://mysqlhighavailability.com/preserve-masters-commit-order-on-slave/


5. Lock Interval Based并行回放阶段


在MySQL 5.7.6之后的版本,LOGICAL_CLOCK的实现发生了比较大的变化,改进的方向就是努力让更多事务可以并行回放,具体的实现思路可以参考:https://dev.mysql.com/worklog/task/?id=7165。核心变化可以通过下面的例子来说明:



如上图所示,P代表在事务Prepare阶段记录全局commit parent的时间点,C代表在存储引擎提交前对全局commit parent进行递增的时间点。按照原有的LOGICAL_CLOCK算法,只有Trx5和Trx6可以并行执行,但是Trx4和Trx5是无法并行执行的,Trx6和Trx7也是无法并行执行的。但如果两个事务可以在同一时间点同时获得各自的锁,说明这两个事务在Master上是没有冲突的,因此这两个事务在Slave上并行执行也没有问题。

 

在上面的例子中:

  • Trx4,Trx5和Trx6同时获得各自的锁,但是Trx4不能和Trx5和Trx6并行执行

  • Trx6和Trx7也是类似的情况

 

新的算法:如果两个事务可以在同一时间点获得各自的锁,那么这两个事务就可以并行执行。具体代码细节这里不深入,用两个图来简单说明新算法的核心逻辑:



L表示加锁区间的开始时间点,C表示加锁区间的结束时间点。如上图所示,左边图中的两个事务可以并行执行,右图中的两个事务不能并行执行。


文章转载自数据库技术汇,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论