Mysql的主从复制(一)—— 原理

一、概念

        MySQL 主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。MySQL 默认采用异步复制方式,这样从节点不用一直访问主服务器来更新自己的数据,数据的更新可以在远程连接上进行,从节点可以复制主数据库中的所有数据库或者特定的数据库,或者特定的表。

二、主要用途

1、读写分离

        在开发工作中,有时候会遇见某个sql 语句需要锁表,导致暂时不能使用读的服务,这样就会影响现有业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。

2、数据实时备份

        当系统中某个节点发生故障时,可以方便的故障切换。

3、高可用HA和架构扩展

        随着系统中业务访问量的增大,如果是单机部署数据库,就会导致I/O访问频率过高。有了主从复制,增加多个数据存储节点,将负载分布在多个从节点上,降低单机磁盘I/O访问的频率,提高单个机器的I/O性能。

三、主从形式

1、一主一从/一主多从

在这里插入图片描述

 

        一主多从,提高系统的读性能。一主一从和一主多从是最常见的主从架构,实施起来简单并且有效,不仅可以实现HA,而且还能读写分离,进而提升集群的并发能力。

2、多主一从 (从5.7开始支持)

在这里插入图片描述

        多主一从可以将多个mysql数据库备份到一台存储性能比较好的服务器上。

3、双主复制

        双主复制,也就是互做主从复制,每个master既是master,又是另外一台服务器的slave。这样任何一方所做的变更,都会通过复制应用到另外一方的数据库中。

4、级联复制

 

        级联复制模式下,部分slave的数据同步不连接主节点,而是连接从节点。因为如果主节点有太多的从节点,就会损耗一部分性能用于replication,那么我们可以让3~5个从节点连接主节点,其它从节点作为二级或者三级与从节点连接,这样不仅可以缓解主节点的压力,并且对数据一致性没有负面影响。

四、主从复制原理

        MySQL主从复制涉及到三个线程,一个运行在主节点(log dump thread),其余两个(I/O thread, SQL thread)运行在从节点,如下图所示:

在这里插入图片描述

1、主节点 binary log dump 线程

        当从节点连接主节点时,主节点会创建一个log dump 线程,用于发送bin-log的内容。在读取bin-log中的操作时,此线程会对主节点上的bin-log加锁,当读取完成,甚至在发动给从节点之前,锁会被释放。

2、从节点I/O线程

        当从节点上执行start slave命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的bin-log。I/O线程接收到主节点binlog dump 进程发来的更新之后,保存在本地relay-log中。

3、从节点SQL线程

        SQL线程负责读取relay log中的内容,解析成具体的操作并执行,最终保证主从数据的一致性。

        对于每一个主从连接,都需要三个进程来完成。当主节点有多个从节点时,主节点会为每一个当前连接的从节点建一个binary log dump 进程,而每个从节点都有自己的I/O进程,SQL进程。从节点用两个线程将从主库拉取更新和执行分成独立的任务,这样在执行同步数据任务的时候,不会降低读操作的性能。比如,如果从节点没有运行,此时I/O进程可以很快从主节点获取更新,尽管SQL进程还没有执行。如果在SQL进程执行之前从节点服务停止,至少I/O进程已经从主节点拉取到了最新的变更并且保存在本地relay日志中,当服务再次起来之后,就可以完成数据的同步。

        要实施复制,首先必须打开Master 端的binary log(bin-log)功能,否则无法实现。

        因为整个复制过程实际上就是Slave 从Master 端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。如下图所示:

在这里插入图片描述

五、复制的基本过程

1、从节点上的I/O 进程连接主节点,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;

2、主节点接收到来自从节点的I/O请求后,通过负责复制的I/O进程根据请求信息读取指定日志指定位置之后的日志信息,返回给从节点。返回信息中除了日志所包含的信息之外,还包括本次返回的信息的bin-log file 的以及bin-log position;从节点的I/O进程接收到内容后,将接收到的日志内容更新到本机的relay log中,并将读取到的binary log文件名和位置保存到master.info 文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log 的哪个位置开始往后的日志内容,请发给我”;

3、Slave 的 SQL线程检测到relay-log 中新增加了内容后,会将relay-log的内容解析成在主节点上实际执行过的操作,并在本数据库中执行。

六、主从复制模式

        MySQL 主从复制默认是异步的模式。MySQL增删改操作会全部记录在binary log中,当slave节点连接master时,会主动从master处获取最新的bin log文件。并把bin log中的sql relay。

 1、异步模式

        (Asynchronous replication)。异步模式如下图所示,这种模式下,主节点在执行完客户端提交的事务后会立刻将执行结果返回给客户端,并不关心从结点是否已经接收处理,不会主动push bin log到从节点,这样有可能导致failover的情况下,也许从节点没有即时地将最新的bin log同步到本地(即当主节点挂掉了,此时主节点上提交的事务可能还没有传到从节点上,而强行将从节点提升为主节点就会导致新主节点上的数据不完整)。

在这里插入图片描述

        异步复制是一种基于偏移量的主从复制,实现的原理是:主库开启binlog功能并授权从库连接主库,从库通过change master得到主库的相关同步信息,然后连接主库进行验证,主库的IO线程根据从库slave的线程请求,从master.info开始记录的位置点向下开始取信息,同时把提取到的位置点和最新的位置与binlog信息一同发给从库IO线程,从库将相关的sql语句放在relay_log中,最终从库的sql线程会将relay_log里的sql语句应用到从库上,至此同步过程完成,以后一直循环此过程。

        对于异步复制而言,主库将事务的Binlog事件写入到binlog文件中,此时主库会通知下dump线程发送这些新的binlog然后主库会继续处理提交操作,而此时并不保证这些日志会传输到任何一个从库的节点上。

2、全同步模式

        (Fully synchronous replication)。当主库执行完一个事务,所有的从库都执行了该事务才会将结果返回给客户端。这样保证了数据的安全性,但是因为需要等待所有从库执行完该事务才能返回客户端结果,所以全同步复制的性能必然会受到很大的影响。

        对于全同步复制而言,当主库提交一个事务后,要求所有从库节点必须收到,执行并提交这些事务,然后主库线程才能继续做后续操作,而因此带来的问题就是主库完成一个事务的时间被大幅度拉长,性能降低。

3、半同步模式(Mysql5.5 开始)

        (Semi synchronous replication)。介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收并写到relay log中才返回给客户端(主库不需要等待所有从库给主库反馈,同时这里只是收到反馈而不是完全执行并且提交事务的反馈,这样会节省很多的时间。相对于异步复制,半同步复制提高了数据的安全性,同时也会造成一定程度的延迟,这个延迟最少为一个TCP/IP往返的时间。所以半同步复制需要在低延时的网络中使用。

(1)半同步复制的特性

  • 从库会在连接到主库时告诉主库它是不是配置了半同步。
  • 从库节点只有在接收到某一事务的所有Binlog,将其写入并Flush到Relay Log文件后才会通知主库上面的等待线程。
  • 半同步复制必须在主库和从库两端都开启才生效,如果在主库上或从库任一节点没打开,主库都会以异步的方式进行复制。
  • 如果在主库的等待过程中,等待时间已经超过了配置的超时时间,没有任何一个节点通知当前事务,那么此时主库会自动转换为异步复制,当至少一个 半同步从节点赶上来时,主库便会转为半同步复制方式。 

        半同步的意思表示master只要接收到其中一台slave的返回信息就会commit,否则需要等待到超时时间转为异步进行提交。这种方式在损失很小的性能的情况下尽可能的提高了数据安全。

        半同步复制本质上来说还是一种异步复制,因为主库产生binlog到主库的binlog file,传到从库的中继日志,然后从库应用,可以说传输是异步的应用也是异步的。半同步复制指的是传输同步而应用还是异步的。也就是说保证了数据的安全不丢失,但是不能保证应用的同步即数据一致性。但是mysql5.6中,半同步复制相较于异步复制,dump thread除了传送binlog给从库,还新增了一个ack(消息确认)机制,即接收从库是否接成功接收到主库所提交的事务的标识码,而且这两个任务是串行的,dump thread必须等待从库返回之后才会传送下一个events事务。如果出现异常没有收到ack会自动降级为普通的复制,直到异常修复以后又会变成半同步复制。

(2)半同步复制存在的问题

        客户端的事务在存储引擎层提交了,但在得到从库确认的过程中,主库宕机了,此时有两种可能的情况:

  • 事务还没有发送到从库上:客户端此时会受到事务提交失败的提示,而客户端会将请求提交到新的主上,当宕机的主库重新启动后,以从库的身份加入到这个主从结构中,会发现该事务在此从库中被提交了两次。一次是作为之前主库时,一次是作为新从库被同步来的。
  • 事务已经发送到从库上:此时从库已经收到并应用了该事务,但客户端仍会收到事务提交失败的信息,会重新提交请求到新的主上。

        简单来说就是,在MySQL5.5-5.6使用after_commit的模式,客户端事务在存储引擎层提交后,在得到从库的确认的过程中,主库宕机了。此时,主库在等待slave ACK的过程中,虽然没有返回结果给当前的客户端,但是实际事务时提交的,其他客户端会读取到当前的已提交事务,如果slave端还没有读到该事务的events,同时主库也开始了故障切换到了备库,那么之前读到的事务就会消失,也就是“幻读”。如果此时主库永远都无法启动那么这期间的事务便丢失了即数据丢失,这样的问题是MySQL不愿意看到的。

        针对上述存在的问题,MySQL5.7引入了一种新的半同步方案,即独立出一个ack collector thread,专门用于接收从库的反馈信息,这样 master 上有两个线程独立工作,可以同时发送 binlog 到 slave ,和接收 slave 的反馈。并且在5.7引入了一个新的参数,rpl_semi_sync_master_wait_point,这个参数有两种取值,1)AFTER_SYNC 、2)AFTER_COMMIT,前者是新的半同步方案后者为老的半同步方案。

(3)半同步复制的必要条件

  • MySQL5.5及以上版本
  • 变量have_dynamic_loading 为YES(查看命令:show variables like “have_dynamic_loading”;)
  • 主从复制已经存在(即提前部署mysql主从复制环境,主从同步要配置基于整个数据库的,不要配置基于某个库的同步,即同步时不要过滤库)。

(4)半同步复制配置

        主库配置:


vim /etc/my.cnf                
 
#在 [mysqld] 区域添加下面内容
......
#加载mysql半同步复制的插件
plugin-load=rpl_semi_sync_master=semisync_master.so       
#或者设置为"1",即开启半同步复制功能     
rpl_semi_sync_master_enabled=ON        
#超时时间为1000ms,即1s                        
rpl-semi-sync-master-timeout=1000                    
 
#重启服务
systemctl restart mysqld

        从库配置:

vim /etc/my.cnf    
 
......
#这是是slave
plugin-load=rpl_semi_sync_slave=semisync_slave.so
rpl_semi_sync_slave_enabled=ON
 
systemctl restart mysqld

        查看半同步是否在运行:

#主数据库执行
show status like 'Rpl_semi_sync_master_status';
show variables like 'rpl_semi_sync_master_timeout';
#从数据库执行(此时可能还是OFF状态,需要在下一步重启IO线程后,从库半同步状态才会为ON)
show status like 'Rpl_semi_sync_slave_status';
 
#重启从数据库上的IO线程
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
 
#在主库查询半同步状态
show status like '%Rpl_semi%';    

(5)半同步参数说明

  • Rpl_semi_sync_master_clients                      #半同步复制客户端的个数
  • Rpl_semi_sync_master_net_avg_wait_time            #平均等待时间(默认毫秒)
  • Rpl_semi_sync_master_net_wait_time                #总共等待时间
  • Rpl_semi_sync_master_net_waits                    #等待次数
  • Rpl_semi_sync_master_no_times                     #关闭半同步复制的次数
  • Rpl_semi_sync_master_no_tx                        #表示没有成功接收slave提交的次数
  • Rpl_semi_sync_master_status               #表示当前是异步模式还是半同步模式,on为半同步
  • Rpl_semi_sync_master_timefunc_failures            #调用时间函数失败的次数
  • Rpl_semi_sync_master_tx_avg_wait_time             #事物的平均传输时间
  • Rpl_semi_sync_master_tx_wait_time                 #事物的总共传输时间
  • Rpl_semi_sync_master_tx_waits                     #事物等待次数
  • Rpl_semi_sync_master_wait_pos_backtraverse        #可以理解为"后来的先到了,而先来的还没有到的次数"
  • Rpl_semi_sync_master_wait_sessions    #当前有多少个session因为slave的回复而造成等待
  • Rpl_semi_sync_master_yes_tx           #成功接受到slave事物回复的次数

七、总结

        Mysql 主从复制是mysql 高可用,高性能的基础,有了这个基础,mysql 的部署会变得简单、灵活并且具有多样性,从而可以根据不同的业务场景做出灵活的调整。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值