为什么需要半同步复制
默认情况下,MySQL的复制功能是异步的,异步复制可以提供最佳的性能,主库把Binlog日志发送给从
库即结束,并不验证从库是否接收完毕。这意味着当主服务器或从服务器端发生故障时,有可能从服务
器没有接收到主服务器发送过来的binlog日志,这就会造成主服务器和从服务器的数据不一致,甚至在
恢复时造成数据的丢失
什么是半同步复制
在一主多从的环境下,如果一个从收到了来自主服务器的同步信息,那么立即返回给主,表示已同步完成;不需要等所有从都同步才返回信息,继而保障了主机异常宕机时,数据不会丢失,可提升为已完成备份的从服务器提升为主,保障服务的持续集成。如果主存活,slave全部宕机,主服务器写入数据后等待time超时时间过期后,就会返回成功信息,不同继续等待slave,如果slave再次上线,继而同步成功。
官方文档: https://mariadb.com/kb/en/library/semisynchronous-replication/
实验环境
OS | IP | Dabase | Type |
---|---|---|---|
centos7.6 | 192.168.146.97 | MariaDB5.5.6 | Master |
centos7.6 | 192.168.146.97 | MariaDB5.5.6 | Slave1 |
centos7.6 | 192.168.146.97 | MariaDB5.5.6 | Slave2 |
配置YUM仓库: 本示例采用阿里yum源
[root@97 /etc/yum.repos.d]#curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@97 /etc/yum.repos.d]#yum install mariadb-server -y
Master1配置
[root@97 /etc/yum.repos.d]#cat /etc/my.cnf.d/server.cnf
[mysqld]
server-id=97 #服务器ID
log-bin=myqsl-bin #二进制日志
log-error #错误日志
启动服务,并配置mariadbserver
[root@97 ~]# systemctl start mariadb
[root@97 ~]# mysql
先搭建三台机器的主从配置,后续接入半同步配置
Master
MariaDB [(none)]> grant replication slave on *.* to 'repluser'@'192.168.146.%' identified by 'replpasswd'; 创建可复制的用户
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> show master logs; #查看当前bin-log日志位置
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 30322 |
| mysql-bin.000002 | 1038814 |
| mysql-bin.000003 | 407 |
+------------------+-----------+
3 rows in set (0.00 sec)
slave1配置
[root@107 ~]#cat /etc/my.cnf
[mysqld]
server-id=107
log-error
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
[root@107 ~]#systemctl start mariadb
[root@107 ~]#mysql
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.146.97', MASTER_USER='repluser', MASTER_PASSWORD='replpasswd', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=407;
Query OK, 0 rows affected (0.01 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.146.97
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 407
Relay_Log_File: mariadb-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: 407
Relay_Log_Space: 825
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: 97
1 row in set (0.00 sec)
测试
Master创建db1测试
MariaDB [(none)]> create database db1;
Query OK, 1 row affected (0.00 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.00 sec)
slave查看
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 | #至此主从已完成
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.01 sec)
半同步设置
Master
MariaDB [(none)]> INSTALL SONAME 'semisync_master'; #安装master插件,无须重启
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> SET GLOBAL rpl_semi_sync_master_enabled=ON; #开启master_sync
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> SET GLOBAL rpl_semi_sync_master_timeout = 1000; #设置超时时长为1s
Query OK, 0 rows affected (0.000 sec)
MariaDB [(none)]> 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_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_COMMIT |
| rpl_semi_sync_slave_delay_master | OFF |
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_kill_conn_timeout | 5 |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------------+--------------+
9 rows in set (0.001 sec)
MariaDB [(none)]> SHOW GLOBAL STATUS LIKE '%semi%'; #查看当前状态信息
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 | #此时虽然master插件已就绪,还没有slave就绪
| Rpl_semi_sync_master_get_ack | 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_request_ack | 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 |
| Rpl_semi_sync_slave_send_ack | 0 |
| Rpl_semi_sync_slave_status | OFF |
+--------------------------------------------+-------+
18 rows in set (0.001 sec)
slave1.2设置
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; #安装从插件
Query OK, 0 rows affected (0.01 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)]> SHOW GLOBAL STATUS LIKE '%semi%'; #此时发现slave是关闭的
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | OFF |
+----------------------------+-------+
1 row in set (0.01 sec)
MariaDB [(none)]> STOP SLAVE IO_THREAD; #重启线程
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> START SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> SHOW GLOBAL STATUS LIKE '%semi%'; #插件开启
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
1 row in set (0.00 sec)
master上查看slave插件线程是否启动且同步到了master
MariaDB [(none)]> SHOW GLOBAL STATUS LIKE '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 2 | #此时检测到两个线程已连接,配置成功
| 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)
测试半同步
#在master实现,创建数据库,立即成功
MariaDB [(none)]> create database db2;
Query OK, 1 row affected (1.00 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db2 |
| mysql |
| performance_schema |
| test |
+--------------------+
6 rows in set (0.00 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db2 |
| mysql |
| performance_schema |
| test |
+--------------------+
7 rows in set (0.00 sec)
#在所有slave节点实现,停止复制线程
MariaDB [(none)]> stop slave;
Query OK, 0 rows affected (0.011 sec)
#在master实现,创建数据库,等待3s才能成功
MariaDB [(none)]> create database db3
Query OK, 1 row affected (1.00 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db2 |
| db3 |
| mysql |
| performance_schema |
| test |
+--------------------+
6 rows in set (0.00 sec)
此时slave上没有同步信息,因为线程已关闭
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db2 |
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.00 sec)
#在任意一个slave节点实现,恢复复制线程
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.006 sec)
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| db1 |
| db2 |
| db3 | #数据马上同步成功
| mysql |
| performance_schema |
| test |
+--------------------+
6 rows in set (0.00 sec)