MySQL 12_MySQL高可用架构

一、主从复制

1.1 主从复制的架构及作用

主从复制的基本架构如下图:

主从复制的作用:

  • 读写分离
  • 数据备份
  • 高可用性

1.2 主从复制的原理

MySQL主从同步的原理是基于 binlog 进行数据同步的。在主从复制过程中,会基于 3 个线程 来操作,一个主库线程两个从库线程

二进制日志转储线程(Binlog dump thread) 是一个主库线程。当从库线程连接master的时候,主库可以将二进制日志发送给从库,当主库读取事件(Event)的时候,会在 Binlog 上加锁,读取完成之后,再将锁释放掉。

从库 I/O 线程 会连接到主库,向主库发送请求同步更新 Binlog。这时从库的 I/O 线程就可以读取到主库的二进制日志转储线程发送的 Binlog 更新部分,并且拷贝到本地的中继日志 (Relay log)。

从库 SQL 线程 会读取从库中的中继日志,并且执行日志中的事件,将从库中的数据与主库保持同步。

注意:

  • 不是所有版本的MySQL都默认开启服务器的二进制日志。在进行主从同步的时候,需要先检查服务器是否已经开启了耳机二进制文件。
  • 除非特殊指定,默认情况下从服务器会执行所有主服务器中保存的事件。也可以通过配置,使从服务器执行特定的事件。

主从复制三步骤步骤1:Master将写(增、删、改等DML操作 及 DDL操作)操作记录到二进制日志(binlog); 步骤2:Slave将Master的binary log events拷贝到它的中继日志(relay log); 步骤3:Slave重做中继日志中的事件,将改变应用到自己的数据库中。 MySQL复制是异步的且串行化的,而且重启后从接入点开始复制。

主从复制的基本原则:

  • 每个Slave只有一个Master;
  • 每个Slave只能有一个唯一的服务器ID;
  • 每个Master可以有多个Slave;

1.3 主从复制同步数据一致性问题

主从同步的要求

  • Slave库和Master库的数据一致(最终一致);
  • 写数据必须写到Master库;
  • 读数据可以一般到Slave库,也可以到Master库;

主从同步延迟问题: 进行主从同步的内容是二进制日志,它是一个文件,在进行网络传输的过程中就一定会存在主从延迟(比如 500ms),这样就可能造成用户在从库上读取的数据不是最新的数据,也就是主从同步中的数据不一致性问题。

在网络正常的时候,日志从主库传给从库所需的时间是很短的。即,网络正常情况下,主备延迟的主要来源是备库接收完binlog和执行完这个事务之间的时间差。

主备延迟最直接的表现是,从库消费中继日志(relay log)的速度,比主库生产binlog的速度要慢,造成原因:

  • 从库的机器性能比主库要差
  • 从库的压力大
  • 大事务的执行

若想要减少主从延迟的时间,可以采取下面的办法:

  • 降低多线程大事务并发的概率,优化业务逻辑;
  • 优化SQL,避免慢SQL,减少批量操作,建议写脚本以 update-sleep 这样的形式完成;
  • 提高从库机器的配置,减少主库写binlog和从库读binlog的效率差;
  • 尽量采用 短的链路,也就是主库和从库服务器的距离尽量要短,提升端口带宽,减少binlog传输的网络延时;
  • 实时性要求的业务读强制走主库,从库只做灾备,备份;

解决主从同步一致性问题

读写分离情况下,解决主从同步中数据不一致的问题,就是解决主从之间 数据复制方式 的问题,如果按照数据一致性 从弱到强 来进行划分,有以下 3 种复制方式:

方式1:异步复制 异步模式 就是客户端提交commit之后,Master库不需要再等从库返回任何结果,而是直接将结果返回给客户端,这样做的好处是不会影响主库写的效率,但可能会存在主库宕机,而Binlog还没有同步到从库的情况,也就是此时的主库和从库数据不一致。

这时候从从库中选择一个作为新主,那么新主则可能缺少原来主服务器中已提交的事务。所以,异步复制这种复制模式下的数据一致性是最弱的。

方式2:半同步复制 MySQL5.5版本之后开始支持半同步复制的方式。半同步复制的原理是在客户端提交COMMIT之后,Master不直接将结果返回给客户端,而是等待至少有一个从库接收到了Binlog,并且写入到中继日志中,再返回给客户端。

这样做的好处就是提高了数据的一致性,当然相比于异步复制来说,至少多增加了一个网络连接的延迟,降低了主库写的效率。

在MySQL5.7版本中还增加了一个 rpl_semi_sync_master_wait.for_slave.count 参数,可以对应答的从库数量进行设置,默认为1,也就是说只要有1个从库进行了响应,就可以返回给客户端。如果将这个参数调大,可以提升数据一致性的强度,但也会增加主库等待从库响应的时间。

方式3:组复制 首先将多个节点共同组成一个复制组,在执行读写(RW)事务的时候,需要通过一致性协议层(Consensus 层)的同意,也就是读写事务想要进行提交,必须要经过组里“大多数人”(对应 Node 节点)的同意,大多数指的是同意的节点数量需要大于(N/2+1),这样才可以进行提交,而不是原发起方一个说了算。而针对只读(RO)事务则不需要经过组内同意,直接 COMMIT 即可。

在主从架构的配置中,如果想要采取读写分离的策略,可以自己编写程序,也可以通过第三方的中间件来实现: