首页 > 其他分享 >复制3- 半同步复制

复制3- 半同步复制

时间:2023-05-31 23:45:30浏览次数:42  
标签:同步 semi sync 复制 master NULL rpl

一. loss less semi-sync replication

之前测试的复制,都是异步复制,Master并不关心数据是否被Slave节点所获得,所以复制效率很高,但是数据有可能会丢失。
从MySQL5.5开始,MySQL推出了semi-sync replication(半同步复制)

  • 至少有一个Slave节点收到binlog后再返回(IO线程接收到即可)
  • 减少数据丢失风险
  • 不能完全避免数据丢失
  • 超时后,切换回异步复制

从MySQL5.7开始,MySQL推出了lossless semi-sync replication(无损复制)

  • 二进制日志(binlog)先写远程(IO线程接收到即可)
  • 可保证数据完全不丢失

 

1.1. loss less / semi-sync replication插件安装
1.1.1. 方式一:手工安装
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
1.1.2. 方式二:写入配置文件
[mysqld]
plugin_dir=/usr/local/mysql/lib/plugin
plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"

 

上述操作仅仅是加载了插件,还未启动对应的功能,需要配置以下参数:

[mysqld]
# 等同于rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_master_enabled = 1
# 等同于rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
# 超时5秒后,则切换回异步方式
loose_rpl_semi_sync_master_timeout = 5000

 

使用 loose_ 前缀表示如果没有加载 semi_sync 的插件,则忽略该参数
当Slave在Timeout后,又追上了Master了(IO线程),则会自动切换回半同步复制
注意:半同步复制/ 无损复制在主从上都要安装插件和开启功能

 

1.2. semi-sync replication

semi-sync replication称为半同步复制,在一个事物提交(commit)的过程时,在 InnoDB层的commit log步骤后,Master节点需要收到至少一个Slave节点回复的 ACK(表示收到了binlog)后,才能继续下一个事物;

如果在一定时间内(Timeout)内没有收到ACK,则切换为异步模式,具体流程如下:

对应的配置参数如下:

[mysqld]
# 开启主的半同步复制
rpl_semi_sync_master_enabled=1
# 开启从的半同步复制
rpl_semi_sync_slave_enabled=1
# 超时1秒,切回异步
rpl_semi_sync_master_timeout=1000
# 至少收到1 个slave发回的ack
rpl_semi_sync_master_wait_for_slave_count=1

 

1.3 loss less semi-sync replication

loss less semi-sync replication称为无损复制,在一个事物提交(commit)的过程中,在MySQL层的write binlog步骤后,Master节点需要收到至少一个Slave节点回复的ACK(表示收到了binlog)后,才能继续下一个事物;
如果在一定时间内(Timeout)内没有收到ACK,则切换为异步模式,具体流程如下

对应的配置参数如下:

[mysqld]
# 开启主的半同步复制
rpl_semi_sync_master_enabled=1
# 开启从的半同步复制
rpl_semi_sync_slave_enabled=1
# 超时1秒,切回异步
rpl_semi_sync_master_timeout=1000
[mysqld57]
# 控制 半同步复制 还是 无损复制 的参数
# - AFTER_SYNC 表示的是无损复制;(5.7 默认)
# - AFTER_COMMIT 表示的是半同步复制;
rpl_semi_sync_master_wait_point=AFTER_SYNC
# 至少收到1 个slave发回的ack
rpl_semi_sync_master_wait_for_slave_count=1

 

1.4. 两种复制方式的对比
  • 等待ACK的 时间点 不同
    • semi-sync replication (半同步复制)在InnoDB层的Commit Log后 (第三步),等待ACK
    • loss less semi-sync replication(无损复制)在MySQL层的Write binlog后(第二步),等待ACK
  • 主机宕机后主从数据一致性的不同

假设主从复制时产生异常(比如Master宕机了),Master的binlog还没有传递到Slave上,此时两种复制方式,在主从数据一致性上的表现是不一样的(其实都是主有从没有)。

    • semi-sync replication(半同步复制)在commit完成后,才传输binlog,意味着在Master节点上,这个刚刚提交的事物对数据库的修改,对其他事物是可见的(即在Master上该事物已经提交了),假如此时Master宕机了,且发生主从切换,此时的Slave提升为New Master,但是此时的New Master上是没有之前提交的事物的内容的,这样就产生了主从数据的不一致。
      • 对App而言,之前读取到的内容,现在读取不到了;
    • loss less semi-sync replication(无损复制)在write binlog完成后,就传输binlog,但还没有去写commit log,意味着当前这个事物对数据库的修改,其他事物也是不可见的(即在Master上还没有提交),假如此时Master宕机了,且发生了主从切换,此时的Slave提升为New Master,由于Master上对该事物还没有提交,且此时的 New Master 上同样也没有该事物的内容,此时主从的数据是一致的。
      • 如果此时Slave提升为New Master,且原来的Master又恢复了,需要让原来的Master不要提交宕机前的那个事物。
      • 使用Flashback,人工介入,进行人工回滚,因为宕机的那一刻提交的事物,用户是不知道是否成功的,我们可以让他成功,也可以让他回滚。

举例来说,记录row=1修改为row=2

  1. semi-sync replication (半同步复制)模式下,Master上的row=1改成row=2,且commit成功,此时其他事物是可以读到row=2的;若此时binlog还没来得及传给Slave,Master就宕机了,那在Slave上记录还是row=1;发生主从切换后,App读取到的内容是前后是 不一致的;
  2. loss less semi-sync replication(无损复制)模式下,Master上的row=1改成row=2,但是还没有commit完成(仅到第二步),此时其他事物读取到的记录仍为row=1;若此时binlog还没来得及传给Slave,Master就宕机了,但是在Slave上记录也还是row=1; 发生主从切换后,App读取到的内容前后是 一致的;
  • 当主机恢复后,且主从还未切换,则在两种复制模式下,主从的数据都是最终一致的(配置是crash_safe的)

在数据一致性要求较高的场合,比如金融行业(可靠性要求大于可用性需求),则可以把参数rpl_semi_sync_master_timeout设置的很大,不让他切成异步;此时Master节点会hang住,然后需要人工介入。

 

1.5. 查看无损/ 半同步复制状态
root@mysqldb 10:37:  [(none)]> show variables like '%rpl%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |  -- status正常
| rpl_semi_sync_master_timeout              | 3000       |
| 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_semi_sync_slave_enabled               | ON         |  -- status正常
| rpl_semi_sync_slave_trace_level           | 32         |
| rpl_stop_slave_timeout                    | 31536000   |
+-------------------------------------------+------------+
9 rows in set (0.06 sec)

 

1.6. 两种复制方式的性能

  • 蓝色的Normal Slave是异步复制
    • 性能很好,但是随着并发数的增长,性能有所下降
  • 绿色的Enhanced mysqlbinlog是无损复制
    • 随着并发数的增长,性能几乎是线性增长的,在高并发下,性能会优于异步复制
  • 紫色的Normal Semi Slave是半同步复制
    • 性能较低

无损复制性能优于半同步复制的原因

  • 就等待ACK回包问题上,其实两种复制的开销是一样的,没有区别,都是网络的等待开销。
  • 无损复制由于在 write binlog (commit 的第二步)后,需要等待ACK,后续的事物无法提交,这样就堆积了很多需要落盘的事物(半同步复制由于已经提交了事物,没有堆积事物的效果),通过组提交机制,一次 fsync 的事物变多了(半同步复制也有组提交,只是一次fsync 的事物数没那么多), 相当于提高了I/O性能 。所以线程(事物)越多,效果越明显,以至于有上图中超过异步复制的效果。(无损复制的组提交比例比原版的高3~4倍)

产生上述测试效果的前提:测试用例是 IO Bound 的(比如数据量有100G,而buffer pool 只有10G),且并发数足够多。

 

下面这两个参数不要去设置,设置了反而性能差

root@mysqldb 10:37:  [(none)]> show variables like '%binlog_group%';
+-----------------------------------------+-------+
| Variable_name                           | Value |
+-----------------------------------------+-------+
| binlog_group_commit_sync_delay          | 0     |  -- 等待多少秒才提交
| binlog_group_commit_sync_no_delay_count | 0     |  -- 等待一组里面有多少事物我才提交
+-----------------------------------------+-------+
2 rows in set (0.00 sec)

 

1.7. rpl_semi_sync_master_wait_for_slave_count

该参数控制Master在收到多少个Slave的 ACK 后,才可以继续commit。配置多个ACK和配置一个ACK的效果是类似的,因为他们是并行执行的(理论上来说不会有两倍的等待时间),取决于最慢的那个 。

 

二. 并行复制(Multi-Threaded Slave)(姜老师的博客– MYSQL 5.7 并行复制实现原理与调优)

2.1 介绍

在官方文档中,并行复制的叫法为 Multi-Threaded Slave (MTS)

MySQL的并行复制基于组提交:一个组提交中的事务都是可以并行执行的,因为既然处于组提交中,这意味着事务之间没有冲突(不会去更新同一行数据),否则不可能在同一个组里面。

Slave上开启并行复制,需要在配置文件中增加以下参数:

[mysqld]
# DATABASE -- 基于库级别的并行复制,如果只有一个库,就还是串行(为了兼容5.6)。
# LOGICAL_CLOCK -- 逻辑时钟,主上怎么并行执行的,
#  从上也是怎么并行回放的。
slave-parallel-type=LOGICAL_CLOCK
# 并行复制的线程数,一般设置为一个组内提交的事物数,线上设置为32足够了
slave-parallel-workers=4
# Slave上commit的顺序保持一致,必须为1,否则可能会有GAP锁产生
slave_preserve_commit_order=1  # 这个参数的含义未知

 

2.2. 动态调整复制线程数

配置并行复制后,Slave节点上的效果如下,可以看到4个Coordinator线程

root@mysqldb 10:38:  [(none)]> show processlist;
+----+-----------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User            | Host      | db   | Command | Time | State                                                  | Info             |
+----+-----------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
|  1 | system user     |           | NULL | Connect | 2684 | Waiting for master to send event                       | NULL             |
|  2 | system user     |           | NULL | Connect | 2684 | Slave has read all relay log; waiting for more updates | NULL             |
|  3 | system user     |           | NULL | Connect | 2684 | Waiting for an event from Coordinator                  | NULL             |
|  4 | system user     |           | NULL | Connect | 2684 | Waiting for an event from Coordinator                  | NULL             |
|  5 | system user     |           | NULL | Connect | 2684 | Waiting for an event from Coordinator                  | NULL             |
|  6 | system user     |           | NULL | Connect | 2684 | Waiting for an event from Coordinator                  | NULL             |
|  7 | event_scheduler | localhost | NULL | Daemon  | 2683 | Waiting on empty queue                                 | NULL             |
|  9 | root            | localhost | NULL | Query   |    0 | starting                                               | show processlist |
+----+-----------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
8 rows in set (0.04 sec)

 

动态调整方式如下:

root@mysqldb 10:53:  [(none)]> set global slave_parallel_workers=8;
Query OK, 0 rows affected (0.01 sec)

root@mysqldb 10:54:  [(none)]> stop slave;
Query OK, 0 rows affected (0.47 sec)

root@mysqldb 10:54:  [(none)]> start slave;
Query OK, 0 rows affected (0.20 sec)

root@mysqldb 10:55:  [(none)]> show processlist;
+----+-----------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User            | Host      | db   | Command | Time | State                                                  | Info             |
+----+-----------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
|  7 | event_scheduler | localhost | NULL | Daemon  | 2813 | Waiting on empty queue                                 | NULL             |
|  9 | root            | localhost | NULL | Query   |    0 | starting                                               | show processlist |
| 10 | system user     |           | NULL | Connect |   12 | Waiting for master to send event                       | NULL             |
| 11 | system user     |           | NULL | Connect |   11 | Slave has read all relay log; waiting for more updates | NULL             |
| 12 | system user     |           | NULL | Connect |   12 | Waiting for an event from Coordinator                  | NULL             |
| 13 | system user     |           | NULL | Connect |   12 | Waiting for an event from Coordinator                  | NULL             |
| 14 | system user     |           | NULL | Connect |   12 | Waiting for an event from Coordinator                  | NULL             |
| 15 | system user     |           | NULL | Connect |   12 | Waiting for an event from Coordinator                  | NULL             |
| 16 | system user     |           | NULL | Connect |   12 | Waiting for an event from Coordinator                  | NULL             |
| 17 | system user     |           | NULL | Connect |   12 | Waiting for an event from Coordinator                  | NULL             |
| 18 | system user     |           | NULL | Connect |   12 | Waiting for an event from Coordinator                  | NULL             |
| 19 | system user     |           | NULL | Connect |   12 | Waiting for an event from Coordinator                  | NULL             |
+----+-----------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
12 rows in set (0.00 sec)
  1. 特别注意:这里的并行复制指的是 SQL Thread (回放线程),而非IO Thread(IO线程)
  2. Waiting for master to send event 这个 State 在 show processlist 中只有一个,即只有一个 IO Thread 

标签:同步,semi,sync,复制,master,NULL,rpl
From: https://www.cnblogs.com/gavin-zheng/p/17444864.html

相关文章

  • springsecurity配置内存中账号密码的配置(方便复制)。
    pom.xml的依赖:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> springsecurity的配置文件:WebSecurityConfig.javaimportorg.aspectj.weaver.ast.A......
  • Inofity+Rsync实时同步服务部署
    第一步:部署rsync服务1.1服务端:1.检查rsync是否安装[root@rsync-backup~]#rpm-qarsyncrsync-3.1.2-12.el7_9.x86_642.对rsync服务进行配置[root@rsync-backup~]#cat/etc/rsyncd.confuid=rsyncgid=rsyncfakesuper=yesusechroot=nomaxconnections=......
  • 使用同步带模组需要注意的事项
    提到直线模组,相信大家都非常熟悉了,直线模组的种类很多,一般用于自动化设备,其中,丝杆模组和同步带模组是直线模组中使用率较多的两种。在工业自动化时代,同步带模组得到了广泛的应用,那么我们在使用同步带模组时需要注意哪些问题呢?首先我们应该考虑使用环境,在恶劣的环境下,我们一般都要选......
  • linux时间同步,ntpd、ntpdate
    在Windwos中,系统时间的设置很简单,界面操作,通俗易懂。而且设置后,重启,关机都没关系。系统时间会自动保存在Bios的时钟里面,启动计算机的时候,系统会自动在Bios里面取硬件时间,以保证时间的不间断。    但在Linux下,默认情况下,系统时间和硬件时间,并不会自动同步。在Linux运行过程中,......
  • 42、如何把pdf里面的表格复制到Excel表格里面呢?
    要求:把pdf表格里面的价格去掉(pdf里面的表格有一个是一整张图片来的,有一个是直接表格)解决方法:直接复制的话,Excel的格式会乱的,那么这里就把pdf的内容转为word,然后在Excel表格里面复制word的内容,但是这样做也是比较慢的,         另一个表格是图片来的,这个用off......
  • Redis主从复制、哨兵、集群原理部署介绍
    Redis主从复制、哨兵、集群原理部署介绍原创 程序话题 IT当时语 2023-04-1820:26 发表于广东收录于合集#架构设计22个#分布式系统17个#Redis4个#微服务11个#分布式锁3个Redis主从复制、哨兵、集群原理部署介绍Redis主从复制的核心原理在分布式架构设计中......
  • Streamsets读取binlog数据实时同步到MySQL
    原文:https://blog.csdn.net/maomaosi2009/article/details/1082932171、说明实时同步binlog数据到MySQL我使用了2种方式,2、方式一第一种方式较为繁琐,数据从binlog流出,经过JS数据解析器将必要的字段解析出来,流入操作选择器,根据具体需要执行的增删改操作选择最后的JDBCProducer,pi......
  • ES transport client底层是netty实现,netty本质上是异步方式,但是netty自身可以使用sync
    EStransportclient底层是netty实现,netty本质上是异步方式,但是netty自身可以使用sync或者await(future超时机制)来实现类似同步调用!因此,EStransportclient可以同步调用也可以异步(不过底层的socket必然是异步实现)。发送端例子对于javaclient的数据发送(这里以bulk为例),写过的人都知......
  • thinkphp结合workerman和gateway实现数据同步
    thinkphp结合workerman和gateway实现数据同步0x10安装扩展composerrequiretopthink/think-worker=2.0.*composerrequireworkerman/gatewayclient此安装仅针对5.1,其他版本根据官方要求安装。client仅针对3.0.8以上,具体看GitHub0x20服务端Gateway0x21config/worker_gate......
  • TDSQL强同步复制
    一.概述通过分析,我们发现MySQL原声半同步复制缺陷:1、MySQL半同步复制支持退化成异步复制,在严格的金融场景不一定合适。2、MySQL在Slave在收到Master的binlog时,默认情况下无法保证relay log实时落盘,即sync_relay_log=0,如果需要保证relay log实时落盘,即sync_relay_log=1,则每个event......