Mysql系列之多线程复制(5)

文章目录

  • 多线程复制
    • 前提条件
    • 按表分发策略
    • 按行分发策略
    • 按库分发策略
    • 模拟主库并行模式策略
    • Mysql 5.7
    • 基于WRITESET的并行复制

多线程复制

将sql_thread拆分为coordinator和多个worker

  • coordinator只负责读取中转日志和分发事务
  • worker线程负责更新日志,worker个数由slave
    _parallel_workers设定,这个值设置为8~16之间最好(32核物理机的情况)

多线程,为了保证一致性,分发事务需要满足以下基本要求:

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

前提条件

  1. 要能够从binlog里面解析出表名、主键值和唯一索引的值。也就是说,主库的binlog格式必须是row;
  2. 表必须有主键;
  3. 不能有外键。表上如果有外键,级联更新的行不会记录在binlog中,这样冲突检测就不准确。

按表分发策略

如果两个事务更新不同的表,它们就可以并行。因为数据是存储在表里的,所以按表分发,可以保证两个worker不会更新同一行。

设计思路
Mysql系列之多线程复制(5)_第1张图片

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

事务分发时:

  1. 如果都不冲突,则分配给最空闲的worker
  2. 如果有多个冲突,需要等待
  3. 只有一个冲突时,分配给冲突的worker

在多个表负载均衡时很有效,但是对于热点表会基本变成单线程复制

按行分发策略

按行复制的核心思路是:如果两个事务没有更新相同的行,它们在备库上可以并行执行。这个模式要求binlog格式必须是row。

  • 此时判断一个事务T和worker是否冲突,用的就规则就不是“修改同一个表”,而是“修改同一行”
  • 按行复制也是为每个worker,分配一个hash表。只是要实现按行分发,这时候的key,就必须是“库名+表名+唯一键的值”。有时候除了主键,还需要考虑唯一索引
  • 此种方案分发时需要更多资源;1.耗费内存。比如一个语句要删除100万行数据,这时候hash表就要记录100万个项 2.耗费CPU。解析binlog,然后计算hash值,对于大事务,成本还是很高。

按库分发策略

也是为每个worker,分配一个hash表。实现按库分发,这时候的key就是数据库名。

  • 如果主库多个db负载均衡,则效果很好
  • 优势在于:1.构建hash值很快,只需要库名,同时由于库数量不多,key项也不会很多。2.不要求binlog的格式。因为statement格式的binlog也可以很容易拿到库名

模拟主库并行模式策略

利用了redo log组提交的特性(MariaDB的策略)

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

实现思路

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

注意
1.事务在备库上执行的时候,不能完全与主库一样并行,要等第一组事务完全执行完成后,第二组事务才能开始执行,系统的吞吐量不够
2.大事务影响较大,会变成单线程

Mysql 5.7

slave_parallel_type来控制并行复制策略:
1.配置为DATABASE,表示使用MySQL 5.6版本的按库并行策略
2. 配置为LOGICAL_CLOCK,表示的就是类似MariaDB的策略并针对并行度做了优化:处于所有执行中的状态不能并行,所有处于redo log prepare状态的事务可以并行(此时已经通过了锁冲突检测)

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

基于WRITESET的并行复制

MySQL5.7.22 增加了一个新的并行复制策略,基于WRITESET的并行复制。
新增了一个参数binlog-transaction-dependencytracking,用来控制是否启用这个新策略。这个参数的可选值有以下三种。

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

后面两种相当于按行分发策略,但是优势在于:

  1. writeset是在主库生成后直接写入到binlog里面的,这样在备库执行的时候,不需要解析binlog内容
    (event里的行数据),节省了很多计算量; 不需要把整个事务的binlog都扫一遍才能决定分发到哪个worker,更省内存;
    由于备库的分发策略不依赖于binlog内容,所以binlog是statement格式也是可以的。因此,MySQL
    5.7.22的并行复制策略在通用性上还是有保证的

当然,对于“表上没主键”和“外键约束”的场景,WRITESET策略也是没法并行的,也会暂时退化为单线程模型。

你可能感兴趣的:(Mysql,mysql,数据库)