zoukankan      html  css  js  c++  java
  • mysql 主从并行复制(MTS)

    众所周知,MySQL的复制延迟是一直被诟病的问题之一,在MySQL 5.7版本已经支持“真正”的并行复制功能,官方称为为enhanced multi-threaded slave(简称MTS),因此复制延迟问题已经得到了极大的改进。总之,MySQL 5.7版本后,复制延迟问题永不存在。

    GTID (Global Transaction ID)是全局事务ID

    MySQL 5.7基于组提交的并行复制

    MySQL 5.7才可称为真正的并行复制,这其中最为主要的原因就是slave服务器的回放与主机是一致的即master服务器上是怎么并行执行的slave上就怎样进行并行回放。不再有库的并行复制限制,对于二进制日志格式也无特殊的要求(基于库的并行复制也没有要求)。

    MySQL 5.7并行复制的思想简单易懂,一言以蔽之: 一个组提交的事务都是可以并行回放 ,因为这些事务都已进入到事务的prepare阶段,则说明事务之间没有任何冲突(否则就不可能提交)。

    mysql 主从优化之并行复制(MTS)配置

    从库多线程MTS
    基本要求:
    5.7以上的版本
    必须开启GTID 
    binlog必须是row模式  
    
    gtid_mode=ON
    enforce_gtid_consistency=ON
    log_slave_updates=ON          # 前3行为开启gtid模式
    slave-parallel-type=LOGICAL_CLOCK  # 关键参数, 支持事务级别的sql进行并发回放, 默认是database级别(也就是只能并发database)
    slave-parallel-workers=16       # 并发回访的线程数, cpu数的一半
    master_info_repository=TABLE
    relay_log_info_repository=TABLE
    relay_log_recovery=ON
    
    5.7 :
    slave-parallel-type=LOGICAL_CLOCK
    slave-parallel-workers=8
    cpu核心数作为标准
    
    CHANGE MASTER TO
      MASTER_HOST='10.0.0.128',
      MASTER_USER='repl',
      MASTER_PASSWORD='123',
      MASTER_PORT=3307,
      MASTER_AUTO_POSITION=1;
    start slave;
    

    支持并行复制的GTID

    如何知道事务是否在一组中,又是一个问题,因为原版的MySQL并没有提供这样的信息。在MySQL 5.7版本中,其设计方式是将组提交的信息存放在GTID中。那么如果用户没有开启GTID功能,即将参数gtid_mode设置为OFF呢?故MySQL 5.7又引入了称之为Anonymous_Gtid的二进制日志event类型,如:

    mysql> SHOW BINLOG EVENTS in 'mysql-bin.000006';
    +------------------+-----+----------------+-----------+-------------+-----------------------------------------------+
    | Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
    +------------------+-----+----------------+-----------+-------------+-----------------------------------------------+
    | mysql-bin.000006 | 4 | Format_desc | 88 | 123 | Server ver: 5.7.7-rc-debug-log, Binlog ver: 4 |
    | mysql-bin.000006 | 123 | Previous_gtids | 88 | 194 | f11232f7-ff07-11e4-8fbb-00ff55e152c6:1-2 |
    | mysql-bin.000006 | 194 | Anonymous_Gtid | 88 | 259 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
    | mysql-bin.000006 | 259 | Query | 88 | 330 | BEGIN |
    | mysql-bin.000006 | 330 | Table_map | 88 | 373 | table_id: 108 (aaa.t) |
    | mysql-bin.000006 | 373 | Write_rows | 88 | 413 | table_id: 108 flags: STMT_END_F |
    ......
    

    这意味着在 MySQL 5.7版本中即使不开启GTID,每个事务开始前也是会存在一个Anonymous_Gtid ,而这GTID中就存在着组提交的信息。

    LOGICAL_CLOCK

    然而,通过上述的SHOW BINLOG EVENTS,我们并没有发现有关组提交的任何信息。但是通过mysqlbinlog工具,用户就能发现组提交的内部信息:

    root@localhost:~# mysqlbinlog mysql-bin.0000006 | grep last_committed
    #150520 14:23:11 server id 88 end_log_pos 259 CRC32 0x4ead9ad6 GTID last_committed=0 sequence_number=1
    #150520 14:23:11 server id 88 end_log_pos 1483 CRC32 0xdf94bc85 GTID last_committed=0 sequence_number=2
    #150520 14:23:11 server id 88 end_log_pos 2708 CRC32 0x0914697b GTID last_committed=0 sequence_number=3
    #150520 14:23:11 server id 88 end_log_pos 3934 CRC32 0xd9cb4a43 GTID last_committed=0 sequence_number=4
    #150520 14:23:11 server id 88 end_log_pos 5159 CRC32 0x06a6f531 GTID last_committed=0 sequence_number=5
    #150520 14:23:11 server id 88 end_log_pos 6386 CRC32 0xd6cae930 GTID last_committed=0 sequence_number=6
    #150520 14:23:11 server id 88 end_log_pos 7610 CRC32 0xa1ea531c GTID last_committed=6 sequence_number=7
    #150520 14:23:11 server id 88 end_log_pos 8834 CRC32 0x96864e6b GTID last_committed=6 sequence_number=8
    #150520 14:23:11 server id 88 end_log_pos 10057 CRC32 0x2de1ae55 GTID last_committed=6 sequence_number=9
    #150520 14:23:11 server id 88 end_log_pos 11280 CRC32 0x5eb13091 GTID last_committed=6 sequence_number=10
    #150520 14:23:11 server id 88 end_log_pos 12504 CRC32 0x16721011 GTID last_committed=6 sequence_number=11
    #150520 14:23:11 server id 88 end_log_pos 13727 CRC32 0xe2210ab6 GTID last_committed=6 sequence_number=12
    #150520 14:23:11 server id 88 end_log_pos 14952 CRC32 0xf41181d3 GTID last_committed=12 sequence_number=13
    ...
    

    可以发现较之原来的二进制日志内容多了last_committed和sequence_number,last_committed表示事务提交的时候,上次事务提交的编号,如果事务具有相同的last_committed,表示这些事务都在一组内,可以进行并行的回放。例如上述last_committed为0的事务有6个,表示组提交时提交了6个事务,而这6个事务在从机是可以进行并行回放的。

    上述的last_committed和sequence_number代表的就是所谓的LOGICAL_CLOCK。

    使用LOGICAL_CLOCK的场景如下:

    class MYSQL_BIN_LOG: public TC_LOG
    {
      ...
      public:
      /* Committed transactions timestamp */
      Logical_clock max_committed_transaction;
      /* "Prepared" transactions timestamp */
      Logical_clock transaction_counter;
      ...
    

    可以看到在类MYSQL_BIN_LOG中定义了两个Logical_clock的变量:

    • max_committed_transaction:记录上次组提交时的logical_clock,代表上述mysqlbinlog中的last_committed
    • transaction_counter:记录当前组提交中各事务的logcial_clock,代表上述mysqlbinlog中的sequence_number

    并行复制测试

    下图显示了开启MTS后,slave服务器的QPS。测试的工具是sysbench的单表全update测试,测试结果显示在16个线程下的性能最好,从机的QPS可以达到25000以上,进一步增加并行执行的线程至32并没有带来更高的提升。而原单线程回放的QPS仅在4000左右,可见MySQL 5.7 MTS带来的性能提升,而由于测试的是单表,所以MySQL 5.6的MTS机制则完全无能为力了。

    图片

    并行复制配置与调优

    master_info_repository

    开启MTS功能后,务必将参数master_info_repostitory设置为TABLE,这样性能可以有50%~80%的提升。这是因为并行复制开启后对于元master.info这个文件的更新将会大幅提升,资源的竞争也会变大。在之前 InnoSQL 的版本中,添加了参数来控制刷新master.info这个文件的频率,甚至可以不刷新这个文件。因为刷新这个文件是没有必要的,即根据master-info.log这个文件恢复本身就是不可靠的。在MySQL 5.7中,Inside君推荐将master_info_repository设置为TABLE,来减小这部分的开销。

    slave_parallel_workers

    若将slave_parallel_workers设置为0,则MySQL 5.7退化为原单线程复制,但将slave_parallel_workers设置为1,则SQL线程功能转化为coordinator线程,但是只有1个worker线程进行回放,也是单线程复制。然而,这两种性能却又有一些的区别,因为多了一次coordinator线程的转发,因此slave_parallel_workers=1的性能反而比0还要差,在Inside君的测试下还有20%左右的性能下降,如下图所示:

    图片

    这里其中引入了另一个问题,如果主机上的负载不大,那么组提交的效率就不高,很有可能发生每组提交的事务数量仅有1个,那么在从机的回放时, 虽然开启了并行复制,但会出现性能反而比原先的单线程还要差的现象,即延迟反而增大了 。聪明的小伙伴们,有想过对这个进行优化吗?

    Enhanced Multi-Threaded Slave配置

    说了这么多,要开启enhanced multi-threaded slave其实很简单,只需根据如下设置:

    # slave
    slave-parallel-type=LOGICAL_CLOCK
    slave-parallel-workers=16
    master_info_repository=TABLE
    relay_log_info_repository=TABLE
    relay_log_recovery=ON
    

    并行复制监控

    复制的监控依旧可以通过SHOW SLAVE STATUSG,但是MySQL 5.7在performance_schema架构下多了这些表,用户可以更细力度的进行监控:

    mysql> show tables like 'replication%';
    +---------------------------------------------+
    | Tables_in_performance_schema (replication%) |
    +---------------------------------------------+
    | replication_applier_configuration           |
    | replication_applier_status                  |
    | replication_applier_status_by_coordinator   |
    | replication_applier_status_by_worker        |
    | replication_connection_configuration        |
    | replication_connection_status               |
    | replication_group_member_stats              |
    | replication_group_members                   |
    +---------------------------------------------+
    8 rows in set (0.00 sec)
    

    总结

    MySQL 5.7推出的Enhanced Multi-Threaded Slave解决了困扰MySQL长达数十年的复制延迟问题,再次提醒一些无知的PostgreSQL用户,不要再停留在之前对于MySQL的印象,物理复制也不一定肯定比逻辑复制有优势,而MySQL 5.7的MTS已经完全可以解决延迟问题。

  • 相关阅读:
    封装、权限修饰符、包、构造器
    从Discuz!NT v2.0扣出来的生成静态页面的方法
    C#中struct与class的区别
    Asp.Net中虚拟文件系统的使用
    C#生成中文验证码
    C#导入Excel表
    IIS5、IIS6、IIS7的ASP.net 请求处理过程比较
    如何保证Session值不丢失
    C#抽象类与接口的区别
    C#实现DES加密解密
  • 原文地址:https://www.cnblogs.com/caibaotimes/p/14667438.html
Copyright © 2011-2022 走看看