18 KiB
Mysql Group Replication
Mysql Group Replication可以用于创建弹性、高可用、有容错的replication拓扑。
groups可以在single-primary mode下进行执行,其支持自动的primary选举,在同一时刻只有一个server接收更新操作。
另外,groups也支持multi-primary mode部署,此时所有servers都能够接收写操作,即使多个写请求是并行发送的。
MGR存在一个内置的group membership service,其在任一时刻都能为所有servers提供一致且可用的组视图。server可以加入和离开group,group view也会随之改变。在某些时刻,server可能非预期的离开group,在这种情况下failure detection机制将会自动感知并通知group去更新group view。
group replication是作为mysql server的插件被提供的。可以通过Innodb Cluster来部署mysql server instances group。
为了部署多个mysql实例,可以使用Innodb Cluster,其能够通过Mysql Shell轻松的管理mysql server实例组。Innodb Cluster和Mysql Router无缝集成,在应用连接到集群式,无需在应用中编写failover流程。
Group Replication Background
创建有容错性系统的最常用方式是采用冗余组件的方案,即使组件被移除,系统仍可按预期继续运行。这样将会增加系统的复杂性,特别的,replicated databases必须维护和管理多台server;并且,servers以集群的方式对外提供服务,还需要处理其他若干的经典分布式系统问题:如network partition或split brain问题。
mysql group replication提供了distributed state machine replication,并保证了servers间的强协同;server在作为同一group的一部分,会自动的彼此之间进行协调。
对于待提交的事务,majority of group必须就事务在global transactions中的顺序达成一致。决定事务commit或abort是由每个server单独处理的,但是所有server中,该事务提交/回滚状态都完全一致。如果存在network partition,导致members不能就transaction order达成一致,那么系统将不能继续处理,直至该问题被解决。故而,MGR中存在内置、自动的split-brain保护机制。
上述所有内容都由GCS(Group Communication System)协议提供,其提供了如下内容
- 故障检测机制
- group membership service
- safe and completely ordered message delivery
上述所有机制都保证了数据在group of servers之间能够被一致的复制。GCS技术的核心基于Paxos算法实现,其用作group communication engine。
Replication Technologies
传统的mysql replication提供了一种简单的source to replica的复制方法:
- source为primary实例
- replica为secondaries实例
source将会应用事务,并对事务进行提交。之后,事务会异步的被发送到replicas,接收到事务的replica会对事务进行重新执行(statement-based replicaion)或被应用(row-based replication)。在默认情况下,所有的server都拥有数据的完整副本。
默认情况下,mysql的异步replication示例图如下:
除此之外,还存在半同步的replication,其在协议中添加了同步步骤。示例如下所示,primary会等待replicas接收到事务并向primary返回ack,在接收到ack后才会执行commit操作。

上面两张图为传统的asynchronous MYSQL replication protocol。
group replication
group replication是一种用于实现fault-tolerant系统的技术。replication group是一系列servers的集合,其中每个server都含有数据的完整副本,servers之间通过message进行交互。
group中的communication layer提供了一系列保证,例如atomic message和total order message delivery。
Mysql Group Replication基于这些特性、抽象,实现了multi-source update everywhere replication protocol。一个replication group由多个server组成,每个server在每时每刻都独立的执行事务。
- read/write事务都只在其被group同意之后才提交;即对于read/write事务,都要由整个group决定其是否能被提交,故而提交操作并不是由源服务器单方面决定的。(read/write transaction代表事务中包含写操作的事务)。
- read-only事务则是不需要group内其他server的协助,立刻就能提交
当read/write事务准备好在源server上提交时,都会原子性的广播write values和write set:
- write values:代表被修改后的整行数据
- write set:被修改数据的唯一标识符
由于transaction是被原子广播的,故而,要么group中所有servers都接收到该事务,要么group中所有servers都未收到该事务。并且,对于所有servers,其接收到的所有事务都相同,并且所有事务按照相同的顺序被接收,并且,会为所有事务建立一个global total order。
但是,事务在不同的servers上并行执行时,可能会发生冲突。在被称为certification的过程中,该冲突通过查看和比较两个不同并行事务的write sets来检测。在certification的过程中,冲突检测在行级别执行:如果两个并行的事务在不同的servers上执行,并且修改了相同的行,那么这将会存在冲突。
该冲突将会按照如下方案被解决:对于在global total order中排序靠前的事务,其将会在所有server上被提交;而排序靠后的事务则是会终止,在源服务器上被提交,并且被group中的其他servers丢弃。
例如,t1和t2在不同的servers上并发执行,两者都修改了同一行,t2的排序在t1之前,那么在冲突中t2将会获胜而t1会回滚。上述规则则是分布式的first commit wins rule。
如果两个事务发生冲突的可能性高于不冲突的可能性,那么最好让其在相同的server上执行,并且通过server的local lock机制来对事务进行同步;而不是在不同的server上执行,并因certification造成回滚。
对于已经被认证的事务进行applying和externalizing,group replicaion允许server在不破坏一致性和有效性的前提下偏离agreed order of the transactions。group replication是一个最终一致性的系统,代表incoming traffic降低或停止时,所有的group members都将包含相同的data content。当traffic较高时,事务可以以稍微不同的顺序进行externalizing,并且,事务在进行externalizing时,在一些servers进行externalizing的时机也可能早于其他servers。(externalizing指的即是实际提交事务并使事务的修改对client可见;applying指的是server应用来自其他server的事务修改)。
例如,在mulit-primary模式下,一个本地事务可能在certification之后立马就被externalized,即使一个来自remote server的transaction在global order中顺序更靠前并且尚未被applied。当certification过程中,多个transactions间不涉及冲突时,该操作是被允许的。
在single-primary模式下,在primary server上,可能小概率会发生并发、非冲突的本地事务按照和global order agreed by group replication的顺序进行提交和externalized。
在不接受来自客户端写入操作的secondaries节点上,事务总是按照agreed order被提交和externalized。
具体mysql group replication protocol的示意图如下所示:

Group replication Use Cases
Group Replication通过将系统状态复制到一组servers,能够创建一个有冗余性的容错系统。即使部分服务器随后fail,只要不是所有或majority发生故障,那么系统仍然可访问。
取决于group中故障server的数量不同,group可能出现性能下降或可拓展性降低的情况,但是整个系统仍然是可用的。server的故障是隔离和独立的,故障由group membership service来进行追踪,其基于分布式的failure detector,该detector能够在任何server自愿退出或异常退出group时发送信号。
在该系统中,无需进行server failover,且multi-source update everywhere的特性确保在单台server故障的场景下,update操作的执行仍然不会受阻。总而言之,mysql group replication保证了数据库服务是持续可用的。
需要认识到的是,即使数据库服务整体是可用的,当server非预期的退出时,连接到该故障server的clients仍然需要被重定向或故障转移到其他server。该处理流程不应由group replication来处理,而是应该由connector/load balancer/router/其他中间件来处理。
总之,mysql group replication提供了一个高可用、高弹性、可靠的mysql服务。
Exmaple Use Cases
如下示例为group replication的典型用例场景:
Elastic Replication: 适用于高灵活度复制结构的环境,servers的数量需要可以动态的增加或缩减,并尽可能的减少副作用Highly Available Shards: sharding是一种实现write scale-out的流行方案,可以使用mysql group replication来实现高可用shards,其中每个shard都被映射到一个replication groupasync source-replica replication的替代方案: 在某些场景下,使用单个source server可能会造成单点争用,向整个group写入在特定场景下则更具有可拓展性(MGR支持多主模式部署,能够在group范围内缓解写压力)
Multi-primary and Single-Primary Modes
Group Replication可以在single-primary或multi-primary模式上工作。该group mode为一个group范围内的配置设置,通过system variable group_replication_single_primary_mode来指定,在所有group members中该variable必须都相同。
ON: 该值代表single-primary mode,也为变量的默认值OFF: 该值代表multi-primary mode
在group中,所有的members其
group_replication_single_primary_mode变量的值都必须相同
在group replication运行时,并无法手动修改group_replication_single_primary_mode的值,但是,在group replication运行时,可以使用group_replication_switch_to_single_primary_mode()和group_replication_switch_to_multi_primary_mode()方法来将group从一个模式切换到另一个模式。这些方法能够修改group的mode,并且确保数据的一致性和安全性。
不管处于哪种mode下,group replciation都不会处理client的failover,其必须由中间件framework例如Mysql Router/proxy/connector/应用本身来处理。
Single-Primary Mode
在single-primary mode(group_replication_single_primary_mode=ON)时,group中只存在一个primary server(被设置为read/write mode)。group中所有其他的members都被设置为read-only mode(super_read_only=ON)。该primary server通常会引导整个集群的启动,所有其他加入到group中的servers都会识别到primary server并且自动被设置为read-only mode.
在single-primary mode时,group replication会强制只有一个server能够向group中写入,相比于multi-primary mode,single-primary mode的数据一致性检查可以不那么严格,DDL statements也无需额外谨慎的处理。
group_replication_enforce_update_everywhere_checks
group_replication_enforce_update_everywhere_checks选项能够启用/禁用对group的严格一致性检查。当在single-primary mode下部署时,或将group的mode修改为single-primary mode时,该system variable的值必须被设置为OFF。
被指定为primary server的member可以按如下方式进行变更:
- 如果该primary正常/非预期退出group,那么新primary的选举将会自动被触发
- 可以通过
group_replication_set_as_primary()方法将指定的member任命为primary - 如果使用
group_replication_switch_to_single_primary_mode()方法将group从multi-primary mode切换为single-primary mode,那么将会自动选举出一个新的primary,或者可以通过方法指定primary
当new primary server被选举出后(自动或手动),岂会被自动设置为read/write状态;并且其他的group members将会变为secondaries,状态变为read-only,具体流程如下图所示:
当新primary被选中时,可能会存在部分变更的积压,这些变更已经在old primary中被应用,但是还没有被应用到new primary中。在这种情况下,直到new primary追上old primary之前,read/write transaction可能造成冲突并被回滚,而read-only transaction则可能会读取过时的数据。
通过group replication flow control mechanism,将会将fast member和slow member的差异最小化,在该机制被激活并经合理调优的情况下,可以有效降低该上述情况的发生概率。
group_replication_consistency
可以通过该system variable来设置group的事务一致性级别,从而解决上述问题。
BEFORE_ON_PRIMARY_FAILOVER: 该值为默认值- 将该变量设置为
BEFORE_ON_PRIMARY_FAILOVER或更高级别时,新选举出的primary将会暂时持有新事务,直到primary完成积压changes的applying
- 将该变量设置为
Primary Election Algorithm
自动的primary member选举过程涉及每个member:每个member都会查看group的new view,对潜在的new primary members进行排序,并且选择最合适的member。在每个member的决策过程中,都会独立的在本地进行决策,决策遵循mysql server的primary election algorithm。
由于所有的members都必须就决策达成一致,如果其他group member运行的mysql server版本较低时,members会调整其primary election algorithm,令其行为和group内最低版本的mysql server保持一致。
在members选举primary时,会考虑如下因素,考虑顺序如下:
- 首先考虑的因素为
哪个member运行最低的mysql server version,所有group members都会首先按照mysql server version进行排序 - 如果存在多个members都运行最低的mysql server version,那么第二个考虑的因素为members中每个member的member weight,member weight由
group_replication_member_weight进行指定group_replication_member_weightsystem variable通过一个范围为0-100的数字进行指定,所有members的weight默认为50,该值设置越小,排序越靠后,值设置越大,排序越靠前- 通过weighting function可以令硬件更好的member优先级更高,或在primary计划维护时转移至特定的节点
- 如果存在多个members运行相同的mysql server version,并且多个members都拥有最高的member weight,那么考虑的第三个因素则是每个member UUID的字典序,UUID通过
server_uuidsystem variable来指定。拥有最小server UUID的member将会被选中为primary
Finding the Primary
在部署在single-primary mode下时,如果要找出哪个server为当前的primary,可以通过performance_schema.replication_group_members表中的MEMBER_ROLE来进行判断,示例如下:
mysql> SELECT MEMBER_HOST, MEMBER_ROLE FROM performance_schema.replication_group_members;
+-------------------------+-------------+
| MEMBER_HOST | MEMBER_ROLE |
+-------------------------+-------------+
| remote1.example.com | PRIMARY |
| remote2.example.com | SECONDARY |
| remote3.example.com | SECONDARY |
+-------------------------+-------------+
Multi-Primary Mode
在multi-primary mode(group_replication_single_primary_mode=OFF)下,没有member拥有特殊的role。任何member在加入group时都被设置为read/write模式,即使在并发情况下也能执行write transaction。
如果一个member停止接收write transactions,例如发生非预期的server exit,连接到member的clients将会被重定向或failover到其他的任一处于read/write模式的member。group replciation本身并不会处理client-side failover,可以使用中间件来处理,例如mysql router。
group replication是一个最终一致性的系统,其代表当incoming traffic降低或停止时,所有group members都会包含相同的数据内容。当traffic流动时,某些members对transactions进行externalized的时机可能位于另一些members之前。尤其是某些member的写吞吐可能低于其他member,导致连接到该member的client可能读取到过时数据。
在multi-primary mode下,较慢的member也可能会积累过多的待认证事务和待applying的事务,导致冲突和认证失败的风险更高。为了限制该问题,可以采用group replication的flow control mechansim机制来最小化fast member和slow member的差异。
如果想要为group中的每个事务提供一致性保证,可以使用group_replication_consistency系统变量实现。可以根据group中工作负载和数据读写的优先级来选择合适的设置,同时应考虑提升一致性所引入的同步操作对性能带来的影响。可以针对独立的session来设置该系统变量,从而保护对并发性敏感的事务。