mysql半同步复制与并行复制

####################################相关概念###################################################

(1)异步复制:主库上的事务不会等待从库的确认即返回客户端提交成功!

(2)同步复制:主库上提交的事务向客户端返回成功之前,需要收到所有从库提交事务的确认信息。

(3)半同步复制:异步复制和同步复制的折中,主库上提交事务时,需要等待至少一个从库发来的收到事件确认信息,才向客户端返回成功。

MySQL 5.5之前的复制都是异步的,主服务器在将更新操作写入二进制日志文件中后,不用管从服务器是否已经完成复制,就可以自由处理其它事务处理请求。异步复制 能提供较高的性能,但无疑易造成主/从服务器数据的不一致。MySQL 5.5开始引入半同步复制功能,此功能是由google开发的一个插件实现的。半同步复制要求主库提交的每一个事务,至少有一个备库成功接收后,才能继续 提交下一个。
半同步复制的概念详解:
       当slave主机连接到master时,能够查看其是否已开启半同步复制功能。
     当master上开启半同步复制的功能时,至少应该有一个slave开启此功能。此时,一个线程在master上提交事务将受到阻塞,直到得知一个已开启半同步复制功能的slave已收到此事务的所有事件,或等待超时。
   当一个事务的事件都已写入relay-log中且已刷新到磁盘,slave才会告知已收到。在 master实例上,有一个专门的线程(ack_receiver)接收备库的响应消息。
     如果等待超时,也就是master没被告知已收到,此时master会自动转换为异步复制模式。当至少一个半同步的slave赶上了,master与其slave自动转换为半同步复制。
      半同步复制的功能要在master,slave都开启,若只开启一边,它依然为异步复制。

半同步复制原理图:

mysql半同步复制与并行复制_第1张图片

###################################实验搭建######################################################

-安装前提

1、MySQL5.5 版本或更高

2、主、备库的 have_dynamic_loading 系统变量值为 yes

3、主、备异步复制已部署

步骤:

在master(主节点)上:

mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';   ##导入半同步master模块
Query OK, 0 rows affected (0.11 sec)

mysql> set global rpl_semi_sync_master_enabled=1;
Query OK, 0 rows affected (0.00 sec)
mysql>set global rpl_semi_sync_master_timeout=10000          # 10s
#备注: rpl_semi_sync_master_enabled 参数控制主节点是否开启半同步复制;rpl_semi_sync_master_timeout 参数控制主节点等待备
节点返回确认信息的超时时间,单位为毫秒,超过这个时间后半同步复制转变成异步复制,这里设置成 10 秒。

mysql> show variables like 'rpl%';
+-------------------------------------------+------------+
| 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_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
| rpl_stop_slave_timeout                    | 31536000   |
+-------------------------------------------+------------+
7 rows in set (0.00 sec)
mysql> show status like 'rpl%';
+--------------------------------------------+-------+
| 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     |   ###一共有几次从Semi-sync跌回普通状态
| 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     |   ###开启Semi-sync,事务返回需要等待的平均时间
| 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)

在slave(从节点)上:

mysql> select * from mysql.gtid_executed;
+--------------------------------------+----------------+--------------+
| source_uuid                          | interval_start | interval_end |
+--------------------------------------+----------------+--------------+
| 0e09c92a-8139-11e8-9d84-52540013d792 |              1 |            1 |
| 0e09c92a-8139-11e8-9d84-52540013d792 |              2 |            2 |
+--------------------------------------+----------------+--------------+
2 rows in set (0.00 sec)

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

mysql> show variables like 'rpl%';
+---------------------------------+----------+
| Variable_name                   | Value    |
+---------------------------------+----------+
| rpl_semi_sync_slave_enabled     | OFF      |
| rpl_semi_sync_slave_trace_level | 32       |
| rpl_stop_slave_timeout          | 31536000 |
+---------------------------------+----------+
3 rows in set (0.02 sec)

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

mysql> show variables like 'rpl%';
+---------------------------------+----------+
| Variable_name                   | Value    |
+---------------------------------+----------+
| rpl_semi_sync_slave_enabled     | ON       |
| rpl_semi_sync_slave_trace_level | 32       |
| rpl_stop_slave_timeout          | 31536000 |
+---------------------------------+----------+
3 rows in set (0.01 sec)

mysql> show status like 'rpl%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | OFF   |
+----------------------------+-------+
1 row in set (0.00 sec)

mysql> stop slave io_thread;    ##重新开启io线程,使它完全打开
Query OK, 0 rows affected (0.01 sec)

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

mysql> show status like 'rpl%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+
1 row in set (0.00 sec)

测试:

master机写入数据,并接收到slave机返回的ack值

mysql> insert into user.usertb values('chaokaidi','21');
Query OK, 1 row affected (0.26 sec)

mysql> show status like 'rpl%';
+--------------------------------------------+-------+
| 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             | 1     |
| 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      | 1372  |
| Rpl_semi_sync_master_tx_wait_time          | 1372  |
| 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                | 1     |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

将slave机的io线程停掉,master机写入数据,会默认等待10s,如果超时还未等到slave机的ack,将自动切换到异步复制,如果slave机的io线程再次开启,复制将自动切换到半同步方式。

slave机

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

 

master机

mysql> insert into user.usertb values('chao','22');
Query OK, 1 row affected (10.45 sec)

mysql> show status like 'rpl%';
+--------------------------------------------+-------+
| 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             | 1     |
| 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      | 1372  |
| Rpl_semi_sync_master_tx_wait_time          | 1372  |
| 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                | 1     |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

并行复制

先重复下MySQL复制原理,其通过三个线程来完成,在master节点上运行的binlogdump线程以及在slave节点上运行的I/O线程和SQL线程。具体如下:

1. master节点上的binlogdump线程,在slave与其正常连接的情况下,将binlog发送到slave上。

2.slave节点上的I/O线程,通过读取master节点发送的内容,并将数据复制到本地的relaylog中。

3.slave节点上的SQL线程,读取relaylog中的日志,并将其事务在本地执行。

Master节点的多个数据库并发进行事务提交,提交的事务根据LSN号顺序的写入binlog,slave节点通过I/O线程将master上的 binlog写到本地relaylog中,在slave节点只有一个SQL线程来执行relaylog中的日志,这样很容易造成slave延迟。在MySQL5.6中,引入了并发复制,这个并发复制是数据库级别的,这意味着一个SQL线程可以处理一个数据库的连续事务,而不用等待其它数据库完成。这个版本的并发复制,可以理解成一个数据库一个SQL线程。其与并发有关的参数如下:

slave_parallel_workers           // worker 线程个数

slave-checkpoint-group           // 隔多少个事务做一次 checkpoint

slave-checkpoint-period          // 隔多长时间做一次 checkpoint

slave-pending-jobs-size-max      // 分发给worker的、处于等待状态的event的大小上限

MySQL5.6基于DATABASE级别的并发复制可以解决业务表放在不同的database下同步延迟的问题,但是在实际生产中大部分表还是放 在同一个库中的,这种情况即使设置slave_parallel_workers大于0,也无法进行并发。在高并发的情况下,依然会造成主从复制延迟。在MySQL5.7中,引入了新的并发复制方法,基于LOGICAL_CLOCK的并发复制,可以支持在一个database中,并发执行relaylog中的事务。相同的二进制日志组在master上提交并行应用到slave节点上,没有跨数据库的限制,并且不需要把数据分割到多个数据库。要实现这个功能,需要在master节点标记binlog中提交的事务哪些是可以并发执行,虽然的MySQL5.6中已经引入binarylog group commit,但是没有将可并发的事务标记出来。

可以通过此命令来查看:mysqlbinlog-vvv mysql-bin.000106 | grep -i last_commit

在MySQL5.7中,已经解决了主从复制延迟的问题,具体配置参数如下:

slave-parallel-type=LOGICAL_CLOCK

slave-parallel-workers=16

master_info_repository=TABLE

relay_log_info_repository=TABLE

relay_log_recovery=ON

1、查看从库的sql类型

mysql> show processlist;
+----+-------------+-----------+------+---------+-------+--------------------------------------------------------+------------------+
| Id | User        | Host      | db   | Command | Time  | State                                                  | Info             |
+----+-------------+-----------+------+---------+-------+--------------------------------------------------------+------------------+
|  1 | system user |           | NULL | Connect | 52393 | Slave has read all relay log; waiting for more updates | NULL             |
|  2 | system user |           | NULL | Connect |   415 | Waiting for master to send event                       | NULL             |
|  7 | root        | localhost | NULL | Query   |     0 | starting                                               | show processlist |
+----+-------------+-----------+------+---------+-------+--------------------------------------------------------+------------------+
3 rows in set (0.00 sec)

 

2、slave机配置

[root@server2 ~]# vim /etc/my.cnf

slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16                  ##线程数
master_info_repository=TABLE               ##master_info存储方式为:table
relay_log_info_repository=TABLE            ##relay_log_info存储方式为:table
relay_log_recovery=ON

[root@server2 ~]# /etc/init.d/mysqld restart 
Stopping mysqld:                                           [  OK  ]
Starting mysqld:                                           [  OK  ]

 

3、登陆从库查看sql类型

mysql> show processlist;
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User        | Host      | db   | Command | Time | State                                                  | Info             |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
|  1 | system user |           | NULL | Connect |   86 | Slave has read all relay log; waiting for more updates | NULL             |
|  2 | system user |           | NULL | Connect |   87 | Waiting for master to send event                       | NULL             |
|  4 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
|  5 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
|  6 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
|  7 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
|  8 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
|  9 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
| 10 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
| 11 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
| 13 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
| 15 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
| 16 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
| 17 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
| 18 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
| 19 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
| 20 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
| 21 | system user |           | NULL | Connect |   87 | Waiting for an event from Coordinator                  | NULL             |
| 22 | root        | localhost | NULL | Query   |    0 | starting                                               | show processlist |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
19 rows in set (0.00 sec)

 

查看mysql的表,新增了下面两个表

mysql> use mysql;
mysql> show tables;
----------------------------
 slave_master_info         
 slave_relay_log_info 
----------------------------

你可能感兴趣的:(运维,linux)