mysql主从复制架构及实现

MySQL复制:

  • 扩展方式:
    • Scale up,向上扩展;使用更好更高级性能的硬件;
    • Scale Out,向外扩展;增加更多的主机
  • MySQL的扩展:
    • 复制:复制是mysql向外扩展的解决方案,每个节点都有相同的数据集;结构通常是主从复制结构;工作方式就是让从节点通过向主节点请求二进制日志中的事件于本地,并执行replay完成;复制默认是单向进行的;
    • 主从复制:mysql的从节点不接收任何修改操作的请求,而仅仅把自己扮演成客户端,向主服务器请求主服务器上所有的数据修改,并在本地replay一遍,从而实现跟主服务器一模一样的数据集;在这个数据集上可以接受其他用户的读请求;但不接收写请求,这就叫做mysql的主从复制;
  • 为什么要做mysql复制?完成数据分布的目的;例如,更多用户查询;
    • 冗余:既然能完成冗余就能提升高可用性能,可写脚本检测主从节点当中,主节点的可靠性,一旦发现主节点故障,将主节点下线,自动提升从节点为主节点,所以就完成了故障切换,从而实现高可用功能;
      市面有很多实现高可用解决方案,就是通过这种方式实现的;
    • 负载均衡:主节点接受所有的写操作,并且把写操作又同步给从节点一份,所以,从节点也必须要完成同样多的写操作;因此,只能负载均衡读请求;
    • 支援安全的备份操作:当主节点挂了,从节点迅速提升为主节点;这是一种冗余功能;复制还能帮助完成备份;数据做冷备是最可靠的,冷备不可能在线上做但是最可靠的;而有了复制结构以后,可以给主服务器配置一个从节点,当需要做备份时,只需将从节点从主复制上给它下线,停止服务,然后直接复制数据副本就ok了;辅助完成备份的;
    • 测试:通过备份的方式,把数据放到新版的msyql服务器上测试;

MySQL主从复制

mysql主从复制.png
工作模式:

主节点(master)必须启用二进制日志,所有的写操作除了保存在数据中一份之外,还会在本地的二进制日志中将能够修改数据或潜在有可能修改数据的语句记录在二进制日志文件中一份;
从节点(slave)启动一个专门的线程,把自己扮演成mysql客户端,通过mysql协议向mysql服务器请求读取对方二进制日志中的事件,服务器端会检查自己二进制日志中的事件跟对方请求的位置(对方会指明请求二进制日志中的事件),于是服务器会从自己的二进制日志中根据请求者指定的位置,如果请求者不能指定就从第一个文件的最开始处开始,把一个个事件发送给从节点。
从节点收到后,每读到一个事件,先保存在中继日志中,保存完成后还会用一个文件记录已经读到了主节点哪个二进制日志的哪个位置,索引下次请求时,就会告诉主节点自己读到哪个位置了,从该位置之后是否产生新事件,如果有,主节点又会继续发送事件给从节点。
从节点不断的向主节点发送这种请求,让主节点检索有没有新事件,如果有的话,主节点需要启动一个叫做mysqldump线程,dump它能够从二进制日志文件中,把事件读出来,并响应给从节点;
从节点得到事件后保存在中继日志中,目的是在本地replay一遍,因此,在本地还要启动一个叫sql thread 的线程,负责从中级日志中读一个事件然后在本地执行一遍,最终数据就保存在数据文件中;而负责从节点向主节点请求数据的线程叫做IO thread。

主从架构类型:
  • 异步复制:主节点收到写操作后,只需要保证本地写入完成,那么就立即返回给客户端写入操作完成,不用等待从服务器反馈写入完成并在本地重放完成。
  • 半同步复制:一个主节点有多个从节点,主节点接收到请求以后,要至少等待一个从节点同步完成并告诉主节点数据存储完成,主节点才返回客户端结果,但从节点可有n个,给余的从节点异步;一旦主节点掉线,至少能够有一个从节点数据是完整的
  • 一主多从
  • 一主一从
  • 级联复制:一个节点首先是主节点的从,同时又是其它节点的主:
  • 循环复制:每一个服务器都是下家的主服务器同时又是上家的从服务器;
  • 双柱复制
  • 一从多主: 每个主服务器提供不同的数据库
主从复制的落后原因:

事实上落后也有很大的好处,有时甚至需要专门落后一些时间;例如,一不小心删除了数据库,这样,从服务器落后主服务器就不用担心,赶紧断开从服务器,所有数据仍然不受影响,把从服务器切换为线上的主节点就OK了;
所以在有些场景中有意让专门一台从服务器落后与主服务器一段时间;

对非常繁忙的主节点,由于主节点事务是可以并行的,就意味着很多事务是并行提交的,对数据库本身没什么问题,因为本地有内存,本地数据文件有可能是分散的,因为本地还有可能有多个数据库,所以IO可以分散出去;但是,无论有多少本地事务提交的操作,有多少个写语句,这些写语句只能一个一个写进二进制日志中;从这个角度认为,一个非常繁忙的主节点必然的其本地的执行速度要快于往二进制日志中写入的速度;这样就可认为从节点在复制的过程就更慢了,因此,这种落后也是必然的;有时从节点落后于主节点一两个小时都很常见;

主从配置过程:

(1) 时间同步;
(2)复制的开始位置;
从0开始;
从备份中恢复从节点后启动的复制,复制的起始点是备份操作时主节点所处的日志文件及其事件位置
(3) 中从服务器mysqld程序版本
从服务器版本号可以高于主的版本号
(4) 主节点配置

在mysql配置文件中添加:
[mysqld]
log_bin=mysql-bin    #开启二进制日志
server_id=#       #为当前节点设置一个全局唯一的ID号

启动服务并创建有复杂权限的用户账号:
需要有`REPLICATION SLAVE, REPLICATION CLIENT `两种权限


mysql> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'USERNAME'@'HOST' IDENTIFIED BY 'PASSWORD';
mysql> FLUSH PRIVILEGES;

(5) 从节点配置

配置文件my.cnf
[mysqld]
server_id=#
relay_log=relay_log
read_only=ON

启动服务:
mysql> CHANGE MASTER TO MASTER_HOST='HOST',MASTER_USER='USERNAME',MASTER_PASSWORD='PASSWORD',MASTER_LOG_FILE='BINLOG',MASTER_LOG_POS=#;
mysql> START SLAVE [IO_THREAD|SQL_THREAD];
mysql> SHOW SLAVE STATUS;

练习:基于SSL复制的实现示例:

启用ssl功能可以参考:https://www.jianshu.com/p/eb9d4ab3991e 最后一个练习

此处创建CA server端ssl不在赘述,直接创建client的ssl开始
CA服务和mysql的主节点安装在192.168.43.13
从节点为192.168.43.14
在主节点创建从节点ssl认证所需的key:
[root@node3 ~]# cd /var/lib/mysql/.ssl
[root@node3 .ssl]# (umask 077;openssl genrsa -out client.key 2048)
[root@node3 .ssl]# openssl req -new -key client.key -out client.crt -days 365
[root@node3 .ssl]# openssl ca -in client.crt -out client.pem -days 365
[root@node3 .ssl]# openssl rsa -in client.key -out client-key.pem
[root@node3 .ssl]# scp client* root@192.168.43.14:/var/lib/mysql/.ssl/

[root@node3 .ssl]# mysql   
登录mysql并创建基于ssl的具有复制权限的用户和密码
MariaDB [(none)]> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'inspur'@'192.168.43.%' IDENTIFIED BY 'inspur' REQUIRE SSL;
MariaDB [(none)]> FLUSH PRIVILEGES;

在从节点登录测试:
[root@node4 .ssl]# mysql --ssl-cert=/var/lib/mysql/.ssl/client.pem --ssl-key=/var/lib/mysql/.ssl/client-key.pem -uinspur -h192.168.43.13 -pinspur
配置从节点配置文件
[root@node4 .ssl]# vim /etc/my.cnf
    ssl     
    ssl_cert=/var/lib/mysql/.ssl/client.pem
    ssl_key=/var/lib/mysql/.ssl/client-key.pem
[root@node4 .ssl]# systemctl start mariadb.service
[root@node4 .ssl]# mysql 
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.43.13',MASTER_USER='inspur',MASTER_PASSWORD='inspur',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=245,MASTER_SSL=1,MASTER_SSL_CERT='/var/lib/mysql/.ssl/client.pem',MASTER_SSL_KEY='/var/lib/mysql/.ssl/client-key.pem';
MariaDB [(none)]> START SLAVE;
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.43.13
                  Master_User: inspur
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000005
          Read_Master_Log_Pos: 409
               Relay_Log_File: relay-log.000004
                Relay_Log_Pos: 693
        Relay_Master_Log_File: mysql-bin.000005
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 409
              Relay_Log_Space: 1873
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: Yes
           Master_SSL_CA_File: /etc/pki/CA/cacert.pem
           Master_SSL_CA_Path: 
              Master_SSL_Cert: /var/lib/mysql/.ssl/client.pem
            Master_SSL_Cipher: 
               Master_SSL_Key: /var/lib/mysql/.ssl/client-key.pem
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
1 row in set (0.00 sec)

ERROR: No query specified

主主复制:

  • 互为主从:两个节点各自都要开启binlog和relay log;
    (1) 数据不一致;因此,慎用;无论主从还是主主,只能选择一个并备份出来,删除另一个;
    (2) 自动增长id;

    • 定义一个节点使用奇数id
      auto_increment_offset=1
      auto_increment_increment=2
    • 另一个节点使用偶数id:
      auto_increment_offset=2
      auto_increment_increment=2
  • 配置步骤:

    • (1) 各节点使用唯一的server_id;
    • (2) 都启动binary log和relay log;
    • (3) 创建拥有复制权限的用户账号;
    • (4) 定义自动增长id字段的数值范围为奇偶;
    • (5) 均把对方指定为主节点,并启动复制线程;
  • 复制时应该注意的问题:

    •   1、从服务设定为“只读”;
        在从服务器启动read_only,但仅对非SUPER权限的用户有效;          
        阻止所有用户:
            `mysql> FLUSH TABLES WITH READ LOCK;    `           
      
    •   2、尽量确保复制时的事务安全
        在master节点启用参数:
            `sync_binlog = ON `:当遇到事务提交时,必须将binlog缓冲区中(内存中)记录的事件立即刷新到磁盘上的二进制日志文件中区;
            如果用到的是InnoDB存储引擎:
                `innodb_flush_logs_at_trx_commit=ON`:事务提交时,立即将事务缓冲区中与事务相关的数据刷写到磁盘上的事务日志中区
                `innodb_support_xa=ON   `:xa为分布式事务,是否让innodb支持分布式事务;        
      
    •   3、从服务器意外中止时尽量避免自动启动复制线程
        `skip_slave_start=ON`:      是否自动启动复制线程;默认是自动启动的,建议关闭,手动启动复制功能;
      
    •   4、从节点:设置参数
        `sync_master_info=ON`:每一次当给从节点dump一些event之后,本地对应的master_info信息是否会立即同步到磁盘上让从节点能够获取到或让本地立即记录下来;启动为ON,但会增加磁盘IO压力;
      
      sync_relay_log_info=ON
演示示例:
节点1:192.168.43.13
节点2:192168.43.14

停止msyql服务,清除此前实验;
[root@node3 ~]# systemctl stop mariadb
[root@node3 ~]# rm -rf /var/lib/mysql/*
修改节点1的配置文件:
[root@node3 ~]# vim /etc/my.cnf
    [mysqld]
    ...
    log_bin=mysql-bin
    server_id=1
    relay_log=relay-bin
    
    auto_increment_offset=1
    auto_increment_increment=2
修改节点2的配置文件:
[root@node4 ~]# vim /etc/my.cnf
    [mysqld]
    ...
    log_bin=mysql-bin
    server_id=2
    relay_log=relay-bin
    
    auto_increment_offset=2
    auto_increment_increment=2

分别启动mysql服务:
[root@node3 ~]# systemctl start mariadb
Job for mariadb.service failed because the control process exited with error code. See "systemctl status mariadb.service" and "journalctl -xe" for details.   #此处因为前面直接rm删除了数据库文件,因此需要使用`mysql_install_db --datadir=/var/lib/mysql`   重新初始化,并修改`/var/lib/mysql的属主属组为mysql

然后重新启动:
[root@node3 ~]# systemctl start mariadb

连接到mysql服务器上查看二进制日志和中继日志是否都启动
MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+
1 row in set (0.00 sec)
MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE 'relay_log';
+---------------+-----------+
| Variable_name | Value     |
+---------------+-----------+
| relay_log     | relay-bin |
+---------------+-----------+

在两节点上:设置复制权限的账号:
MariaDB [(none)]> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slave'@'192.168.43.14' IDENTIFIED BY 'slave';
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

在节点1上:
MariaDB [(none)]> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      503 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.43.14',MASTER_USER='slave',MASTER_PASSWO
RD='slave',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=501;
Query OK, 0 rows affected (0.02 sec)

MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
在节点2上:
MariaDB [(none)]> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |      501 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.43.13',MASTER_USER='slave',MASTER_PASSWORD='slave',MASTER_LOG_FILE='mysql-bin.000003',MASTER_LOG_POS=503;
Query OK, 0 rows affected (0.03 sec)

MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.43.14
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 501
               Relay_Log_File: relay-bin.000002
                Relay_Log_Pos: 529
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 501
              Relay_Log_Space: 817
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 3
1 row in set (0.00 sec)
    
测试:
在节点1上创建一个数据库:
MariaDB [(none)]> CREATE DATABASE mydb;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| #mysql50#.ssl      |
| mydb               |
| mysql              |
| performance_schema |
| test               |
+--------------------+
在节点2上查看:
MariaDB [(none)]> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| #mysql50#.ssl      |
| mydb               |
| mysql              |
| performance_schema |
| test               |
+--------------------+


至此双主模式配置完成

半同步复制:

一个个主节点有多个从节点,主节点接收到请求以后,要至少等待一个从节点同步完成并告诉主节点数据存储完成,主节点才返回客户端结果,但从节点可有n个,给余的从节点异步;一旦主节点掉线,至少能够有一个从节点数据是完整的,把这种模型叫半同步复制模型;
这个半同步的服务器应该与主节点在同一机架或同一机房内的有着充分带宽的节点;其它节点可以是跨机房或跨互联网的;
支持多种插件:插件路径为/usr/lib64/mysql/plugins/
需要安装方可使用,安装方法:`mysql> INSTALL PLUGIN plugin_name SONAME 'shared_library_name';

  • 半同步复制所需插件:
    semisync_master.so
    semisync_slave.so
半同步复制示例:
清除此前主主模型的实验:
 ~]# systemctl stop mariadb.service
 ~]# rm -rf /var/lib/mysql/*
重启配置为主从复制模型后再主节点安装相应插件并配置:
[root@node3 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 5.5.60-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.01 sec)

MariaDB [(none)]> SHOW PLUGINS;
+--------------------------------+----------+--------------------+--------------------+---------+
| Name                           | Status   | Type               | Library            | License |
+--------------------------------+----------+--------------------+--------------------+---------+
| binlog                         | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| mysql_native_password          | ACTIVE   | AUTHENTICATION     | NULL               | GPL     |
| mysql_old_password             | ACTIVE   | AUTHENTICATION     | NULL               | GPL     |
| MEMORY                         | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| CSV                            | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| MyISAM                         | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| MRG_MYISAM                     | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| Aria                           | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| BLACKHOLE                      | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| FEDERATED                      | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| ARCHIVE                        | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| InnoDB                         | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| INNODB_RSEG                    | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_UNDO_LOGS               | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_TRX                     | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_LOCKS                   | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_LOCK_WAITS              | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_CMP                     | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_CMP_RESET               | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_CMPMEM                  | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_CMPMEM_RESET            | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_SYS_TABLES              | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_SYS_TABLESTATS          | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_SYS_INDEXES             | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_SYS_COLUMNS             | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_SYS_FIELDS              | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_SYS_FOREIGN             | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_SYS_FOREIGN_COLS        | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_SYS_STATS               | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_TABLE_STATS             | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_INDEX_STATS             | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_BUFFER_POOL_PAGES       | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_BUFFER_POOL_PAGES_INDEX | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_BUFFER_POOL_PAGES_BLOB  | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| XTRADB_ADMIN_COMMAND           | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_CHANGED_PAGES           | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_BUFFER_PAGE             | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_BUFFER_PAGE_LRU         | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| INNODB_BUFFER_POOL_STATS       | ACTIVE   | INFORMATION SCHEMA | NULL               | GPL     |
| PERFORMANCE_SCHEMA             | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| FEEDBACK                       | DISABLED | INFORMATION SCHEMA | NULL               | GPL     |
| partition                      | ACTIVE   | STORAGE ENGINE     | NULL               | GPL     |
| rpl_semi_sync_master           | ACTIVE   | REPLICATION        | semisync_master.so | GPL     |
+--------------------------------+----------+--------------------+--------------------+---------+
43 rows in set (0.00 sec)

MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE '%semi%';
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled       | OFF   |
| rpl_semi_sync_master_timeout       | 10000 |
| rpl_semi_sync_master_trace_level   | 32    |
| rpl_semi_sync_master_wait_no_slave | ON    |
+------------------------------------+-------+
4 rows in set (0.00 sec)

MariaDB [(none)]> SET @@GLOBAL.rpl_semi_sync_master_enabled=1;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE '%semi%';
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled       | ON    |
| rpl_semi_sync_master_timeout       | 10000 |
| rpl_semi_sync_master_trace_level   | 32    |
| rpl_semi_sync_master_wait_no_slave | ON    |
+------------------------------------+-------+


从节点安装插件并配置:
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.02 sec)    

MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE '%semi%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | OFF   |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+
2 rows in set (0.00 sec)

MariaDB [(none)]> SET @@GLOBAL.rpl_semi_sync_slave_enabled=1;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> 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)
    
MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.03 sec)

主节点查看:
MariaDB [(none)]> 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             | 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)

注意:使用INSTALL PLUGIN plugin_name SONAME 'shared_library_name时,可以在配置文件中[mysqld]段中添加:
plugin_dir=/path/to/plugin/directory;不指明则默认在/usr/lib64/mysql/pligin/目录下;
plugin_name:为插件的名字;
shared_library_name:为插件文件的名字;

插件安装后会生成很多服务器变量:

rpl_semi_sync_master_enabled:是否启用自己为半同步节点
rpl_semi_sync_master_timeout:等待从节点超时时间;单位毫秒,默认10秒;
rpl_semi_sync_master_trace_level:跟踪级别;使用默认值即可
rpl_semi_sync_master_wait_no_slave:没有从节点是否等待;
rpl_semi_sync_master_clients:对于当前主节点,有多少个半同步节点;
Rpl_semi_sync_master_net_avg_wait_time:网络平均等待时间;
rpl_semi_sync_master_net_wait_time:网络等待时间;
rpl_semi_sync_master_net_waits:网络等待次数;
rpl_semi_sync_master_tx_avg_wait_time:事务的平均等待时间;
rpl_semi_sync_master_tx_wait_time:事务的等待时间;
rpl_semi_sync_master_tx_waits:事务的等待次数;
rpl_semi_sync_slave_enabled:是否启用为半同步节点
rpl_semi_sync_slave_trace_level:跟踪级别

复制过滤器:

仅复制有限一个或几个数据库相关的数据,而非所有;由复制过滤器进行;

  • 有两种实现方式:
    • (1) 主服务器仅向二进制日志中记录与特定数据库(特定表)相关的事件
      使用方法:
      • binlog_do_db=:数据库白名单列表,使用逗号分隔;只记录哪些数据看相关的写入操作到二进制文件中;
      • binlog_ingore_db=:数据库黑名单列表,使用逗号分隔;仅忽略哪些数据库相关的写入操作到而键值文件中
    • 注意:二者不能同时使用;还有此方法时间点还原无法实现,不建议使用;
    • (2) 从服务器SQL_THREDA在replay中继日志中的事件时,仅读取特定数据库(特定表)相关的事件并应用于本地;
      使用方法:
      • reolicate_do_db=:仅复制指定的数据库,要复制数据库的白名单;
      • replicate_ingore_db=:忽略复制指定的数据库,黑名单;
      • replicate_do_table=:表的白名单
      • replicate_ingore_table=:表的黑名单
      • replicate_wild_do_table=:使用通配符的表的白名单
      • replicate_wild_ingore_table=:使用通配符的表的黑名单

复制的监控和维护:

  • (1) 清理日志:PURGE
    PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFORE datetime_expr };
  • (2) 复制监控
    • MASTER:
      SHOW MASTER STATUS;
      SHOW BINLOG EVENTS;
      SHOW BINARY LOGS;
      -SLAVE:
      SHOW SLAVE STATUS;
      判断从服务器是否落后于主服务器的变量:Seconds_Behind_Master:0
  • (3) 如何确定主从节点数据是否一致?
    通过表的CHECKSUM检查;
    使用percona-tools中pt-table-checksum;
  • (4) 主从数据不一致时的修复方法?
    重新复制;选择一个认为比较完整的数据库,重新备份导入到从节点上;

推荐阅读更多精彩内容