• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 处理一致性保证

    诸如组复制之类的分布式系统的主要含义之一是它作为一个组提供的一致性保证。换句话说,在组成员之间分布的事务的全局同步的一致性。本节介绍了组复制如何根据组中发生的事件处理一致性保证,以及如何最好地配置组的一致性保证。


    了解处理一致性保证

    在正常操作或故障修复操作中,就分布式一致性保证而言,组复制一直都是最终的一致性系统。这意味着一旦传入流量减慢或停止,所有组成员将具有相同的数据内容。与系统一致性相关的事件可以分为控制操作,可以是手动操作,也可以由故障自动触发。和数据流操作。

    对于组复制,可以评估一致性的控制操作是:

    • 组复制的“分布式恢复”和写保护所涵盖的成员加入或离开。
    • 防护模式涵盖的网络故障。
    • 在单主要组中,主要故障转移也可以由触发group_replication_set_as_primary()

    一致性保证和主要故障转移

    在单主服务器组中,如果将主服务器提升为主服务器时发生主服务器故障转移,则无论复制积压的大小如何,都可以立即使新的主服务器可用于应用程序流量,或者可以对其进行访问被限制,直到积压已被应用。

    使用第一种方法,组可以在最主要的故障之后花费最短的时间来确保稳定的组成员身份,方法是选择一个新的主要数据库,然后在仍旧应用来自旧主要数据库的任何待办事项时立即允许数据访问。确保写入一致性,但是在新的主数据库应用积压工作时,读取可以临时检索陈旧数据。例如,如果客户端C1 A=2 WHERE A=1刚好在旧的主节点发生故障之前就在其上进行写操作,则当客户端C1重新连接到新的主节点时,它可能会读取A=1直到新的主节点应用其积压并赶上旧的主节点在离开主节点之前的状态。组。

    使用第二种方法,系统可以在主要故障后确保稳定的组成员身份,并以与第一种方法相同的方式选择新的主要方法,但是在这种情况下,组将等待直到新的主要方法应用所有待办事项,然后才执行允许数据访问。这确保了在如上所述的情况下,当客户端C1重新连接到新的主服务器时,它将读取A=2。但是,需要权衡的是,故障转移所需的时间与待办事项的大小成正比,在正确配置的组上,应小。

    在MySQL 8.0.14之前,无法配置故障转移策略,默认情况下,如第一种方法中所述,可用性已最大化。在成员运行MySQL 8.0.14及更高版本的组中,可以使用group_replication_consistency变量配置成员在主要故障转移期间提供的事务一致性保证级别。参见一致性对初选的影响。

    数据流操作

    由于对组执行读写操作,因此数据流与组一致性保证有关,尤其是当这些操作分布在所有成员上时。数据流操作适用于组复制的两种模式:单主模式和多主模式,但是为了使说明更清楚,它仅限于单主模式。在单个主要组的成员之间划分传入的读取或写入事务的通常方法是将写入路由到主要组,然后将读取平均分配给次要组。由于该组应表现为单个实体,因此可以合理地预期在主数据库上的写入可在次数据库上即时获得。尽管组复制是使用实现Paxos算法的组通信系统(GCS)协议编写的,但是组复制的某些部分是异步的,这意味着数据被异步应用于次级。这意味着客户端C2可以写B=2 WHERE B=1在主服务器上,立即连接到辅助服务器并阅读B=1。这是因为辅助服务器仍在应用积压,并且尚未应用由主服务器应用的事务。

    处理同步点

    您可以基于要在整个组中同步事务的点来配置组的一致性保证。为了帮助您理解该概念,本节简化了在读操作时或写操作时跨组同步事务的要点。如果数据在读取时已同步,则当前客户端会话将等待直到给定点(可以应用所有先前的更新事务的时间点)才能开始执行。使用这种方法,只影响此会话,不影响所有其他并发数据操作。

    如果数据在写入时已同步,则写入会话将一直等待,直到所有辅助设备都已写入其数据。组复制对写入使用总顺序,因此,这意味着要等待应用此优先级以及所有在辅助队列中的先前写入。因此,在使用此同步点时,写入会话将等待所有辅助队列被应用。

    任何选择都可以确保B=2即使在立即连接到辅助服务器的情况下,在针对客户端C2所述的情况下也始终可以读取。每种选择都有其优点和缺点,这些优点和缺点与系统工作负载直接相关。以下示例描述了不同类型的工作负载,并建议了合适的同步点。

    想象以下情况:

    • 如果要负载平衡读取,而又不对读取的服务器部署其他限制以避免读取过时的数据,则组写入要比组读取少得多。
    • 您有一个主要包含只读数据的组,您希望在提交后将读写事务应用于所有地方,以便对包含最新写入的最新数据进行后续读取。这样可以确保您不必为每个RO事务支付同步成本,而仅对RW事务支付同步成本。

    在这些情况下,您应该选择在写入时进行同步。

    想象以下情况:

    • 如果要平衡读取的内容,而又不对读取的服务器部署其他限制以避免读取过时的数据,则组写入比组读取要普遍得多。
    • 您希望工作负载中的特定事务始终从组中读取最新数据,例如,每当敏感数据更新时(例如文件或类似数据的凭据),并且您想强制执行读取操作,以获取最多的最新数据日期值。

    在这些情况下,您应该选择在读取时进行同步。

    配置事务一致性保证

    虽然处理同步点部分解释,在概念上有从中你可以选择两个同步点:在读或写时,这些条款是一个简化和组复制使用的术语是:之前之后,处理执行。如本节所示,一致性级别可能会对组处理的只读(RO)和读写(RW)事务产生不同的影响。

    • 如何选择一致性级别
    • 一致性级别的影响
    • 连贯性对初选的影响

    以下列表显示了可以使用group_replication_consistency变量在组复制中配置的可能的一致性级别,以提高事务一致性保证的顺序:

    • EVENTUAL

      RO和RW事务都不等待执行之前的事务。这group_replication_consistency是添加变量之前组复制的行为。RW处理不等待其他成员申请处理。这意味着可以先在一个成员上将事务外部化。这也意味着,如果发生主节点故障转移,则新的主节点可以在应用所有先前的主节点事务之前接受新的RO和RW事务。RO事务可能导致过时的值,RW事务可能由于冲突而导致回滚。

    • BEFORE_ON_PRIMARY_FAILOVER

      保留(不应用)具有从旧主数据库应用积压的新选举基数的新RO或RW事务,直到应用了任何积压。这样可以确保在发生主故障转移时,无论有意还是无意,客户端始终可以在主故障上看到最新的值。这保证了一致性,但意味着在应用积压的情况下,客户端必须能够处理延迟。通常,此延迟应最小,但它确实取决于积压的大小。

    • BEFORE

      RW事务在应用之前会等待所有先前的事务完成。RO事务在执行之前会等待所有先前的事务完成。这样可以确保该事务仅通过影响事务的延迟来读取最新值。通过确保仅在RO事务上使用同步,这减少了每个RW事务上同步的开销。此一致性级别还包括所提供的一致性保证BEFORE_ON_PRIMARY_FAILOVER

    • AFTER

      RW事务等待,直到其更改已应用于所有其他成员。此值对RO处理没有影响。此模式确保在将事务提交到本地成员时,任何后续事务都将读取任何组成员上的写入值或更新值。将此模式与主要用于RO操作的组一起使用,以确保已提交的RW事务一旦提交便会应用到任何地方。您的应用程序可以使用它来确保后续读取读取包括最新写入在内的最新数据。这样可以减少每个RO事务的同步开销,通过确保仅在RW事务上使用同步。此一致性级别还包括以下方面提供的一致性保证:BEFORE_ON_PRIMARY_FAILOVER

    • BEFORE_AND_AFTER

      RW事务等待1)所有之前的事务完成,然后再应用; 2)等待其更改已应用于其他成员。RO事务在执行之前会等待所有先前的事务完成。此一致性级别还包括所提供的一致性保证BEFORE_ON_PRIMARY_FAILOVER

    BEFOREBEFORE_AND_AFTER反渗透,RW处理一致性水平可以既使用。该AFTER一致性水平对RO的处理没有影响,因为它们不会产生变化。

    如何选择一致性级别

    不同的一致性级别为两个DBA提供了灵活性,后者可以使用它们来建立其基础结构;以及可以使用最适合其应用程序要求的一致性级别的开发人员。以下方案显示了如何根据使用组的方式选择一致性保证级别:

    • 方案1您想平衡读取的负载而不必担心过时的读取,因此组写入操作比组读取操作要少得多。在这种情况下,您应该选择AFTER
    • 方案2中,您有一个数据集,该数据集应用了大量写入操作,并且您希望偶尔进行读取操作,而不必担心读取过时的数据。在这种情况下,您应该选择BEFORE
    • 方案3中,您希望工作负载中的特定事务始终从组中读取最新数据,以便每当敏感数据更新(例如文件或类似数据的凭据)时,您都想强制执行读取操作,始终读取最新值。在这种情况下,您应该选择BEFORE
    • 方案4中,您有一个主要包含只读(RO)数据的组,您希望在提交后将其读写(RW)事务应用于任何地方,以便对包含以下内容的最新数据进行后续读取:您最近的写入操作并不需要为每个RO事务支付同步,而仅对RW事务进行同步。在这种情况下,您应该选择AFTER
    • 方案5中,您有一个主要包含只读数据的组,希望您的读写(RW)事务始终从该组中读取最新数据,并在提交后将其应用于所有位置,以便后续读取对包括您的最新写入的最新数据执行此操作,并且您无需为每个只读(RO)事务支付同步,而仅对RW事务进行同步。在这种情况下,您应该选择BEFORE_AND_AFTER

    您可以自由选择实施一致性级别的范围。这很重要,因为如果将一致性级别设置为全局范围,则一致性级别可能会对组性能产生负面影响。因此,您可以通过group_replication_consistency在不同作用域使用系统变量来配置组的一致性级别。

    要在当前会话上实施一致性级别,请使用会话范围:

    > SET @@SESSION.group_replication_consistency= 'BEFORE';
    

    要在所有会话上强制执行一致性级别,请使用全局范围:

    > SET @@GLOBAL.group_replication_consistency= 'BEFORE';
    

    在特定会话上设置一致性级别的可能性使您可以利用以下方案:

    • 场景6:给定的系统处理了几条不需要很强的一致性级别的指令,但是一种指令确实需要很强的一致性:管理对文档的访问权限;在这种情况下,系统将更改访问权限,并且要确保所有客户端都看到正确的权限。您只需要按照SET @@SESSION.group_replication_consistency=‘AFTER’这些说明进行操作,而将其他说明保留EVENTUAL在全局范围内运行即可。
    • 方案7在方案6中描述的同一系统上,每天一条指令需要进行一些分析处理,因此,它需要始终读取最新数据。为此,您只需要SET @@SESSION.group_replication_consistency=‘BEFORE’遵循该特定说明即可。

    总而言之,您不需要运行具有特定一致性级别的所有事务,尤其是在仅某些事务实际需要它的情况下。

    请注意,所有读写事务在组复制中都是完全有序的,因此,即使您将AFTER当前会话的一致性级别设置为,该事务也要等到其更改应用于所有成员之后,这意味着要等待此事务以及所有之前的事务在中学的队列中。实际上,一致性级别将AFTER等待所有事务,直到并包括该事务为止。

    一致性级别的影响

    分类一致性级别的另一种方法是根据对组的影响,即一致性级别对其他成员的影响。

    BEFORE一致性水平,除了在处理流被排序,局部构件上只影响。也就是说,它不需要与其他成员进行协调,也不会对他们的处理产生影响。换句话说,BEFORE仅影响使用它的处理。

    AFTERBEFORE_AND_AFTER一致性水平确实有对其他成员执行并发事务的副作用。这些一致性级别使其他成员事务EVENTUAL在具有AFTERBEFORE_AND_AFTER正在执行的事务开始时启动具有一致性级别的事务。AFTER即使其他成员的事务具有EVENTUAL一致性级别,其他成员也要等到事务在该成员上提交后再进行。换句话说,AFTERBEFORE_AND_AFTER影响所有ONLINE小组成员。

    为了进一步说明这一点,请想象一个由3个成员M1,M2和M3组成的组。客户在成员M1上发出:

    > SET @@SESSION.group_replication_consistency= AFTER;
    > BEGIN;
    > INSERT INTO t1 VALUES (1);
    > COMMIT;
    

    然后,在应用以上事务时,客户在成员M2上发出:

    > SET SESSION group_replication_consistency= EVENTUAL;
    

    在这种情况下,即使第二个事务的一致性级别为EVENTUAL,因为它在第一个事务已经在M2上的提交阶段时开始执行,所以第二个事务必须等待第一个事务完成提交,才可以执行。

    您只能使用一致性级别BEFOREAFTER并且BEFORE_AND_AFTERONLINE成员上尝试在其他状态的成员上使用它们会导致会话错误。

    EVENTUAL直到wait_timeout达到由值配置的超时(默认为8小时)后,一致性级别才保持执行的事务。如果达到超时,ER_GR_HOLD_WAIT_TIMEOUT将引发错误。

    连贯性对初选的影响

    本节描述组的一致性级别对选择了新主数据库的单主数据库组的影响。这样的组会自动检测故障并调整活动成员的视图,换句话说,成员资格配置。此外,如果以单主要模式部署组,则只要该组的成员资格发生更改,就会执行检查以检测该组中是否仍然存在主要成员。如果没有,则从辅助成员列表中选择一个新成员。通常,这被称为二次促销。

    考虑到系统检测到故障并自动进行自我重新配置的事实,用户可能还希望升级后,新的主数据库在数据方面与旧的数据库处于准确的状态。换句话说,一旦用户能够读取和写入新主数据库,则该用户可能希望不存在要应用到新主数据库上的复制事务的积压。实际上,用户可能希望一旦他的应用程序故障转移到新的主数据库,就没有机会读取旧数据或写入旧数据记录,即使是暂时的。

    激活流量控制并在组上对其进行适当调整后,升级后立即从新当选的主数据库中短暂读取陈旧数据的可能性很小,这是因为不应存在积压,如果存在积压,则应该很小。此外,您可能具有代理或中间件层,这些层在升级后控制对主数据库的应用程序访问,并在该级别上实施一致性标准。如果您的小组成员使用的是MySQL 8.0.14或更高版本,则可以使用group_replication_consistency变量,它控制新选举的主节点是否阻塞读写,直到完全应用积压后,或者是否以运行MySQL 8.0.13或更早版本的成员的方式运行。如果该group_replication_consistency选项在BEFORE_ON_PRIMARY_FAILOVER要应用积压的新选出的主数据库上设置为,并且在仍在应用积压的新主数据库上发布了事务,则将阻塞传入事务,直到完全应用积压。因此,可以防止以下异常:

    • 对于只读和读写事务,不会过时读取。这样可以防止新的主数据库将陈旧的读取外部化到应用程序中。
    • 由于与仍在待申请的待办事项中的复制读写事务发生读写冲突,因此不会发生针对读写事务的虚假回滚。
    • 读写事务不存在读取偏斜,例如:

      > BEGIN;
      > SELECT x FROM t1; -- x=1 because x=2 is in the backlog;
      > INSERT x INTO t2;
      > COMMIT;
      

      该查询不应引起冲突,但应写出过时的值。

    总而言之,group_replication_consistency将设置为时,BEFORE_ON_PRIMARY_FAILOVER您选择的是优先考虑一致性而不是可用性,因为无论何时选择新的主数据库,都会进行读写操作。这是在配置组时必须考虑的权衡。还应记住,如果流控制正常运行,则积压应该最少。请注意,较高的一致性级别BEFOREAFTER并且BEFORE_AND_AFTER还包括所提供的一致性保证BEFORE_ON_PRIMARY_FAILOVER

    为了确保组提供相同的一致性级别,而不考虑将哪个成员提升为主要成员,该组的所有成员都应保持BEFORE_ON_PRIMARY_FAILOVER(或更高的一致性级别)其配置。例如,在每个成员问题上:

    > SET PERSIST group_replication_consistency='BEFORE_ON_PRIMARY_FAILOVER';
    

    这样可以确保成员的行为均相同,并且在重新启动成员后仍保留配置。

    尽管在使用BEFORE_ON_PRIMARY_FAILOVER一致性级别时将保留所有写入,但不会阻止所有读取,以确保在升级后服务器在应用积压时仍可以检查服务器。这对于调试,监视,可观察性和故障排除很有用。允许一些不修改数据的查询,例如:

    • SHOW陈述
    • SET陈述
    • DO陈述
    • EMPTY陈述
    • USE陈述
    • SELECTperformance_schemasys数据库使用语句
    • SELECT对数据库中的PROCESSLIST表使用语句infoschema
    • SELECT不使用表或用户定义函数的语句
    • STOP GROUP_REPLICATION陈述
    • SHUTDOWN陈述
    • RESET PERSIST陈述

    事务不能永远被保留,并且如果保留的时间超过了wait_timeout它,则会返回ER_GR_HOLD_WAIT_TIMEOUT 错误。