Mysql并行复制,半同步

并行复制的原理

在普通的主从复制架构中,slave服务器上有两个线程:IO线程和SQL线程。IO线程负责接收master的二进制日志(准确的说是二进制日志的event),SQL线程负责应用二进制日志(准确的说是relay-log)。

在MySQL5.6版本中的并行复制中(需开启并行复制功能),SQL线程变为coordinator线程,判断是否可以并发执行:

  • 如可以并行执行,选择worker线程执行二进制日志
  • 如不可并行执行,是DDL或是跨schema的操作,则等待所有的worker线程执行完成之后再执行当前日志

coordinator线程不仅仅可以将日志发送给worker线程,也可以回放日志,但是并行的操作都会交给worker线程来完成。

 

server6(slave)上:

[[email protected] ~]# mysql -p

mysql> show processlist;

Mysql并行复制,半同步

修改配置文件:

[[email protected] ~]# vim /etc/my.cnf

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

Mysql并行复制,半同步

[[email protected] ~]# /etc/init.d/mysqld restart

mysql> show processlist;

Mysql并行复制,半同步

 

Mysql半同步

  1. 正常的复制为:事务一(t1) 写入binlog buffer;dumper 线程通知slave有新的事务t1;binlog buffer 进行checkpoint;slave的io线程接收到t1并写入到自己的的relay log;slave的sql线程写入到本地数据库。 这时,master和slave都能看到这条新的事务,即使master挂了,slave可以提升为新的master。
  2. 异 常的复制为:事务一(t1)写入binlog buffer;dumper 线程通知slave有新的事务t1;binlog buffer 进行checkpoint;slave因为网络不稳定,一直没有收到t1;master 挂掉,slave提升为新的master,t1丢失。
  3. 很大的问题是:主机和从机事务更新的不同步,就算是没有网络或者其他系统的异常,当业务并发上来时,slave因为要顺序执行master批量事务,导致很大的延迟。

为了弥补以上几种场景的不足,mysql从5.5开始推出了半同步。即在master的dumper线程通知slave后,增加了一个ack,即是否成功 收到t1的标志码。也就是dumper线程除了发送t1到slave,还承担了接收slave的ack工作。如果出现异常,没有收到ack,那么将自动降 级为普通的复制,直到异常修复。

主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所 以,半同步复制最好在低延时的网络中使用。

 

1.主库端加载mater模块(server5)

mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';       在master上安装这个插件

(--删除插件的方法 mysql > uninstall plugin rpl_semi_sync_master;)

mysql> set global rpl_semi_sync_master_enabled=ON;              #**半同步复制

--安装OK后,主上会多几个参数

mysql> show variables like '%semi%';                         ##环境变量

 rpl_semi_sync_master_enabled               ON                   #表示半同步开启

 rpl_semi_sync_master_timeout              | 10000      |             #默认主等待从返回信息的超时间时间,10秒

 rpl_semi_sync_master_trace_level          | 32         |              #监控

 rpl_semi_sync_master_wait_no_slave        | ON         |       # 是否允许每个事物的提交都要等待slave的信号.on为每一 个事物都等待

Mysql并行复制,半同步


2.server6上安装插件(slave)

mysql> stop slave;

mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';            #安装slave插件

mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';        #安装master插件

mysql> set global rpl_semi_sync_master_enabled=ON;      #**半同步       

mysql> set global rpl_semi_sync_slave_enabled=ON;        

mysql> show variables like '%semi%';             #查看状态

Mysql并行复制,半同步

mysql> start slave;

mysql> stop slave io_thread;          #关闭IO线程

mysql> start slave io_thread;           #开启IO线程

mysql> show status like '%rpl_semi_sync%';

Mysql并行复制,半同步

3.在master查看状态

mysql> show status like '%rpl_semi_sync%';

Mysql并行复制,半同步

| Rpl_semi_sync_master_clients               | 1     |              --有一个从服务器启用半同步复制

| Rpl_semi_sync_master_net_avg_wait_time     | 0     |  --master等待slave回复的平均等待时间。单位毫秒

 | Rpl_semi_sync_master_net_wait_time         | 0     |  --master总的等待时间。单位毫秒

| Rpl_semi_sync_master_net_waits             | 0     |  --master等待slave回复的总的等待次数

| Rpl_semi_sync_master_no_times              | 0     |  --master关闭半同步复制的次数

| Rpl_semi_sync_master_no_tx                 | 0     |  --master 等待超时的次数

| Rpl_semi_sync_master_status                | ON    |  --标记master现在是否是半同步复制状态

| Rpl_semi_sync_master_timefunc_failures     | 0     |  --master调用时间(如gettimeofday())失败的次数

 | Rpl_semi_sync_master_tx_avg_wait_time      | 0     |  --master花在每个事务上的平均等待时间

| Rpl_semi_sync_master_tx_wait_time          | 0     |  --master花在事物上总的等待时间

| Rpl_semi_sync_master_tx_waits              | 0     |  --master事物等待次数

| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |  --后来的先到了,而先来的还没有到的次数

 | Rpl_semi_sync_master_wait_sessions         | 0     |  --当前有多少个session因为slave回复而造成等待

| Rpl_semi_sync_master_yes_tx                | 0     |  --标记slave是否在半同步状态

 

4.测试

1)master上:

mysql> show databases;

mysql> use westos;

mysql> insert into usertable values('user3','222');

mysql> show global status like 'rpl_semi_sync%_yes_tx';

Mysql并行复制,半同步

Rpl_semi_sync_master_yes_tx | 1     |     --表示这次 事物成功从slave返回一次确认信号

 

2)模拟错误,把slave上的IO线程停掉!

mysql> stop slave io_thread;          (slave上)

再回到master上测试

mysql> insert into usertable values('user4','777');

Mysql并行复制,半同步

--这次插入一个值需要等待10秒(默认的等待时间)!

 

再把slave上的IO线程开启,查看数据发现刚才slave关闭期间的那几条数据还是会自动复制过来,数据又回到一致

mysql> start slave io_thread;

mysql> select * from westos.usertable;

Mysql并行复制,半同步

 如果是把slave上的mysql停掉,再次把slave启动,看到半同步复制没启来,是异步模式,需要重新把同步模式再启起来就可以了.