• MySQL半同步复制实践


    1.主从复制原理

    在MySQL主从复制中,大体上有三个线程,master端有一个dump 线程,slave端有两个线程,i/o 线程和sql线程。

    当有数据写入后,master 端的dump线程将bin log发送到slave端的io线程,i/o线程接收后,将其存放在本地的relay log中。

    sql线程读取relay log,接着重放 event,更新数据。

    主从复制有三种方式:

    • 异步复制
    • 同步复制
    • 半同步复制

    其中,同步复制中,master执行一个事务后,要求所有的slave都执行完成后,才会返回给客户端。这样,在性能上,是有影响的。同步复制的优势,就是不丢失数据。缺点,就是复制效率低。
    MySQL自身不支持同步复制,需要用第三方工具如DRBD(sync模式)等实现同步复制。

    异步复制中,master 更新操作写入binlog后,就会返回给客户端。不关心,slave 是否接收到binlog,以及是否应用了更新。异步复制的优势,是复制效率高。缺点是,可能会丢失数据。

    半同步复制(semi-sync repication),是介于同步复制和异步复制之间的一种复制方式。主库在执行完客户端提交的事务之后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端(极端情况下,如果等待超时,会退化为异步复制)。相对于异步复制,半同步复制提高了数据的安全性。

    2.半同步复制环境搭建

    下文使用的是单机多实例环境,具体搭建过程可参考单机安装MySQL多实例

    MySQL版本是 5.7.27。

    MySQL主从集群信息如下:

    角色 ip port
    主库 127.0.0.1 3306
    从库 127.0.0.1 3307

    2.1 半同步插件安装和配置

    MySQL安装包中,已经自带MySQL半同步插件。

    $ ll /application/mysql/lib/plugin/semi*
    -rwxr-xr-x. 1 lanyang lanyang 708586 Jun 10  2019 /application/mysql/lib/plugin/semisync_master.so
    -rwxr-xr-x. 1 lanyang lanyang 152341 Jun 10  2019 /application/mysql/lib/plugin/semisync_slave.so
    

    2.1.1 主库半同步插件安装和配置

    安装插件

    mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> 
    

    主库开启半同步

    mysql> set global rpl_semi_sync_master_enabled = 1;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> 
    

    配置半同步超时参数(单位ms)

    mysql> set global rpl_semi_sync_master_timeout = 1000;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> 
    

    该参数表示主库等待从库ack的时间,如果超时,半同步复制就退化为异步复制。

    此处配置的超时时间是1s。

    在配置文件添加,使其永久生效:

    [mysqld]
    rpl_semi_sync_master_enabled = 1
    rpl_semi_sync_master_timeout = 1000
    

    查看半同步插件安装和配置状态

    mysql> select * from mysql.plugin;
    +----------------------+--------------------+
    | name                 | dl                 |
    +----------------------+--------------------+
    | rpl_semi_sync_master | semisync_master.so |
    +----------------------+--------------------+
    1 row in set (0.00 sec)
    

    主库半同步复制的状态参数

    mysql> show global status like '%semi%';
    +--------------------------------------------+-------+
    | Variable_name                              | Value |
    +--------------------------------------------+-------+
    | Rpl_semi_sync_master_clients               | 0     |
    | Rpl_semi_sync_master_net_avg_wait_time     | 0     |
    | Rpl_semi_sync_master_net_wait_time         | 0     |
    | Rpl_semi_sync_master_net_waits             | 0     |
    | Rpl_semi_sync_master_no_times              | 0     |
    | Rpl_semi_sync_master_no_tx                 | 0     |
    | Rpl_semi_sync_master_status                | ON    |
    | Rpl_semi_sync_master_timefunc_failures     | 0     |
    | Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
    | Rpl_semi_sync_master_tx_wait_time          | 0     |
    | Rpl_semi_sync_master_tx_waits              | 0     |
    | Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
    | Rpl_semi_sync_master_wait_sessions         | 0     |
    | Rpl_semi_sync_master_yes_tx                | 0     |
    +--------------------------------------------+-------+
    14 rows in set (0.00 sec)
    

    其中,Rpl_semi_sync_master_clients 有多少个开启了半同步复制的从库。

    Rpl_semi_sync_master_net_avg_wait_time master等待slave回复的平均网络等待时间。

    Rpl_semi_sync_master_net_wait_time 总网络等待时间。

    Rpl_semi_sync_master_net_waits master等待slave回复总的网络等待次数。

    Rpl_semi_sync_master_tx_avg_wait_time 平均事务等待时间。

    Rpl_semi_sync_master_tx_wait_time 总事务等待时间。

    Rpl_semi_sync_master_tx_waits 总事务等待次数。

    Rpl_semi_sync_master_yes_tx 接收确认次数。

    Rpl_semi_sync_master_no_times 关闭半同步复制的次数。

    Rpl_semi_sync_master_no_tx 查看有多少事务没有使用半同步复制的机制进行复制,也就是master等待超时的次数。

    主库半同步复制的相关参数配置

    mysql> show global variables like '%semi%';
    +-------------------------------------------+------------+
    | Variable_name                             | Value      |
    +-------------------------------------------+------------+
    | rpl_semi_sync_master_enabled              | ON         |
    | rpl_semi_sync_master_timeout              | 1000       |
    | rpl_semi_sync_master_trace_level          | 32         |
    | rpl_semi_sync_master_wait_for_slave_count | 1          |
    | rpl_semi_sync_master_wait_no_slave        | ON         |
    | rpl_semi_sync_master_wait_point           | AFTER_SYNC |
    +-------------------------------------------+------------+
    6 rows in set (0.00 sec)
    

    其中,
    rpl_semi_sync_master_wait_for_slave_count 表示主库事务提交前,在指定的时间rpl_semi_sync_master_timeout超时之前,必须有这个指定数量的从库确认已接收到。

    如果超时之前,仍然没有得到rpl_semi_sync_master_wait_for_slave_count这个数量的从库确认,则退化为异步复制。

    默认值1,即超时之前,需要有一个从库确认已接收到bin log,事务才可以提交。

    对于
    rpl_semi_sync_master_wait_no_slave,表示是否每个事务提交后都需要等待从库的接收确认信号。

    如果为ON(默认是ON),只要指定数量的从库在超时之前确认已接收,则半同步复制会继续。

    如果为OFF,表示在超时之前,没有达到指定数量从库已确认接收。则退化为异步复制。

    2.1.2 从库半同步插件安装和配置

    mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> 
    

    从库开启半同步

    mysql> set global rpl_semi_sync_slave_enabled = 1;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> 
    

    添加到配置文件使其永久生效:

    [mysqld]
    rpl_semi_sync_slave_enabled = 1
    

    配置后,记得重启下i/o线程。

    查看从库上半同步复制状态和参数:

    mysql> show global status like '%semi%';
    +----------------------------+-------+
    | Variable_name              | Value |
    +----------------------------+-------+
    | Rpl_semi_sync_slave_status | ON    |
    +----------------------------+-------+
    1 row in set (0.00 sec)
    
    mysql> show global variables like '%semi%';
    +---------------------------------+-------+
    | Variable_name                   | Value |
    +---------------------------------+-------+
    | rpl_semi_sync_slave_enabled     | ON    |
    | rpl_semi_sync_slave_trace_level | 32    |
    +---------------------------------+-------+
    2 rows in set (0.00 sec)
    
    

    接着,查看主库上的半同步复制状态:

    mysql> show global status like '%semi%';
    +--------------------------------------------+-------+
    | Variable_name                              | Value |
    +--------------------------------------------+-------+
    | Rpl_semi_sync_master_clients               | 1     |
    +--------------------------------------------+-------+
    ... ...
    14 rows in set (0.00 sec)
    
    

    显示已有一个从库通过半同步复制连接到主库。

    2.2 半同步复制测试

    2.2.1 测试1--简单测试

    在主库上写入两条数据:

    mysql> insert into app.test(service_group_name) values('abc001');
    Query OK, 1 row affected (0.01 sec)
    
    mysql> insert into app.test(service_group_name) values('abc002');
    Query OK, 1 row affected (0.00 sec)
    
    

    查看主库上的半同步复制状态:

    mysql> show global status like '%semi%';
    +--------------------------------------------+-------+
    | Variable_name                              | Value |
    +--------------------------------------------+-------+
    | Rpl_semi_sync_master_clients               | 1     |
    | Rpl_semi_sync_master_net_avg_wait_time     | 0     |
    | Rpl_semi_sync_master_net_wait_time         | 0     |
    | Rpl_semi_sync_master_net_waits             | 2     |
    | Rpl_semi_sync_master_no_times              | 0     |
    | Rpl_semi_sync_master_no_tx                 | 0     |
    | Rpl_semi_sync_master_status                | ON    |
    | Rpl_semi_sync_master_timefunc_failures     | 0     |
    | Rpl_semi_sync_master_tx_avg_wait_time      | 472   |
    | Rpl_semi_sync_master_tx_wait_time          | 472   |
    | Rpl_semi_sync_master_tx_waits              | 1     |
    | Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
    | Rpl_semi_sync_master_wait_sessions         | 0     |
    | Rpl_semi_sync_master_yes_tx                | 2     |
    +--------------------------------------------+-------+
    14 rows in set (0.00 sec)
    
    mysql> 
    

    2.2.2 测试2--超时测试

    (1)停止从库的i/o线程

    停止从库的i/o线程,可以使半同步复制超时。

    mysql> stop slave io_thread;
    Query OK, 0 rows affected (0.01 sec)
    

    (2)在主库上写入数据

    mysql> insert into app.test(service_group_name) values('abc003');
    Query OK, 1 row affected (1.01 sec)
    
    mysql> 
    

    可以看到执行时间1.01s。

    查看此时的半同步复制状态:

    mysql> show global status like '%semi%';
    +--------------------------------------------+-------+
    | Variable_name                              | Value |
    +--------------------------------------------+-------+
    | Rpl_semi_sync_master_clients               | 0     |
    | Rpl_semi_sync_master_net_avg_wait_time     | 0     |
    | Rpl_semi_sync_master_net_wait_time         | 0     |
    | Rpl_semi_sync_master_net_waits             | 2     |
    | Rpl_semi_sync_master_no_times              | 1     |
    | Rpl_semi_sync_master_no_tx                 | 1     |
    | Rpl_semi_sync_master_status                | OFF   |
    | Rpl_semi_sync_master_timefunc_failures     | 0     |
    | Rpl_semi_sync_master_tx_avg_wait_time      | 472   |
    | Rpl_semi_sync_master_tx_wait_time          | 472   |
    | Rpl_semi_sync_master_tx_waits              | 1     |
    | Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
    | Rpl_semi_sync_master_wait_sessions         | 0     |
    | Rpl_semi_sync_master_yes_tx                | 2     |
    +--------------------------------------------+-------+
    14 rows in set (0.01 sec)
    

    Rpl_semi_sync_master_no_times 关闭半同步的次数为1。

    Rpl_semi_sync_master_no_tx 等待超时的次数,为1.

    Rpl_semi_sync_master_status 半同步状态处于关闭状态。

    (3)从库开启i/o 线程

    mysql> start slave io_thread;
    Query OK, 0 rows affected (0.00 sec)
    

    (4)再次查看主库上半同步复制状态

    mysql> show global status like '%semi%';
    +--------------------------------------------+-------+
    | Variable_name                              | Value |
    +--------------------------------------------+-------+
    | Rpl_semi_sync_master_clients               | 1     |
    | Rpl_semi_sync_master_net_avg_wait_time     | 0     |
    | Rpl_semi_sync_master_net_wait_time         | 0     |
    | Rpl_semi_sync_master_net_waits             | 3     |
    | Rpl_semi_sync_master_no_times              | 1     |
    | Rpl_semi_sync_master_no_tx                 | 1     |
    | Rpl_semi_sync_master_status                | ON    |
    | Rpl_semi_sync_master_timefunc_failures     | 0     |
    | Rpl_semi_sync_master_tx_avg_wait_time      | 472   |
    | Rpl_semi_sync_master_tx_wait_time          | 472   |
    | Rpl_semi_sync_master_tx_waits              | 1     |
    | Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
    | Rpl_semi_sync_master_wait_sessions         | 0     |
    | Rpl_semi_sync_master_yes_tx                | 2     |
    +--------------------------------------------+-------+
    14 rows in set (0.00 sec)
    

    从库复制后,主库半同步复制状态又变为ON。

    3.参考

    16.1.6.2 Replication Source Options and Variables

  • 相关阅读:
    自己动手实现一个WEB服务器
    Java SPI机制和使用示例
    Redis笔记(七):Redis应用场景
    Linux笔记:linux常用命令
    Linux笔记:vi常用命令
    PostgreSQL执行超时的问题
    Redis笔记(五):Redis发布订阅
    Redis笔记(四):Redis事务支持
    Redis笔记(三):Redis常用命令
    Redis笔记(二):Redis数据类型
  • 原文地址:https://www.cnblogs.com/lanyangsh/p/13779797.html
Copyright © 2020-2023  润新知