目录结构:

  1. 神马是半同步,同步,异步。

  2. 查看系统是否支持半同步。

  3. 加载半同步插件。

  4. 启动半同步。

  5. 查看半同步状态与测试。

  6. 多个slave,半同步。

  7. 半同步主从切换。

  8. 更换slave到新的master节点。

  9. 原Master恢复,加入新master节点。

  10. GTID双主半同步构建。


Mysql在5.5版本引入了半同步的概念,在这里也普及一些基础知识。


一:神马是半同步,同步,异步。

1:Mysql的复制过程就是slave去master拉日志回来,存到relay文件中,然后执行。

2:Master根本不考虑数据是否达到了slave,或者slave是否执行成功了。

3:默认情况下mysql主从复制就是异步的方式,别看好像数据刚被创建,slve就可以看到了,因为你的数据量太小了,无法感受到异步的现象。

4:同步就是两边信息都完全一样,master确认了slvae数据复制并执行成功,才叫同步。


我们举个生产例子说明一下这件事。

生产中是否做过数据库读写分离?不管什么数据库,读写分离就是为了减轻数据库压力,假设我们有2台服务器,A是写入库,B是读库。用户注册了你网站的会员,注册的时候,是通过A库写入, 登录的时候是同步B服务器,对吧?


异步:

注册写到A库,应用前端直接返回注册成功,然后B库才到A库拉取新数据,在本地执行同步。如果由于网络,数据量等原因,B库还没有执行新数据,新用户就点击登录窗口,这个时候,应用前端就提示该用户尚未注册。。蛋疼了吧??


同步情况:

注册写到A库,A库要把信息同步到B库,确定B库执行成功后,返回信息给前端,这个时候应用前端才显示注册成功。用户在注册后登录就不会出现异常了。这才符合逻辑吧?Mysql主从复制中,主库根本不去考虑从库是否把信息拷贝过去,或者成功执行了。


半同步又是什么概念??

如果按mysql主从复制原理看,slave到master把数据垃取下来,然后执行,执行完后,把状态返回给master,这个时候应用程序才给客户端响应成功,这种延迟,用户都接受吗?找一个折中的方法:Mysql半同步在5.5版本横空出世。


半同步情况:
   一主一从,一主多从情况下,Master节点只要确认至少有一个slave接受到了事务,即可向发起请求的客户端返回执行成功的操作,master节点是不需要等待slave节点成功执行完这个事务。slave节点接受到这个事务,并成功写入到本地relay日志中,就算是成功了。
  半同步在数据完成性上得到了保障,起码主从架构中,有一个备份集,当然,这也不是说半同步配置成功,就不会丢失数据,都是有可能的,如sql执行错误,半同步失效,默认会自动转换成异步的方式,如果没有得到及时修复,将造成数据丢失。半同步有利有弊,势必会增加了成本开销,对数据库性能带来一定的影响,开源的就是这样。不然为什么Oracle要收费。哈哈。。


实验基础环境,可以参考之前发布的博客日志。《Mysql-Gtid主从复制》

http://jiajinh.blog.51cto.com/2085098/1632321



二:查看系统是否支持半同步

查看是否加载半同步插件。

sql> show plugins;

查找是否有semisync字母。如果没有跟着步骤走。


步骤1:查找mysql插件目录位置。

sql>show variables like 'plugin_dir';

+---------------+--------------------------------+
| Variable_name | Value                 |
+---------------+--------------------------------+
| plugin_dir   | /usr/local/mysql56/lib/plugin/ |
+---------------+--------------------------------+

步骤2:查看目录文件是否存在。

$ll /usr/local/mysql56/lib/plugin/

wKioL1UwvhvhhX5hAAKTxQA-wHk577.jpg

我们可以发现有2个文件,一个是master.so 一个是slave.so,在主服务器加载master文件,在从服务器加载slave文件就可以。


实验环境描述:我们接着上一章的Mysql-Gtid复制。

A:192.168.112.131

B:192.168.112.132 (主Master)

C:192.168.112.129


三:加载半同步插件。

主服务器:192.168.112.132

sql> install plugin rpl_semi_sync_master soname 'semisync_master.so';

查看是否加载插件

sql> show plugins;

rpl_semi_sync_master   | ACTIVE  | REPLICATION     | semisync_master.so | GPL


从服务器:192.168.112.129

sql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';


查看是否加载插件

sql> show plugins;

rpl_semi_sync_slave    | ACTIVE  | REPLICATION    | semisync_slave.so | GPL  



四:启动半同步插件。

Master:启用插件

(192.168.112.132)

sql>set global rpl_semi_sync_master_enabled = on;


Slave:启动半同步,slave要重启动IO线程,否则还是异步的方式同步数据。

(192.168.112.129)

sql>set global rpl_semi_sync_slave_enabled = on;

sql>stop slave IO_THREAD;

sql>start slave IO_THREAD;



五:查看半同步的状态。

1:在master中查看,slave是没有这几个信息的。

sql>show status like '%Rpl_semi_sync%';

wKiom1Uwva6jwzBYAAJs6WoPh8o881.jpg

解释几个重要的值。

Rpl_semi_sync_master_status是否启用了半同步。
Rpl_semi_sync_master_clients半同步模式下Slave一共有多少个。
Rpl_semi_sync_master_no_tx往slave发送失败的事务数量。
Rpl_semi_sync_master_yes_tx往slave发送成功的事务数量。



2:半同步几个参数设置

sql>show variables like '%Rpl%';

wKiom1UwvcujiWQhAAFC5VMJDCQ157.jpg

注释:

rpl_semi_sync_master_timeoutMaster等待slave响应的时间,单位是毫秒,默认值是10秒,超过这个时间,slave无响应,环境架构将自动转换为异步复制
rpl_semi_sync_master_trace_level监控等级,一共4个等级(1,16,32,64),后续补充详细。
rpl_semi_sync_master_wait_no_slave是否允许master 每个事物提交后都要等待slave的receipt信号。默认为on ,每一个事务都会等待,如果slave当掉后,当slave追赶上master的日志时,可以自动的切换为半同步方式,如果为off,则slave追赶上后,也不会采用半同步的方式复制了,需要手工配置。
rpl_stop_slave_timeout

控制stop slave 的执行时间,在重放一个大的事务的时候,突然执行stop slave ,命令 stop slave会执行很久,这个时候可能产生死锁或阻塞,严重影响性能,mysql 5.6可以通过rpl_stop_slave_timeout参数控制stop slave 的执行时间




3:半同步数据测试

Master添加数据

sql>create table t20(id int);

查看状态

sql>show status like '%Rpl_semi_sync%';

wKiom1Uwvg2x-cUAAALN8D0x4P8421.jpg

Rpl_semi_sync_master_no_tx: 0

Rpl_semi_sync_master_yes_tx: 1

可以看到执行成功,并返回了状态。




六:多个slave,半同步。

将C节点加入半同步。IP:192.168.112.129

1:加载激活C-slave节点服务器。

这四个步骤直接执行即可。前提是C节点是和B节点建立了GTID复制的环境。

sql>install plugin rpl_semi_sync_slave soname 'semisync_slave.so';

sql>set global rpl_semi_sync_slave_enabled = on;

sql>stop slave IO_THREAD;

sql>start slave IO_THREAD;



2:在B主服务器查看状态。

sql> show status like '%Rpl_semi_sync%';

wKioL1Uwv4eCnZMdAAKDdfsv_bw089.jpg

Rpl_semi_sync_master_clients:2  可以看到,节点的数量已经是两个了。



3:继续测试数据。

sql>create table t21(id int);

sql>show status like '%Rpl_semi_sync%';

wKiom1Uwvn3T7bYhAAMCk4Ex-wM830.jpg

Rpl_semi_sync_master_no_tx: 0

Rpl_semi_sync_master_yes_tx: 2

可以看到执行成功,并返回了状态。状态是2不是3,符合了理论值,半同步值确保有一台服务器接受到了数据。




七:半同步主从切换。

A:192.168.112.131(新Master)

B:192.168.112.132(Master)

C:192.168.112.129



考虑每个服务器都可能成为主服务器,所以都需要加载master主从插件,不激活就行了。

1:在主服务器加载半同步slave插件。

sql>install plugin rpl_semi_sync_slave soname 'semisync_slave.so';


2:在从服务器加载半同步master插件。

sql>install plugin rpl_semi_sync_master soname 'semisync_master.so';



描述:模拟master宕机,A服务器接管服务。

3:模拟一下环境,先把C服务器的slave服务关闭。

标准的关闭slave方式,生产中,确保把已复制到relay的日志文件执行了。

sql>stop slave io_thread;

sql>stop slave;




4:B主manster服务器添加新数据。

sql>create table t22(id int);

sql>create table t23(id int);

sql>create table t24(id int);



5:B主master服务器关闭mysql服务。

$sh mysql_shutdown.sh

wKioL1U0-7TA-TssAADogpZLvII107.jpg




6:A服务器关闭slave服务,切换主数据库模式。

sql>stop slave io_thread;

sql>stop slave;

启动主库半同步插件。

sql>set global rpl_semi_sync_master_enabled = on;

sql>show status like '%Rpl_semi_sync%';

wKiom1Uwvs7BdOiiAAKJX14HcFg511.jpg

Rpl_semi_sync_master_clients:1 可以看到目前还没有新的slave连接自己。 




八:更换slave到新的Master节点。

C节点加入新master服务器。

1:C节点连接新master服务器。

sql>change master to master_host='192.168.112.131', master_user='ruser',master_password='rpass',master_auto_position=1;



2:新master添加新数据。(192.168.112.131)

sql>create table t25(id int);

sql>create table t26(id int);

sql>create table t27(id int);



3:C节点启动slave服务,查看C节点slave状态。

sql>start slave;

sql>show slave status\G

wKioL1UwwECC1zBsAAQXJOWxNEo990.jpg



4:A节点查看主从复制状态。

sql>show status like '%Rpl_semi_sync%';

wKiom1Uwvwyhj4a2AAIEbojohlg993.jpg

Rpl_semi_sync_master_clients 1: 一个从节点

Rpl_semi_sync_master_no_tx  0: 没有错误

Rpl_semi_sync_master_yes_tx 3: 成功3次事务



九:原Master恢复,加入新master-A。

1:启动mysql服务

$sh mysql_startup.sh 



2:与新master节点建立主从连接,启动slve服务。

先关闭slave服务

sql>stop slave;

sql>change master to master_host='192.168.112.131', master_user='ruser',master_password='rpass',master_auto_position=1;

sql>start slave;



3:查看主从复制状态(此刻是异步复制)

sql>start slave;

wKiom1Uwv33CrPChAANnxFlu2m8884.jpg



4:检查数据表是否成功同步。

sql>use testhuang

sql>show tables;

wKiom1Uwv5XAo9ZuAADXJSadD10680.jpg



4:启动半同步。

sql>set global rpl_semi_sync_slave_enabled = on;

sql>stop slave IO_THREAD;

sql>start slave IO_THREAD;



5:主数据库查看状态。

sql>show status like '%Rpl_semi_sync%';

wKiom1Uwv9qAW4imAAIl-9CrO-g934.jpg

发现clients现在的值是2.



6:测试,主服务器添加数据测试。

省略.....................




十:GTID双主半同步。

A:192.168.112.131(Master)

B:192.168.112.132(Master)

C:192.168.112.129 (Slave)


开启双主比较简单,只需要在A服务器开启slave服务即可。

A:192.168.112.131

1:开启slave服务。

sql>start slave;

wKioL1U0-myB2sjxAABOsFVTwKA701.jpg



2:查看slave状态

sql>show slave status\G

wKiom1U0-SGCb8s0AAOT36cV3Ms070.jpg

我们看到是没有任何异常现象的。



3:B服务器添加新数据。

192.168.112.132

sql>create table t31(id int);

sql>show status like '%Rpl_semi_sync%';

wKiom1U0-Uug9mZsAAJBGNHXlDA043.jpg

这里是否发现,B服务器的半同步没有没有启动。之前不是启动过吗?因为重启动了B服务器的Mysql服务器,有心的朋友都会发现,我们并没有将半同步配置加入my.cnf文件中,所以失效了。。开启一下。



4:B服务器开启半同步

sql>set global rpl_semi_sync_master_enabled = on;

sql>create table t32(id int);

sql>show status like '%Rpl_semi_sync%';

wKioL1U0-rjB57zBAAMzRFqTT34183.jpg

这个时候是否发现,半同步也启用了,client的值只有1个,双主模式正式完成。是不是比之前的主从复制简单多了。



5:可以回头看A服务器的同步状态。

192.168.112.131

sql>show tables;  #查看表是否创建。

wKioL1U0-tnQ37j6AAERinoPMmU463.jpg

可以看到表t31,t32


sql>show slave status\G #查看GTID是否正确

wKioL1U0-vTRTPOFAAG3KnIyGow799.jpg可以看到执行了GTID到 13 了,,刚好两个事务。



6:在A服务器创建新数据,查看主从状态。

A:192.168.112.131

sql>create table t33(id int);

wKiom1U0-bvxo-t_AAL-G9SHp6c892.jpg

我们可以发现,A服务器的client值等于2,因为A服务器有2个从,一个是互为双主的B,一个是slave-C。



7:再次查看A服务器的slave状态。

192.168.112.131

sql>show slave status\G

wKioL1U0-zCiauZ8AAH45VPtGog855.jpg

Retrieved_Gtid_Set: 7d055966-e1bf-11e4-8842-000c2976947c:1-13
Executed_Gtid_Set: 7d055966-e1bf-11e4-8842-000c2976947c:1-13,7edc6fd5-e1bf-11e4-8842-000c29e512d6:1-25

参数值分析:

Retrieved_Gtid_Set,读取主服务器B的事务位置。

Executed_Gtid_Set,这里有两个值,当在本地创建了t33表,我们发现,前面的7d055966-e1bf-11e4-8842-000c2976947c值并没有发生任何变化,7edc6fd5-e1bf-11e4-8842-000c29e512d6由1-24变成1-25。

可以看到,基于GTID复制,思路很清晰。一个是本地的UUID,一个是远程服务器的UUID值。这也是为什么会同时出现两个原因。

如果一个从服务器更换过N个主服务器,那么这个UUID也将会有多个,用","号隔开,这也符合了GTID事务的唯一性。