并发复制(Parallel Replication 系列二: Enhanced Multi-threaded Slaves

作者:沃趣科技MySQL数据库工程师  麻鹏飞


首先梳理下传统MySQL/MariaDB主备复制基本原理:

主从复制通过三个线程来完成,在master节点运行的binlog dump的线程,I/O线程和SQL线程运行在slave 节点

  • master节点的Binlog dump线程,当slave节点与master正常连接的时候,master把更新的binlog 内容推送到slave节点。
  • slave节点的I/O 线程 ,该线程通过读取master节点binlog日志名称以及偏移量信息将其拷贝到本地relay log日志文件。
  • slave节点的SQL线程,该线程读取relay log日志信息,将在master节点上提交的事务在本地回放,达到与主库数据保持一致的目的。

问题1:

Master节点的数据库实例并发跑多个线程同时提交事务,提交的事务按照逻辑的时间(数据库LSN号)顺序地写入binary log日志,,slave节点通过I/O线程写到本地的relay log日志,但是slave节点只有SQL单线程来执行relay log中的日志信息重放主库提交得事务,造成主备数据库存在延迟(lag)

思考1:

那么为了减少主备数据同步延迟时间,由于备库只有单线程补偿数据的原因而造成延迟,那么能否使slave节点同时运行多个如SQL线程一样的功能来重放在主库执行的事务?答案当然是:可以!但是我们需要解决以下问题:

1、slave本地的relay log记录的是master 的binary log日志信息,日志记录的信息按照事务的时间先后顺序记录,那么为了保证主备数据一致性,slave节点必须按照同样的顺序执行,如果顺序不一致容易造成主备库数据不一致的风险

如:

在master节点提交T1和T2事务按照以下顺序

1.  State0: x= 1, y= 1

2.  T1: { x:= Read(y);

3.          x:= x+1;

4.          Write(x);

5.          Commit; }

6.  
State1: x= 2, y= 1

7.  T2: { y:= Read(x);

8.            y:=y+1;

9.           Write(y);

10.          Commit; }

11. 
State2: x= 2, y= 3

slave节点执行T1和T2相反的顺序:

1.  State0: x= 1, y= 1

2.  T2: { y:= Read(x);

3.            y:= y+1;

4.            Write(y);

5.            Commit; }

6.  
State1: x= 1, y= 2

7.  T1: { x:= Read(y);

8.            x:=x+1;

9.            Write(x);

10.           Commit; }

11. 
State2: x= 3, y= 2

MySQL 5.6改进:

MySQL 5.6版本引入并发复制(schema级别),基于schema级别的并发复制核心思想:“不同schema下的表并发提交时的数据不会相互影响,即slave节点可以用对relay log中不同的schema各分配一个类似SQL功能的线程,来重放relay log中主库已经提交的事务,保持数据与主库一致”。可见MySQL5.6版本的并发复制,一个schema分配一个类似SQL线程的功能。

实现1:

slave节点开启并发复制(slave_parallel_workers=3)如下图,当前的slave的SQL线程为Coordinator(协调器),执行relay log日志的线程为worker(当前的SQL线程不仅起到协调器的作用,同时也可以重放relay log中主库提交的事务)

1.  +-----+-------------+-----------+------+---------+-------+--------------------------------------------------------+------------------+

2.  | Id  | User        | Host      | db   | Command | Time  | State                                                  | Info             |

3.  +-----+-------------+-----------+------+---------+-------+--------------------------------------------------------+------------------+

4.  |   1 | system user |           | NULL | Connect | 29923 | Slave has read all relay log; waiting for more updates | NULL             |

5.  |   2 | system user |           | NULL | Connect | 29923 | Waiting for an event from Coordinator                  | NULL             |

6.  |   3 | system user |           | NULL | Connect | 29923 | Waiting for an event from Coordinator                  | NULL             |

7.  |   4 | system user |           | NULL | Connect | 29923 | Waiting for an event from Coordinator                  | NULL             |

问题2:

MySQL 5.6基于schema级别的并发复制能够解决当业务数据的表放在不同的database库下,但是实际生产中往往大多数或者全部的业务数据表都放在同一个schema下,在这种场景即使slave_parallel_workers>0设置也无法并发执行relay log中记录的主库提交数据。 高并发的情况下,由于slave无法并发执行同个schema下的业务数据表,依然会造成主备延迟的情况。

思考2:

那么如果slave同时可以用多线程的方式,同时执行一个schema下的所有业务数据表,将能大大提高slave节点执行ralay log中记录的主库提交事务达到与主库数据同步的目的,实现该功能我们需要解决什么问题?

  • 1、前面提到过为了保证主库数据一致性,master节点写入的binary log日志按照数据库逻辑时间先后的顺序并且slave节点执行relay log中主库提交的事务必须按照一致的顺序否则会造成主备数据不一致的情况。
  • 2、既然要实现scehma下所有的业务数据表能够并发执行,那么slave必须得知道并发执行relay log中主库提交的事务不能相互影响而且结果必须和主库保持一致。

实现2:

MySQL 5.7 引入Enhanced Muti-threaded slaves,当slave配置slave_parallel_workers>0并且global.slave_parallel_type=‘LOGICAL_CLOCK’,可支持一个schema下,slave_parallel_workers个的worker线程并发执行relay log中主库提交的事务。但是要实现以上功能,需要在master机器标记binary log中的提交的事务哪些是可以并发执行,虽然MySQL 5.6已经引入了binary log group commit,但是没有将可以并发执行的事务标记出来。

我们用命令 mysqlbinlog -vvv mysqlbinlog.0000003 | grep -i last_committed    MySQL 5.7master机器上可以看到last_committed 和sequence_number

1.  #151223 15:11:28 server id 15102  end_log_pos 14623 CRC32 0x767a33fa GTID      last_committed=18         sequence_number=26

2.

3.  #151223 15:11:28 server id 15102  end_log_pos 15199 CRC32 0x7dd1bf05 GTID     last_committed=26         sequence_number=27

4.

5.  #151223 15:11:28 server id 15102  end_log_pos 15773 CRC32 0xb01dc76e GTID     last_committed=26         sequence_number=28

6.

7.  #151223 15:11:28 server id 15102  end_log_pos 16347 CRC32 0x7a8e0ee8 GTID     last_committed=26         sequence_number=29

8.

9.  #151223 15:11:28 server id 15102  end_log_pos 16921 CRC32 0x92516d17 GTID     last_committed=26         sequence_number=30

10.

11. #151223 15:11:28 server id 15102  end_log_pos 17495 CRC32 0xeb14a51e GTID     last_committed=26         sequence_number=31

12.

13. #151223 15:11:28 server id 15102  end_log_pos 18071 CRC32 0x750667d0 GTID     last_committed=26         sequence_number=32

14.

15. #151223 15:11:28 server id 15102  end_log_pos 18645 CRC32 0xcaed6159 GTID     last_committed=26         sequence_number=33

16.

17. #151223 15:11:28 server id 15102  end_log_pos 19219 CRC32 0x62408408 GTID     last_committed=26         sequence_number=34

18.

19. #151223 15:11:28 server id 15102  end_log_pos 19793 CRC32 0x5cf46239 GTID     last_committed=33         sequence_number=35

slave机器的relay log last_committed相同的事务(sequence_num不同)可以并发执行。从上面截取的信息可以看出last_committed=26的事务一共有8个:从sequence_number=27~24。假设当slave_parallel_workers=7时,Coordinator线程(SQL线程)分配这一组事务到worker中排队去执行。这里可以看出增加master库binary log group commit组中事务的数量可以提高slave机器并发处理事务的数量,MySQL5.7引入 binlog_group_commit_sync_delay和 binlog_group_commit_sync_no_delay_count参数即提高binary log组提交并发数量。MySQL等待binlog_group_commit_sync_delay毫秒的时间直到binlog_group_commit_sync_no_delay_count个事务数时,将进行一次组提交。

总结:

MySQL 5.7 GA版本推出的 Enhanced Multi-threaded Slaves功能,彻底解决了之前版本主备数据复制延迟的问题,开启该功能参数如下:

1.  # slave机器

2.  slave-parallel-type=LOGICAL_CLOCK

3.  #slave-parallel-type=DATABASE #兼容MySQL 5.6基于schema级别的并发复制

4.  slave-parallel-workers=16 #开启多线程复制

5.  master_info_repository=TABLE

6.  relay_log_info_repository=TABLE

7.  relay_log_recovery=ON

MySQL并发复制系列二:多线程复制 2016的更多相关文章

  1. Mysql 5.7 主从复制的多线程复制配置方式

    数据库复制的主要性能问题就是数据延时 为了优化复制性能,Mysql 5.6 引入了 “多线程复制” 这个新功能 但 5.6 中的每个线程只能处理一个数据库,所以如果只有一个数据库,或者绝大多数写操作都 ...

  2. MySQL并发复制系列二:多线程复制

     http://blog.itpub.net/28218939/viewspace-1975822/ 并发复制(Parallel Replication) 系列二: Enhanced Multi-th ...

  3. jAVA基础 提高文件复制性能之多线程复制文件

    利用IO流中的随机访问文件 RandomAccessFile 和文件通道 FileChanne 复制文件可大大提高文件的读写效率,在此基础上利用多线程复制文件使其性能更优.因线程的个数可根据文件的大小 ...

  4. Python并发编程系列之多线程

    1 引言 上一篇博文详细总结了Python进程的用法,这一篇博文来所以说Python中线程的用法.实际上,程序的运行都是以线程为基本单位的,每一个进程中都至少有一个线程(主线程),线程又可以创建子线程 ...

  5. java并发编程系列二:原子操作/CAS

    什么是原子操作 不可被中断的一个或者一系列操作 实现原子操作的方式 Java可以通过锁和循环CAS的方式实现原子操作 CAS( Compare And Swap )  为什么要有CAS? Compar ...

  6. MySQL的并行复制多线程复制MTS(Multi-Threaded Slaves)

    MySQL的并行复制多线程复制MTS(Multi-Threaded Slaves) http://www.tuicool.com/articles/m2Unmeq 姜承饶 简称MTS:基于binlog ...

  7. mysql并发复制系列 一:binlog组提交

    http://blog.itpub.net/28218939/viewspace-1975809/ 作者:沃趣科技MySQL数据库工程师  麻鹏飞 MySQL  Binary log在MySQL 5. ...

  8. MySQL并发复制系列一:binlog组提交 (转载)

    http://blog.csdn.net/woqutechteam/article/details/51178803 MySQL  Binary log在MySQL 5.1版本后推出主要用于主备复制的 ...

  9. MySQL系列详解八:MySQL多线程复制演示-技术流ken

    前言 Mysql 采用多线程进行复制是从 Mysql 5.6 开始支持的内容,但是 5.6 版本下有缺陷,虽然支持多线程,但是每个数据库只能一个线程,也就是说如果我们只有一个数据库,则主从复制时也只有 ...

随机推荐

  1. cxf,两个声明导致 ObjectFactory 类中发生冲突

    说明先,这里不管是client还是server端都是用java语言编写,如有写得不好,望原谅! 问题 http://localhost:8080/WEB-SMVC/cxf/userService?ws ...

  2. 浅析Spring事务传播行为和隔离级别

    7个传播行为.4个隔离级别. Spring事务的传播行为和隔离级别[transaction behaviorand isolatedlevel] Spring中事务的定义: Propagation(k ...

  3. @Autowired注解在抽象类中实效的原因分析

    最近在工作中遇到这个问题,在抽象类中使用Autowired这个注解,注入mybatis的dao时,总是出现空指针异常,通过日志的打印,发现是这个dao注入失败为空.然后通过new出spring上下文对 ...

  4. 【转】JAVA处理线程超时

    在实际业务中,由其是多线程并开业务中,经常会遇到某个线程执行超时.而程序如果不捕获这类情况,就会导致程序一直处于等待状态,从而影响后续线程的运行.比如说网络通迅.单任务下的复杂数据库查询等,通常处理这 ...

  5. 自学Zabbix3.7.2-事件Event-来源与分类

    一.zabbix 事件从字面理解,就是发生了一个事情就算是一个事件.就在trigger的文章内,我们已经有用到事件,这个事件要讲概念真心不知道怎么说,就拿trigger事件来说,如果trigger从当 ...

  6. 使用Flink时遇到的问题(不断更新中)

    1.启动不起来 查看JobManager日志: WARN org.apache.flink.runtime.webmonitor.JobManagerRetriever - Failed to ret ...

  7. ligerUI---ligerGrid分页排序的使用(从后台获取数据显示)

    写在前面: 最近项目的前框框架用的是ligerUI,里面用到了ligerGrid表格,下面就来说说从后台获取数据并在前台页面进行完美展示.啊哈哈哈..(天啦,坐我旁边的丽姐貌似炒股 一个月可以搞几十万 ...

  8. 环链表相关的题目和算法[LeetCode]

    这篇文章讨论一下与链表的环相关的题目,我目前遇到的一共有3种题目. 1.判断一个链表是否有环(LeetCode相关题目:https://leetcode.com/problems/linked-lis ...

  9. HTML基础教程-标题

    HTML 标题 在 HTML 文档中,标题很重要. HTML 标题 标题(Heading)是通过 <h1> - <h6> 等标签进行定义的. <h1> 定义最大的标 ...

  10. 前端模块化:RequireJS(转)

    前言 前端模块化能解决什么问题? 模块的版本管理 提高可维护性 -- 通过模块化,可以让每个文件职责单一,非常有利于代码的维护 按需加载 -- 提高显示效率 更好的依赖处理 -- 传统的开发模式,如果 ...