文章目录
MySQL45讲 第二十五讲 高可用性深度剖析:从主备原理到策略选择
在当今数字化时代,数据库的高可用性对于企业的业务连续性至关重要。MySQL 作为广泛使用的关系型数据库管理系统,其高可用性机制一直备受关注。今天,我们将深入探讨 MySQL 是如何保证高可用性的,这涉及到主备关系中的数据同步、主备延迟的产生原因及应对策略,以及主备切换时可靠性优先和可用性优先策略的权衡。
一、MySQL 主备基础原理
(一)主备关系与数据同步
在 MySQL 的主备关系中,每个备库接收主库的 binlog 并执行,以此来保持数据一致。正常情况下,主库执行更新生成的 binlog 能顺利传到备库并被正确执行,备库就能达到与主库一致的状态,这就是最终一致性。例如,在一个简单的一主一备架构中,主库上的数据更新操作会被记录到 binlog 中,备库通过读取和执行这些 binlog,实现数据的同步更新。
(二)主备切换流程
我们来看双 M 结构的主备切换流程(如下图所示)。
在状态 1 时,客户端的读写直接访问主库 A,备库 B 作为主库 A 的备库,通过同步 A 的更新来保持数据一致。此时,通常建议将备库 B 设置为只读(readonly)模式,原因如下:
- 防止运营类查询语句在备库上的误操作。例如,运营人员可能在备库上执行一些临时查询,如果备库可写,可能会不小心修改数据,导致主备数据不一致。
- 避免切换逻辑出现 bug,如双写导致主备不一致。如果备库可写,在主备切换过程中可能会出现同时写入主库和备库的情况,破坏数据的一致性。
- 可依据 readonly 状态判断节点角色。在运维过程中,通过查看节点的 readonly 状态,可以快速确定其是主库还是备库,便于管理和维护。
- 虽然设置为 readonly,但用于同步更新的线程拥有超级权限,仍可进行数据同步。这样既能保证备库的只读性,又能确保数据的同步正常进行。
当需要切换时,客户端读写访问切换到备库 B,此时备库 B 成为主库,原主库 A 成为备库。
二、主备延迟分析
(一)主备延迟的定义与计算
- 相关时间点
- 主库 A 执行完成一个事务,写入 binlog 的时刻记为 T1。
- 备库 B 接收完这个 binlog 的时刻记为 T2。
- 备库 B 执行完成这个事务的时刻记为 T3。
- 主备延迟就是同一个事务在备库执行完成的时间和主库执行完成的时间之间的差值,即 T3 - T1。
- 计算方法
- 可以在备库上执行
show slave status
命令,其返回结果中的seconds_behind_master
用于表示当前备库延迟了多少秒。seconds_behind_master
的计算方法是:每个事务的 binlog 里面都有一个时间字段,用于记录主库上写入的时间;备库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值,得到seconds_behind_master
。实际上,seconds_behind_master
计算的就是 T3 - T1,其时间精度是秒。
- 可以在备库上执行
- 系统时间不一致的影响
- 若主备库机器的系统时间设置不一致,不会导致主备延迟的值不准。因为备库连接到主库的时候,会通过执行
SELECT UNIX_TIMESTAMP ()
函数来获得当前主库的系统时间。如果发现主库的系统时间与自己不一致,备库在执行seconds_behind_master
计算的时候会自动扣掉这个差值。
- 若主备库机器的系统时间设置不一致,不会导致主备延迟的值不准。因为备库连接到主库的时候,会通过执行
(二)主备延迟的来源
- 备库性能较差
- 在一些部署中,备库所在机器的性能比主库所在机器性能差。例如,有人认为备库没有请求,所以使用较差的机器,或者将多个主库放在少数性能较好的机器上,而把备库集中在一台性能较差的机器上。然而,更新请求对 IOPS 的压力在主库和备库上并无差别,这种部署可能导致备库在处理事务时资源不足,从而造成主备延迟。不过,现在这种不对称部署情况较少,更多的是采用主备库选用相同规格机器并做对称部署的方式。
- 备库压力大
- 一种常见情况是,主库提供写能力,备库提供读能力,同时一些运营后台需要的分析语句也在备库上运行。由于主库直接影响业务,使用时会比较克制,而备库的压力容易被忽视。大量的查询操作可能耗费备库大量的 CPU 资源,影响同步速度,进而造成主备延迟。针对这种情况,可以采用一主多从的方式,让多个从库分担读的压力;或者通过 binlog 输出到外部系统(如 Hadoop),让外部系统提供统计类查询的能力。其中,一主多从的方式较为常用,因为从库还适合用于定期全量备份。
- 大事务
- 大事务是导致主备延迟的另一个重要原因。主库上必须等事务执行完成才会写入 binlog 并传给备库,所以如果一个主库上的语句执行时间很长,如一次性删除大量数据或执行大表 DDL 操作,就会导致从库延迟。例如,一些归档类数据在删除时,如果一次性删除过多,可能会使备库延迟很长时间。对于计划内的大表 DDL 操作,建议使用 gh - ost 方案来减少对主备延迟的影响。
- 备库的并行复制能力
- 备库的并行复制能力也会影响主备延迟,这将在下一篇文章中详细介绍。此外,还有其他一些情况可能导致主备延迟,如主库 DML 语句并发大、从库服务器配置差、主库和从库参数配置不一样、从库上在进行备份操作、表上无主键(主库利用索引更改数据,备库回放只能用全表扫描)、设置的是延迟备库、备库空间不足等。
三、主备切换策略
(一)可靠性优先策略
- 切换流程
- 在双 M 结构下,从状态 1 到状态 2 切换时,可靠性优先策略的详细过程如下:
- 判断备库 B 现在的
seconds_behind_master
,如果小于某个值(如 5 秒)继续下一步,否则持续重试这一步。这一步的目的是确保备库与主库的延迟在可接受范围内,避免切换后出现数据不一致的情况。 - 把主库 A 改成只读状态,即把 readonly 设置为 true。这可以防止在切换过程中主库有新的数据写入,保证数据的一致性。
- 判断备库 B 的
seconds_behind_master
的值,直到这个值变成 0 为止。这一步需要等待备库完全同步主库的数据,确保切换后的数据准确性。 - 把备库 B 改成可读写状态,也就是把 readonly 设置为 false。此时备库 B 成为新的主库,可以接受读写请求。
- 把业务请求切到备库 B,完成主备切换。
- 判断备库 B 现在的
- 在双 M 结构下,从状态 1 到状态 2 切换时,可靠性优先策略的详细过程如下:
- 不可用时间分析
- 这个切换流程中存在不可用时间。在步骤 2 之后,主库 A 和备库 B 都处于 readonly 状态,系统处于不可写状态,直到步骤 5 完成后才能恢复。其中,步骤 3 可能需要耗费较长时间,这也是为什么需要在步骤 1 先做判断,确保
seconds_behind_master
的值足够小。如果一开始主备延迟就很长,如长达 30 分钟,而不先做判断直接切换,系统的不可用时间就会很长,这对业务来说可能是不可接受的。
- 这个切换流程中存在不可用时间。在步骤 2 之后,主库 A 和备库 B 都处于 readonly 状态,系统处于不可写状态,直到步骤 5 完成后才能恢复。其中,步骤 3 可能需要耗费较长时间,这也是为什么需要在步骤 1 先做判断,确保
(二)可用性优先策略
- 切换流程与数据不一致示例
- 如果强行把步骤 4、5 调整到最开始执行,即不等主备数据同步,直接把连接切到备库 B 并让其可读写,系统几乎没有不可用时间,但可能出现数据不一致的情况。
- 例如,假设有一个表 t 定义了自增主键 id,初始化数据后,主库和备库上都是 3 行数据。业务人员要执行两条插入语句,在插入一条 c = 4 的语句后发起主备切换(假设此时主备延迟达到 5 秒)。
- 主库 A 执行完 insert 语句,插入了一行数据 (4,4) 后开始切换。由于主备延迟,备库 B 还没来得及应用 “插入 c = 4” 的中转日志,就开始接收客户端 “插入 c = 5” 的命令,此时备库 B 插入了一行数据 (4,5),并把 binlog 发给主库 A。接着备库 B 执行 “插入 c = 4” 的中转日志,插入了一行数据 (5,4),而直接在备库 B 执行的 “插入 c = 5” 语句传到主库 A 后,插入了一行新数据 (5,5)。最终,主库 A 和备库 B 上出现了两行不一致的数据。
- binlog 格式对数据一致性的影响
- 当设置
binlog_format = row
时,数据不一致的问题更容易被发现。因为 row 格式在记录 binlog 时会记录新插入行的所有字段值,所以最后只会有一行不一致,且两边的主备同步应用线程会报错 duplicate key error 并停止。而使用 mixed 或 statement 格式的 binlog 时,数据很可能悄悄地就不一致了,如果过了很久才发现数据不一致问题,可能这时的数据不一致已经不可查,或者连带造成了更多的数据逻辑不一致。
- 当设置
(三)策略选择的权衡
- 可靠性优先的建议
- 大多数情况下,建议使用可靠性优先策略。因为对数据服务来说,数据的可靠性一般要优于可用性。保证数据准确是数据库服务的底线,在此基础上,通过减少主备延迟来提升系统的可用性。
- 可用性优先的适用场景
- 然而,也存在一些情况数据的可用性优先级更高。例如,有一个库用于记录操作日志,数据不一致可以通过 binlog 来修补,且短暂的不一致不会引发业务问题,同时业务系统依赖于这个日志写入逻辑,如果库不可写会导致线上业务操作无法执行。在这种情况下,可以选择先强行切换,事后再补数据的策略。但事后复盘时,应考虑改进措施,如让业务逻辑不依赖于这类日志的写入,将日志写入逻辑模块降级,写到本地文件或另一个临时库中,这样就可以再次使用可靠性优先策略。
四、异常切换情况
(一)异常切换流程
假设主库 A 和备库 B 间的主备延迟是 30 分钟,此时主库 A 掉电,HA 系统要切换 B 作为主库。按照可靠性优先策略,必须等到备库 B 的 seconds_behind_master = 0 之后才能切换。但此时由于主库 A 掉电,连接还未切到备库 B,系统处于完全不可用状态。如果直接切换到备库 B 且保持 B 只读也不行,因为中转日志还未应用完成,客户端查询可能会认为有 “数据丢失”,虽然数据最终会恢复,但查询到 “暂时丢失数据的状态” 对一些业务来说是不可接受的。
(二)对可用性的影响
从这个例子可以看出,在满足数据可靠性的前提下,MySQL 高可用系统的可用性依赖于主备延迟。延迟时间越小,在主库故障时服务恢复所需时间就越短,可用性就越高。
五、总结与思考
MySQL 通过主备机制实现高可用性,主备数据同步基于 binlog。主备延迟的产生有多种原因,包括备库性能、压力、大事务以及并行复制能力等。在主备切换时,可靠性优先策略能保证数据一致性但可能存在不可用时间,可用性优先策略可减少不可用时间但可能导致数据不一致。在实际应用中,应根据业务需求权衡选择合适的策略。
标签:主库,备库,主备,MySQL45,切换,从主备,高可用性,数据,延迟 From: https://blog.csdn.net/KELLENSHAW/article/details/143861483