群组复制MySQL Group Replication

2020-09-28 15:17:07 浏览数 (1)

在通常的IT环境下,如果需要保证系统连续不断的运行,需要创建一个容错系统。最常见方法是使用冗余的组件,即使是部分组件出现故障,系统也能够继续按预期运行。基于这种要求,带来了一系列挑战,系统的复杂性非常高。对于数据库来说,不仅仅是管理一台服务器,而且需要维护和管理多台服务器。除了保证系统持续可用以外,还必须解决常见的分布式系统问题,例如网络分区或脑裂情况。

分布式数据库面临的挑战是如何将数据库和数据复制的逻辑与多个服务器间进行一致性协调的逻辑相融合。也就是说,要让多个服务器根据系统的状态以及系统所经历的每一次数据更改达成一致。可以将其概括为使服务器在每个数据库状态转换上都达成协议,从而使它们都作为一个数据库执行,或者最终它们达到同一状态。这意味着它们需要作为(分布式)状态机运行。

MySQL群组复制为分布式状态机复制提供了服务器之间的强大协调能力。服务器属于同一组时,它们会自动进行协调。该群组可以在单主模式下运行,其中仅有一个服务器接受更新处理。或者,在多主模式下运行,在该模式下,所有服务器都可以同时接受更新处理。

群组复制包括一个内置的组成员资格服务,可以使群组的视图保持一致,并且在任何给定时间点均可用于所有服务器。服务器可以离开并加入该组,视图将相应更新。有时服务器可能会意外离开该组,在这种情况下,故障检测机制会自动检测到此情况,并通知群组视图已更改。

群组复制还有一个内置的脑裂保护机制,对于要提交的事务,群组的大多数成员必须在全局事务顺序中就给定事务的顺序达成一致。每个服务器分别决定提交或中止事务,但是所有服务器都做出相同的决定。如果存在网络分区,导致成员无法达成协议,那么系统将无法继续运行。

所有这些均由群组通信系统(GCS)协议提供支持。它提供故障检测机制,组成员资格服务以及安全有序的消息传递。这些属性是创建系统的关键,该系统可确保在服务器组之间一致地复制数据。该技术的核心是基于Paxos算法的实现。它作为群组通信引擎。

主从复制

传统的MySQL复制提供了一种简单的主从复制方法。有一个主服务器,有一个或多个从服务器。主数据库执行事务,将其提交,然后(因此异步)将它们发送到从据库,以重新执行(基于语句的复制中)或应用(在基于行的复制中)。这是一个非共享系统,默认情况下所有服务器都具有数据的完整副本。

半同步复制,它添加了一个同步步骤。这意味着主服务器在提交时等待从服务器确认已接收到事务。只有这样,主服务器才会恢复提交操作。

半同步复制,它添加了一个同步步骤。这意味着主服务器在提交时等待从服务器确认已接收到事务。只有这样,主服务器才会恢复提交操作。

群组复制场景的示例

以下示例是群组复制的典型用例。

· 弹性复制 -需要非常流畅的复制基础架构的环境,其中服务器的数量必须动态增加或减少,并且副作用要尽可能少。例如,用于云的数据库服务。

· 高度可用的分片 -分片是实现写入横向扩展的一种流行方法。使用MySQL群组复制来实现高度可用的分片,其中每个分片都映射到一个复制组。

· 主从复制的替代方法 -在某些情况下,使用单个主服务器会成为单个竞争点。在某些情况下,写给整个群组可能会更具扩展性。

· 自治系统 -为了使用自动化功能部署MySQL群组复制。

多主模式和单主模式

群组复制以单主模式或多主模式运行。群组的模式是一个群组范围的配置设置,由group_replication_single_primary_mode 系统变量指定,所有成员都必须相同。ON表示单主模式,这是默认模式,OFF表示多主模式。

群组复制运行时,不能手动更改group_replication_single_primary_mode的值。在MySQL 8.0.13中,可以使用 group_replication_switch_to_single_primary_mode()group_replication_switch_to_multi_primary_mode() UDF在群组复制仍在运行时,将群组从一种模式移至另一种模式。这些UDF管理更改群组模式的过程,并确保数据的安全性和一致性。在早期版本中,要更改群组的模式,必须停止群组复制并更改所有成员上的group_replication_single_primary_mode值。然后对群组进行完全重新引导(服务器使用group_replication_bootstrap_group=ON进行引导以实施对新操作配置的更改)。

群组复制不会处理客户端故障转移。这必须由诸如MySQL Router 8.0的中间件,代理,连接器或应用程序本身来处理。

单主模式

在单主模式(group_replication_single_primary_mode=ON)中,该组有一个设置为读写模式的主服务器。组中的其他成员都设置为只读模式(super-read-only=ON)。主服务器通常是引导该组的第一台服务器。加入该组的所有其他服务器将与主服务器通信,并自动设置为只读模式。

在单主模式下,群组复制强制将一台服务器用于数据写入,与多主模式相比,一致性检查的严格性较低,并且不需要特别小心地处理DDL语句。通过选项 group_replication_enforce_update_everywhere_checks 启用或禁用群组的严格一致性检查。在单主模式下部署或将群组更改为单主模式时,必须将此系统变量设置为 OFF

选定主服务器的成员可以通过以下方式进行更改:

· 如果现有的主数据库自愿或意外离开该组,则会自动选择一个新的主数据库。

· 可以使用group_replication_set_as_primary() UDF 任命特定成员作为新的主数据库。

· 如果使用group_replication_switch_to_single_primary_mode() UDF将以多主模式运行的群组更改为以单主模式运行,将自动选举一个新的主数据库,或者可以通过用UDF指定新的主数据库。

仅当所有组成员都运行MySQL 8.0.13或更高版本时,才能使用UDF。自动选择新的主服务器或手动指定新的主服务器时,它会自动设置为可读写,而其他组成员将保持为从服务器,并保持只读状态。如下图:

选举或任命新的主服务器时,可能会有一些数据应用积压(旧的主服务器上已经应用的更改)。在这种情况下,读写事务可能会导致冲突并回滚,而只读事务可能会导致读取旧数据,直到新的主服务器赶上旧的主服务器。群组复制可以通过流量控制机制最大程度地减少快速成员和慢成员之间的差异。从MySQL 8.0.14开始,还可以使用 group_replication_consistency 系统变量,用于配置组的事务一致性级别,以防止出现此问题。设置 BEFORE_ON_PRIMARY_FAILOVER(或任何更高的一致性级别)将新事务保留在新选出的主服务器上,直到应用了数据积压。如果没有为群组使用流量控制和事务一致性保证,最佳实践是在将新的主应用程序重新路由到主服务器之前,等待新主服务器应用其复制相关的中继日志。

选举主成员算法

自动选举过程包括每个成员查看组的最新视图,潜在的新主成员排序,选择最合适的成员。每个成员都按照其MySQL Server版本中的主成员选举算法在本地做出自己的决定。由于所有成员都必须做出相同的决定,因此,如果其他组成员正在运行较低版本的MySQL Server,则成员将调整其主要选举算法,从而使其与该组中拥有最低MySQL Server版本的成员具有相同的行为。

成员按顺序选举主成员时考虑的因素如下:

1. 考虑的第一个因素是哪个或哪些成员运行最低的MySQL Server版本。如果所有组成员都在运行MySQL 8.0.17或更高版本,则首先按其发行版的补丁程序对成员进行排序。如果任何成员运行的是MySQL Server 5.7或MySQL 8.0.16或更低版本,则首先按其发行版的主版本对成员进行排序,并且忽略补丁程序版本。

2. 如果有多个成员正在运行最低的MySQL Server版本,则考虑的第二个因素是每个成员的成员权重,具体由成员上的系统变量group_replication_member_weight指定。如果组中的任何成员正在运行MySQL服务器5.7(该系统变量不可用),将忽略此因素。

group_replication_member_weight 系统变量指定在0-100范围内的数。所有成员的默认权重均为50,将权重设置为低于该权重以降低其排序,将权重设置为高于该权重以增加其排序。可以使用此功能来优先使用更好的硬件,或确保在计划的主要维护期间将故障转移到特定成员。

3. 如果有多个成员正在运行最低的MySQL Server版本,并且多个成员中具有最高成员权重(或忽略了成员权重),则考虑的第三个因素是每个成员所生成的服务器UUID的词典顺序,由系统变量server_uuid指定。服务器UUID最低的成员被选为主服务器。

查找主数据库

要了解以单主服务器模式部署时当前是哪个服务器,请使用performance_schema.replication_group_members表中的MEMBER_ROLE列。例如:

选举或任命新的主服务器时,可能会有一些数据应用积压(旧的主服务器上已经应用的更改)。在这种情况下,读写事务可能会导致冲突并回滚,而只读事务可能会导致读取旧数据,直到新的主服务器赶上旧的主服务器。群组复制可以通过流量控制机制最大程度地减少快速成员和慢成员之间的差异。从MySQL 8.0.14开始,还可以使用 group_replication_consistency 系统变量,用于配置组的事务一致性级别,以防止出现此问题。设置 BEFORE_ON_PRIMARY_FAILOVER(或任何更高的一致性级别)将新事务保留在新选出的主服务器上,直到应用了数据积压。如果没有为群组使用流量控制和事务一致性保证,最佳实践是在将新的主应用程序重新路由到主服务器之前,等待新主服务器应用其复制相关的中继日志。

选举主成员算法

自动选举过程包括每个成员查看组的最新视图,潜在的新主成员排序,选择最合适的成员。每个成员都按照其MySQL Server版本中的主成员选举算法在本地做出自己的决定。由于所有成员都必须做出相同的决定,因此,如果其他组成员正在运行较低版本的MySQL Server,则成员将调整其主要选举算法,从而使其与该组中拥有最低MySQL Server版本的成员具有相同的行为。

成员按顺序选举主成员时考虑的因素如下:

1. 考虑的第一个因素是哪个或哪些成员运行最低的MySQL Server版本。如果所有组成员都在运行MySQL 8.0.17或更高版本,则首先按其发行版的补丁程序对成员进行排序。如果任何成员运行的是MySQL Server 5.7或MySQL 8.0.16或更低版本,则首先按其发行版的主版本对成员进行排序,并且忽略补丁程序版本。

2. 如果有多个成员正在运行最低的MySQL Server版本,则考虑的第二个因素是每个成员的成员权重,具体由成员上的系统变量group_replication_member_weight指定。如果组中的任何成员正在运行MySQL服务器5.7(该系统变量不可用),将忽略此因素。

group_replication_member_weight 系统变量指定在0-100范围内的数。所有成员的默认权重均为50,将权重设置为低于该权重以降低其排序,将权重设置为高于该权重以增加其排序。可以使用此功能来优先使用更好的硬件,或确保在计划的主要维护期间将故障转移到特定成员。

3. 如果有多个成员正在运行最低的MySQL Server版本,并且多个成员中具有最高成员权重(或忽略了成员权重),则考虑的第三个因素是每个成员所生成的服务器UUID的词典顺序,由系统变量server_uuid指定。服务器UUID最低的成员被选为主服务器。

查找主数据库

要了解以单主服务器模式部署时当前是哪个服务器,请使用performance_schema.replication_group_members表中的MEMBER_ROLE列。例如:

群组复制是最终的一致性系统。这意味着一旦传入流量减慢或停止,所有组成员将具有相同的数据内容。当流量在流动时,可以先在某些成员上对事务进行外放,特别是在某些成员的写入吞吐量比其他成员少的情况下,这会导致过时的读取。在多主数据库模式下,速度较慢的成员还可能积压过多的事务,从而导致更大的冲突和认证失败风险。为了限制这些问题,可以激活和调整群组复制的流量控制机制,以最大程度地减少快慢成员之间的差异。从MySQL 8.0.14开始,如果要为组中的每个事务都拥有一个事务一致性保证,可以使用系统变量group_replication_consistency来做到这一点。可以选择适合群组工作量和数据读取/写入优先级的设置,同时需要考虑提高一致性的同步对性能的影响。还可以为单个会话设置系统变量,以保护对并发敏感的事务。

事务检查

在多主模式下部署群组时,将检查事务以确保它们与该模式兼容。在多主模式下部署群组复制时,将进行以下严格的一致性检查:

· 如果事务在SERIALIZABLE隔离级别下执行,在与组同步时,其提交将失败。

· 如果事务是针对具有级联约束的外键的表执行的,在与组同步时,其提交将失败。

检查由group_replication_enforce_update_everywhere_checks系统变量控制。在多主模式下,通常应将系统变量设置为ON,但是可以选择将系统变量设置为来禁用检查OFF。在单主要模式下部署时,系统变量必须设置为OFF

数据定义语句

在多主模式下的群组复制拓扑中,执行数据定义语句(DDL)时需要格外小心。

MySQL 8.0引入了对原子数据定义语言(DDL)语句的支持,其中完整的DDL语句作为单个原子事务被提交或回滚。但是DDL语句(原子或其他方式)隐式结束当前会话中处于活动状态的所有事务,相当于在执行该语句之前进行了COMMIT操作一样。这意味着DDL语句不能在另一个事务内,在诸如START TRANSACTION ... COMMIT的事务控制语句内执行,也不能与同一事务内的其他语句组合。

群组复制基于乐观复制,乐观执行语句,并在必要时回滚。每个服务器执行时都不会首先确保群组协议的安全。因此,在多主模式下复制DDL语句时,需要格外小心。如果对同一对象进行模式更改(使用DDL)并更改对象包含的数据(使用DML),当模式操作尚未完成并在各处复制时,需要通过同一服务器处理更改。否则,当操作中断或仅部分完成时,可能导致数据不一致。

版本兼容性

为了获得最佳兼容性和性能,群组中的所有成员应运行相同版本的MySQL Server,因此应运行相同版本的群组复制。在多主模式下,这更为重要,因为所有成员通常都将以读写模式加入该组。如果组中包含多个MySQL Server版本的成员,某些成员可能与其他成员不兼容,因为它们支持其他成员不具备的功能或缺少其他成员具有的功能。为了防止这种情况,当新成员加入(包括之前已升级并重新启动的成员)时,该成员将对组中的其余成员进行兼容性检查。

这些兼容性检查的结果在多主模式下尤其重要。如果加入成员所运行的MySQL Server版本高于现有组成员所运行的最低版本,则它将加入该组,但保持只读模式。(在单主模式运行的组中,无论如何,新添加的成员在任何情况下均默认为只读。)运行MySQL 8.0.17或更高版本的成员在检查兼容性时会考虑该发行版的补丁程序版本。运行MySQL 8.0.16或更低版本或MySQL 5.7的成员仅考虑主要版本。

在具有使用不同MySQL Server版本的成员的多主模式下运行的群组中,群组复制自动管理运行MySQL 8.0.17或更高版本的成员的读写状态。如果成员离开该组,则运行当前最低版本的成员将自动设置为读写模式。当您将以单主模式运行的组更改为以多主要模式运行时,请使用 group_replication_switch_to_multi_primary_mode() UDF,群组复制会自动将成员设置为正确的模式。如果成员运行的MySQL服务器版本高于组中存在的最低版本的成员,则成员将自动置于只读模式,而运行最低版本的成员将处于读写模式。

群组复制服务

组成员身份

在MySQL群组复制中,一组服务器构成一个复制组。群组具有名称,该名称采用UUID的形式。群组是动态的,服务器可以随时离开(自愿或非自愿)并加入。每当服务器加入或离开时,群组都会进行自我调整。

如果服务器加入该组,它将通过从现有服务器获取丢失的状态来使自己更新至最新状态。如果服务器离开了该组,例如已被拆除以进行维护,则其余服务器会注意到该服务器已离开并自动重新配置该组。

群组复制具有组成员资格服务,该服务定义了哪些服务器处于联机状态并参与该组。联机服务器列表称为视图。组中的每台服务器都具有一致的视图,即在给定的时间哪些成员是积极参与组的服务器。

组成员不仅必须就事务提交达成共识,而且必须就当前视图达成一致。如果现有成员同意将新服务器纳入组,则重新配置该组将新服务器集成到其中,从而触发视图更改。如果服务器自愿离开该组,则该组将重新动态排列其配置,并触发视图更改。

在成员自愿离开组的情况下,它首先启动动态组重新配置,在此期间,所有成员必须在不离开服务器的情况下就新视图达成一致。但是,如果成员非自愿离开该组,例如由于该成员意外停止或网络连接断开,它将无法启动重新配置。在这种情况下,群组复制的故障检测机制会在短时间内识别出该成员已离开,并提出重新配置不包含故障成员的群组。与自愿退出的成员一样,重新配置需要组中大多数服务器的同意。但是,如果小组无法达成协议,例如,由于它的分区方式使得大多数服务器都不在线,因此系统无法动态更改配置,以防止出现脑裂情况。这种情况需要管理员的干预。

成员可能会短暂脱机,并尝试再次重新加入该组。在这种情况下,重新加入的成员会忘记其先前的状态,但是如果其他成员向其发送旨在用于其崩溃前状态的消息,则可能导致出现问题,可能出现数据不一致。如果处于这种情况的成员参加XCom的共识协议,则有可能导致XCom通过在失败前后做出不同的决定来为同一共识回合提供不同的价值。

为了应对这种可能性,从MySQL 5.7.22和MySQL 8.0开始,服务器在加入组时会被赋予唯一的标识符。这样,群组复制就可以了解以下情况:同一台服务器的新化身(具有相同的地址,但有一个新的标识符)正试图加入该组,而旧实例仍被列为成员。新的化身被阻止加入该组,直到可以通过重新配置将旧的化身移除为止。如果系统变量group_replication_member_expel_timeout已设置为允许成员有更多时间在被驱逐之前返回到该组,被怀疑的成员可以重新加入,只要它实际上并未失败即可。如果群组复制在服务器上停止并重新启动,则该成员将成为新的化身,并且在怀疑超时之前不能重新加入。

故障检测

群组复制包括故障检测机制,该机制能够找到并报告哪些服务器处于静默状态,并因此认为已死机。总体而言,故障检测器是一种分布式服务,可提供有关哪些服务器可能死机(怀疑)的信息。服务器静音时会触发怀疑。如果服务器A在给定时间段内未收到来自服务器B的消息,则会发生超时并引起怀疑。之后,如果群组同意这种怀疑可能是真的,那么该组将确定给定的服务器发生了故障。这意味着组中的其余成员将做出协调决策以排除给定成员。

如果服务器与组中的其他服务器隔离,则它怀疑所有其他服务器均已失败。无法与该组达成协议(因为它无法达到法定人数),因此对其怀疑不会产生任何后果。通过这种方式将服务器与组隔离时,它将无法执行任何本地事务。

容错

MySQL群组复制建立在Paxos分布式算法之上实现,以提供服务器之间的分布式协调。因此,它需要大多数服务器处于活动状态才能达到法定人数,从而做出决定。这直接影响了系统可以容忍的故障数量,而不会损害自身及其整体功能。容忍f 故障所需的服务器数量(n)为n = 2 x f 1

实际上,这意味着要容忍一个故障,该组中必须包含三台服务器。这样一来,如果一台服务器发生故障,仍然会有两台服务器形成多数(三分之二),并使系统继续自动做出决定并继续运行。但是,如果第二台服务器发生故障,则该组(仅剩一台服务器)将被阻挡,因为没有多数服务器可以决定。

下表是说明上述公式的内容。

可观察性

群组复制插件中内置了许多自动化功能。有时可能需要了解幕后发生的事情。群组复制和性能模式的检测变得很重要。可以通过Performance Schema表查询系统的整个状态(包括视图,冲突统计信息和服务状态)。可以连接到组中的单个服务器,并通过在与群组复制相关的Performance Schema表上执行select语句来获取本地和全局信息。

群组复制插件体系结构

MySQL Group Replication是一个MySQL插件,它基于现有的MySQL复制基础结构,并利用了二进制日志,基于行的日志记录和全局事务标识符等功能。它与当前的MySQL框架集成,例如Performance Schema或插件和服务基础结构。下图提供了一个框图,描述了MySQL群组复制的总体体系结构。

群组复制插件框图

MySQL群组复制插件包括一组用于捕获,应用和生命周期的API,这些API控制插件如何与MySQL Server交互。有一些接口可以使信息从服务器流向插件,反之亦然。这些接口将MySQL Server核心与群组复制插件隔离开,并且大多数是放置在事务执行管道中的钩子。在一个方向上,从服务器到插件,会有事件通知,例如服务器启动,服务器恢复,服务器准备接受连接以及服务器即将提交事务。另一方面,插件会指示服务器执行诸如提交或中止正在进行的事务,或将事务存储在中继日志的队列中。

群组复制插件体系结构的下一层是一组组件,这些组件在将通知路由到它们时会做出反应。捕获组件负责跟踪与正在执行的事务相关的上下文。应用程序组件负责在数据库上执行远程事务。恢复组件管理分布式恢复,并负责选择捐献者,管理追赶程序并对捐献者的故障做出反应来使加入群组的服务器保持最新状态。

复制协议模块包含复制协议的特定逻辑。它处理冲突检测,接收事务并将其传播到该组。

群组复制插件体系结构的最后两层是组通信系统(GCS)API,以及基于Paxos的组通信引擎(XCom)的实现。GCS API是一个高级API,它抽象了构建复制状态机所需的属性。因此,它将消息传递层的实现与插件的其余上层分离。组通信引擎处理与复制组成员的通信。

0 人点赞