25、MySQL的高可用性

首先,我们需要理解高可用的概念,在百度百科上如此写到, “高可用性”(High Availability)通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性

哇,那就很明显了,就是一直打工,尽量避免休息。

我们来看下数据库主备切换流程图:在状态1时,客户端访问节点A,节点B为备库,将节点A的binlog同步到节点B上执行。当需要切换的时候,就切换状态2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QO6uRD9z-1607957057629)(D:\计算机笔记\mysql\images\83.jpg)]

25.1 主备延迟

主库的binlog同步到备库执行完成是有一个延迟时间的,称为同步延迟,我们可以通过show slave status指令,它会返回seconds_behind_master,用于表示同步延迟了多少秒。

seconds_behind_master 的计算方法是这样的:

  1. 每个事务的 binlog 里面都有一个时间字段,用于记录主库上写入的时间;
  2. 备库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值,得到 seconds_behind_master。

那如果主备库的时间不一致,会加大/缩短时间嘛?并不会,它会通过SELECT_UNIX_TIMESTAMP()来获得主库的的当前时间,计算的时候,会减去该数值。

在网络征程情况下,主备库传递日志的时间是很短的,主备同步延迟的主要表现还是备库消费中转日志额速度比不上主库生成binlog的速度,接下来,我们来看看有哪些原因:

25.2造成主备延迟的来源

1.备库所在机器的性能要比主库所在机器性能差:

一般情况下,有人这么部署时的想法是,反正备库没有请求,所以可以用差一点儿的机器。或者,他们会把 20 个主库放在 4 台机器上,而把备库集中在一台机器上。

但实际上,更新请求对IOPS的要求一点都没有差,在这种模式下,一般都会将备库设置为“非双1”的模式,牺牲备库的可靠性,增加IO能力。

但实际上, 更新过程中也会触发大量的读操作。所以,当备库主机上的多个备库都在争抢资源的时候,就可能会导致主备延迟了。

2.备库压力大

主库提供了写能力,那备库提供一些读能力 。结果大量的读操作抢占CPU资源, 影响了同步速度,造成主备延迟。

这种情况,我们一般可以这么处理:

  1. 一主多从。除了备库外,可以多接几个从库,让这些从库来分担读的压力。
  2. 通过 binlog 输出到外部系统,比如 Hadoop 这类系统,让外部系统提供统计类查询的能力。

3.大事务

大事务这种情况很好理解。因为主库上必须等事务执行完成才会写入 binlog,再传给备库。所以,如果一个主库上的语句执行 10 分钟,那这个事务很可能就会导致从库延迟 10 分钟。

例如 一次性地用 delete 语句删除太多数据。这就是一个典型的大事务场景。

另一种典型的大事务场景,就是大表 DDL。

由于主备延迟的存在,所以在主备切换的时候,就相应的有不同的策略。

25.3 同步延迟应对策略

可靠性优先策略:

在上图 的双 M 结构下,从状态 1 到状态 2 切换的详细过程是这样的:

  1. 判断备库 B 现在的 seconds_behind_master,如果小于某个值(比如 5 秒)继续下一步,否则持续重试这一步;
  2. 把主库 A 改成只读状态,即把 readonly 设置为 true;
  3. 判断备库 B 的 seconds_behind_master 的值,直到这个值变成 0 为止;
  4. 把备库 B 改成可读写状态,也就是把 readonly 设置为 false;
  5. 把业务请求切到备库 B。

这个切换流程,一般是由专门的 HA 系统来完成的,我们暂时称之为可靠性优先流程,流程如下:

Windows下MySQL高可用 mysql的高可用_Windows下MySQL高可用

可以看到,这个切换流程中是有不可用时间的。因为在步骤 2 之后,主库 A 和备库 B 都处于 readonly 状态,也就是说这时系统处于不可写状态,直到步骤 5 完成后才能恢复。

可用性优先策略:

如果我强行把步骤 4、5 调整到最开始执行,也就是说不等主备数据同步,直接把连接切到备库 B,并且让备库 B 可以读写,那么系统几乎就没有不可用时间了。

我们把这个切换流程,暂时称作可用性优先流程。这个切换流程的代价,就是可能出现数据不一致的情况。

下面是出现的代价示意图, 且 binlog_format=mixed 时:

Windows下MySQL高可用 mysql的高可用_数据库_02

当 设置 binlog_format=row 时, 因为 row 格式在记录 binlog 的时候,会记录新插入的行的所有字段值,所以最后只会有一行不一致。而且,两边的主备同步的应用线程会报错 duplicate key error 并停止。也就是说,这种情况下,备库 B 的 (5,4) 和主库 A 的 (5,5) 这两行数据,都不会被对方执行。,视图如下:

Windows下MySQL高可用 mysql的高可用_数据库_03

练习问题:

  1. 高可用性的概念
  2. 数据库切换的流程
  3. 同步延迟的指标,相关指令
  4. 造成同步延迟的几种情况
  5. 同步延迟应对方案级各方案应对的场景