5.1.主从复制架构

5.1.1.什么是MySQL架构的Master-Slave(主从)复制模式

单机版MySQL容易出现单点故障,所以需要搭建多台MySQL服务器,MySQL架构有很多种,目的都是热备份,多活,故障切换,负载均衡、读写分离等

MySQL主从复制模式主要为master负责接收用户的请求,DDL,DML,DCL等操作,slave主要负责同步master的二进制日志,以便备份数据。在一此数据库访问量比较大的场景,master-slave模式还可以结合mysql-proxy做读写分离,mysql-proxy负责将用户的写请求转发到master,将用户的读请求转发到slave,以分担数据库的压力。甚至更健壮的系统,一个master对应多个slave,做成高可用HA集群,当master宕机的时候,多个slave会协商出一个slave重新成为master,以达到服务的持续性。

5.1.2.分类

  • 一主多从复制架构
  • 多级复制架构
  • 双主(Dual Master)复制架构
  • 多源(Multi-Source)复制架构
5.1.2.1.一主多从复制架构

master主节点负责写入数据,slave从节点负责读取数据。实现了读写分离。应用与读多写少的业务场景。

在主库出现异常宕机的情况下,可以把一个从库切换为主库继续提供服务。而且master和slave数据还有同步延迟的风险。

5.1.2.2.多级复制架构

这种架构是级联复制架构,用于解决读需求更多的业务场景。如果读压力加大,就需要更多的slave来解决,但是如果slave的复制全部从master复制,势必会加大master的复制IO的压力,所以就出现了级联复制,减轻master压力。缺点就是slave延迟更加大了。

对比一主多从的架构,多级复制仅仅是在主库Master1复制到从库Slave1、Slave2、Slave3的中间增加了一个二级主库Master2,这样,主库Master1只需要给一个从库Master2发送BINLOG日志即可,减轻了主库Master1的压力。二级主库Master2再发送BINLOG日志给所有的从库Slave1、Slave2和Slave3的I/O线程。

多级复制解决了一主多从场景下,主库的I/O负载和网络压力,当然也有缺点:MySQL的传统复制是异步的,多级复制场景下主库的数据是经历两次复制才到达从库Slave1、Slave2、Slave3的,期间的延迟要比一主多从复制场景下只经历一次复制的还大。

可以通过在二级主库Master2上选择存储引擎为BLACKHOLE来降低多级复制的延迟。顾名思义,BLACKHOLE引擎是一个“黑洞”引擎,写入BLACKHOLE表的数据并不会写回到磁盘上,BLACKHOLE表永远都是空表,INSERT、UPDATE、DELETE操作仅仅在BINLOG中记录事件。

BLACKHOLE引擎非常适合二级主库Masger2的场景:Master2并不承担读写请求,仅仅负责将BINLOG日志尽快传送给从库。

5.1.2.3.双主(Dual Master)复制架构

双主复制架构适用于需要进行主从切换的场景。

两个数据库互为主从,当主库宕机恢复后,由于它还是原来从库(现在主库)的从机,所以它还是会复制新的主库上的数据。那么无论主库的角色怎么切换,原来的主库都不会脱离复制环境。

在DBA做维护时需要主从切换的场景,通过双主复制架构避免了重复搭建从库的麻烦。

主库Master 1和Master 2互为主从,所有Web Client的写请求都访问主库Master 1或Master 2。假如,DBA需要做日常维护操作,为了避免影响服务,需进行以下操作。

首先,在Master1库上停止Slave线程(STOP SLAVE),避免后续对Master2库的维护操作操作被实时复制到Master1库上对服务造成影响。
其次,在Master2库上停止Slave线程(STOP SLAVE),开始日常维护操作,例如修改varchar字段从长度10增加到200。
然后,在Master2库上完成维护操作之后,打开Master2库上的Slave线程(STRART SLAVE),让Master2的数据和Master1库同步,同步完成后,把应用的写操作切换到Master2库上。
最后,确认Master1库上没有应用访问后,打开Master1的Slave线程(START SLAVE)即可。
通过双主复制架构能够大大减轻一主多从架构下对主库进行维护带来的额外搭建从库的工作。

5.1.3.主从复制原理

5.1.3.1 异步复制

(1) 在主服务器写操作举例:insert 语句。
(2) 事务提交到master,master确认修改已保存。
(3) master接收到应用事务提交请求后,更新内部的binlog日志,让mysql引擎执行事务操作,并返回给客户端执行结果信息。同时在master中会存在一个事件监听,其会一直监听着master中binlog日志文件的改变,一旦发现日志文件发生改变,触发dump线程
(4) dump线程被触发后,通知slave中的IO线程:现在有事务操作要进行同步
(5) slave中IO线程接收到通知后,会从slave中relay-log.info文件中获取slave中的binlog日志文件和pos位置信息。接着会把这部分信息发送给master的dump线程。发送信息的含义是:告诉master,我上次读取到了哪里,这次还从上次读取到的位置继续读取。
(6) master的dump线程收到这些信息后,会根据slave发送的binlog日志文件和pos位置,将最新的binlog日志和pos位置后面的内容同步给slave的IO线程
(7) slave的IO线程接收到这些信息后,会将这部分内容同步到slave中的relay-bin文件中
(8) 当relay-bin文件发生改变后,触发slave线程执行sql操作【异步】
(9) 当slave向relay-bin写入完成后,会向master返回一个ACK消息,同步成功。
对于这一系列的操作,可以发现master和slave在进行同步时是以异步的方式完成的,master写入完binlog后,会马上通过引擎进行事务提交并向客户端返回响应,对于与slave同步的操作,则是异步完成的。

优点 : 效率高

缺点 : 可能出现数据不一致

5.1.3.2 半同步复制

半同步复制与异步复制的工作流程大体相似

不同点: 当master中的binlog日志写入完成后,其不会马上通过引擎进行事务提交,而会处于等待,等到slave同步完成向master返回ACK通知后,才会唤醒等待,继续向下执行。

  • 等待的时长,默认为10秒,但该时间可以配置
  • 尽量的避免了主从数据不一致,但造成吞吐量的降低
  • mysql兜底方案: 使用半同步复制进行备份时slave节点挂掉了,那么当master等待10秒后,仍然会进行引擎提交,同时会将半同步复制切换为异步复制。等到slave节点重启后,又会自动的从异步复制切换到半同步复制。