开发者学堂课程【MySQL 实战进阶:MySQL MGR 8.0高可用实战】学习笔记,与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/83/detail/1305
MySQL MGR 8.0高可用实战
内容介绍
一.MGR 特性
二.集群架构
三.数据同步原理
四.冲突检测原理和说明
五.性能分析
六.事务一致性保证
七.流控机制
八.适用场景
九.高可用方案
我们将从 MGR 特性,集群架构,数据同步原理,适用场景,业内常用的高可用方案这几个主题来进行探讨。
一.MGR 特性
在了解 MGR 组件之前,我们需要了解什么是 MGR 特性。
1.MGR 是什么
使用的协议
节点状态一致性保证
如何保证数据一致性
通讯协议:基于 Paxos 算法的 GCS 原子广播协议,保证了一条事务在集群内要么在全部节点上提交或者回滚。
组成员资格: MGR 内部提供一个视图服务,集群节点之间相互交换各自的视图信息,从而实现集群整体的稳态。
数据一致性: MGR 内部实现了一套不同事务之间修改数据的冲突认证检测机制。在集群的所有节点进行一个冲突认证检测,反之,通过冲突认证检测的事务即可提交成功。
MGR是具备强大的分布式协调能力,可用于创建弹性、高可用性、高容错的复制拓扑的一个 MySQL 高可用插件。
如图所示,我们以3节点的 MGR 集群为例。
Member 1代表 primer 节点,Member 2和 Member 3 代表 secondary 节点。
一个事务在发起提交之后,它会通过原子广播协议分发到了我们的集群的其它的几个 secondary 节点, secondary 节点在进行 binlog 和 commit 应用之后,通过冲突检测之后,它会提交成功。在所有的 secondary 节点提交成功之后,它会在 primer 节点再次提交,反之,如果冲突检测失败时,在 secondary 节点它会丢弃这个事务对应的 binlog ,对于 primer 节点,会回滚该事务。
二.集群架构
MGR 架构分为单主模式和多主模式。
1. MGR 插件组成
它是由 MySQL Server ,它的 API 接口层,若干组件以及 GCS 协议分装组成。
MySQL Server :基于 MySQL 现有的主从复制,利用 row 格式的 binlog 和 gtid 等功能实现的集群架构。
它的 API 接口层是基于 server 交互的接口集,在逻辑上将 MySQL 内核与 MGR 插件隔绝开来。
其它的组件,如 Capture 组件是负责事务的状态:它在集群内是提交还是回滚,以及它通过 binlog 广播到其它节点上,进行冲突的认证检测进行到哪一个阶段; Applier 组件代表着 MGR 集群一个 secondary 节点的 binlog 的回放; Recovery 组件代表我们进行崩溃恢复或者集群扩容的时候增量数据的应用。
最下面两层就是组通信系统,它是基于 paxos 协议实现的组通信引,主要提供数据一致性核心功能的实现。
2.单主模式
在单主模式下( group_replication_single_primary_mode=ON):
(1)该变量在所有组成员中必须设置为相同的值。同一个集群中,不能将节点设置在不同的模式中。比如,不能一个节点设置为 on ,另一个节点设置为 off 。
(2)该集群具有一个设置为读写模式的主节点(即 primer 节点)。组中的所有其他成员都设置为只读模式( super-read-only=ON)。
(3)读写节点通常是引导该组的第一个节点。加入该集群的所有其他只读节点均需要从读写节点同步数据,并自动设置为只读模式。
3.多主模式
在多主模式下( group_replication_single_primary_mode = OFF):
(1)所有节点不会区分 primary 和 standby 角色。
(2)加入该集群时,与其他组成员兼容的任何节点都被设置为读写模式,并且可以处理写请求,即使它们在集群内是在不同节点内并发执行的。
(3)如果组复制中的某个节点停止接受写事务,例如,在某个节点意外或者因为断电而宕机的情况下,可以将与其连接的客户端重定向或故障转移到处于读写模式的任何其它健康的节点。
(4)组复制本身不处理客户端故障转移,因此需要使用中间件框架(例如 MySQL Router 8.0,代理,连接器或应用程序本身重叠项的功能)来实现。
三.数据同步原理
我们以一个 succeed MGR 集群为例。当一个事务发起提交的时候,在单主模式下,它会通过原子广播协议将我们事务伴随的 binlog 广播到了其它的 standby 上面,在获得大多数集群的同意之后,它会进行提交。如果通过冲突认证检测,那么该事务最终会在集群当中提交。
如果在 standby 节点上面没有通过冲突认证检测,那么 standby 节点丢弃该事务对应的这段 binlog , prime 节点回滚该事务。
四.冲突检测原理和说明
1.冲突检测原理
(1)在进行冲突检测的时候,由每个事务的 gtid set 和对应的主键 hash 值组成事务认证列表。在每个节点中都维护这样一个冲突检测库,且这个库在内存当中。
(2) gtid set :标记数据库的快照版本,事务提交前从 gtid_execute 变量中获取该值。
(3)事务提交前,数据库中执行了的 gtid 集合,随着 binlog 中的 event 通过原子广播的方式分发到集群的所有节点上进行事务冲突检测。
2.冲突检测说明
比如, T1 和 T2 这两条 update 语句。它们在进行冲突认证检测的时候:
(1)若 T2 修改的数据在冲突检测数据库中无匹配记录,则判定为通过冲突检测认证。
(2)若 T2 中的 gtd set 包含了冲突检测数据库中相同主键值的 gtid set ,则冲突认证检测通过。
(3)冲突认证检测通过后,每个节点的冲突检测数据库按照如下规则变更:
①若在冲突检测数据库中无匹配记录,则向其中插入一条新的记录。
②如果有记录,则更新冲突检测数据库中的 gtid set 值。(如下图所示)
③若 T1 修改的数据在冲突检测数据库中有匹配到记录,且 T1 的 gtid set 不包括冲突检测数据库中的 gtid set ,则判定为冲突检测不通过。
④注意:冲突检测不通过时,不会更新认证数据库里的 gtid set 集合。
五.性能分析
存在的问题
1. MGR 可确保仅在集群中的大多数节点都已收到事务并就并发发送的所有事务之间的相对顺序达成一致后,才提交事务。相对顺序意味着,在 primary 节点进行提交的顺序,我们分发到 standby 节点之后,它可以不按照 primary 节点提交的顺序进行提交,只需要保证和集群的数据的一致性即可。
2. 在流量小的时候不存在任何的性能问题。当流量突增时,如果集群中某些节点的写入吞吐量比其他节点少,尤其是小于 primary 节点,则这些节点的数据和 primary 节点的数据存在偏差。比如,在我们的集群当中,某一个集群,如果它的服务器的性能存在一个差异,就会存在一个性能的问题。
3. 在单主模式的集群中,如果发生故障转移,在新的 primary 节点可以立刻接受写入请求的情况下,则存在集群内事务一致性的问题。
4. 当集群扩容时,例如由3节点集群扩容到5节点集群:
(1)无论采用 clone 的方式还是用 xtrabackup 做全量数据恢复后,都避免不了在集群扩容期间产生的增量数据以二进制日志的方式来追平。
(2)若新扩容的节点配置较低,写入吞吐差,则新加入的节点很有可能一直处于 recover 的状态,该节点很难达到 online 的状态,接受新的读写请求。
六.事务一致性保证
在我们进行高可用切换之后,它存在一个事务一致性保证,因为 standby 和 primary 之间存在一个追数据的过程。在数据没有追平的状态下,可能会业务数据,读到一个 du 的数据,我们可以根据group_replication_consistency 这个参数,根据对应的可选值进行一个调整。那么,它有5个值。要根据不同的级别,选择适应我们产品的值。具体如何选择取决于我们业务上是处于读多写少,还是读少写多,或者读写均衡的请求。不同的场景选择不同的值即可。
group_replication_consistency:
- EVENTUAL:
开启该级别的事务( T2 ),事务执行前不会等待先序事务( T1 )的回放完成,也不会影响后序事务等待该事务回放完成。
- before:
开启了该级别的事务( T2 ),在开始前首先要等待先序事务( T1 )的回放完成,确保此事务将在最新的数据上执行。
- AFTER:
开启该级别的事务( T1 ),只有等该事务回放完成。其他后序事务(T2)才开始执行,这样所有后序事务都会读取包括其更改的数据库状态,而不管它们在哪个节点上执行。
-BEFORE_AND_AFTER:
开启该级别等事务( T2 ),需要等待前序事务的回放完成( T1 );
同时后序事务( T3 )等待该事务的回放完成
-BEFORE_ON_PRIMARY_FAILOVER:
在发生切换时,连到新主的事务会被阻塞,等待先序提交的事务回放完成;
这样确保在故障切换时客户端都能读取到主服务器上的最新数据,保证了一致性。
七.流控机制
有性能问题就有对应的解决方案, MGR 的流控机制很好地解决了这个问题。
1.流控机制试图解决以下问题:
(1)集群内节点之间不会相差太多的事务;
(2)快速适应集群内不断变化的负载,例如集群内的写压力暴增中增加更多的节点;
(3)均分可用写容量到集群内的所有节点上;
(4)避免减少吞吐量而造成资源浪费。
2.两个基本机制
(1)监控集群内所有节点以收集有关吞吐量和队列大小的一些统计信息,以便对每个节点能承受的最大携入压力进行有根据的评估;
(2)对集群中的所有节点的并发写能力时刻保持监控,一旦某节点的并发压力超过了集群中所有节点的平均写能力,就会对其执行流量控制。
3.两个基本队列
认证队列和二进制日志应用队列,当其中一个队列的大小超过用户定义的阈值时,就会触发流量控制机制。
对于流量控制配置:
首先,需要选择对谁配置流量控制,是对认证队列、还是针对应用队列、还是两者都需要配置流量控制。然后,对需要配置流量控制的对象(认证队列和应用队列)设置流量控制阈值。
4.流控过程
(1)将根据上一阶段延迟的事务数量逐步减少10%,让触发限流机制的队列减小到限流机制被触发的阈值之内,待恢复后,为避免在队列大小超过阈值时出现吞吐量的陡增,在此之后,每个时间段的吞吐量只允许增长相同的10%。
(2)当前的限流机制不会影响到触发限流机制阈值内的事务,但是会延迟应用超过阈值的事务,直到本监控周期结束。
(3)如果触发节流机制的阈值设置的非常小,部分事务的延迟可能会接近一个完整的监控周期。因为在整个流控的监控过程中,它会以每一个周期来获取监控的数据。
八.适用场景
在生产中, MGR 的一些典型使用场景:
1.弹性复制:
需要非常灵活的复制基础设施的环境,其中 MySQL Server 的数量必须动态增加或减少,我们需要集群能够动态地扩容或者缩容,
并且在增加或减少 Server 的过程中,对业务的副作用尽可能少。例如,云数据库服务。
2.高可用分片:
分片是实现写扩展的一种流行方法。基于 MGR 实现的高可用分片,其中每个分片都会映射到一个复制组上(逻辑上需要一一对应,但在物理上一个复制组可以承载多个分片)。
3.替代主从复制:
在某些情况下,使用一个主库会造成单点争用。在某些情况下,向整个组内的多个成员同时写入数据,多主模式就可以避免单点争用,对应用来说可能伸缩性更强。
九.高可用方案
我们业内常用的高可用方案
通常,在我们的云数据库里边,比如说一个3节点的 MGR 集群。 MGR 本身并不能保证业务的重叠性,写入重叠性。
在 MGR 集群上面加一个读写分析的中间件,比如, maxsc ale 读写中间件。
我们将源代码重新编写进去后,我们会打开一个其自带的岛国机制, maxsc ale 会自动探查 MGR 里面的 primariy 节点的状态,如果发生高可用切换或者当前的 primariy 节点宕机之后,它会重新探测选举出来一个新的 primariy 节点,然后自动将我们业务读写请求重新上传到新的 primariy 节点上面。
我们只需要将 client 端经过 SQL 解析连接到 maxsc ale 上面,然后进入 maxsc ale 做一个路由转发,即可实现一个灵活的高可用。