Mysql组复制MGR

admin
2025-06-30 / 0 评论 / 8 阅读 / 正在检测是否收录...


数据库的高可用方式有很多,其中利用组复制MGR组建高可用mysql是主流之一,组复制极高的数据一致性,使得使用在最重要的场景。


Mysql复制的技术演进



1 传统复制 (即异步复制)


主从复制:有一个主和不等数量的从,主节点执行的事务会异步发送给从节点,在从节点重新执行。即是在主节点执行和提交事务,然后把他们异步的发送到从节点,行复制的重新执行主节点的SQL语句,这是一个 shared-nothing 的系统,默认情况下所有server成员都有一个完整的数据副本

image3.png


这个过程主库是不考虑从库是否有接收到binlog文件,以及是否执行成功,有可能出现这种情况,当主库commit一个事务后,数据库发生宕机,刚好它的binlog还没来得及传送到slave端,这个时候任何一个从服务器都会丢失这个事务,造成数据丢失情况

2 半同步复制


为了避免出现主从数据不一致的情况,MySQL引入了半同步复制,添加多了一个从库反馈机制,主库执行完事务后,同步binlog给从库,从库ack反馈接收到binlog,主库提交commit,反馈给客户端,释放会话

image4.png


但是半同步复制也并不完美,写压力全部在主节点上,主节点宕机之后,需要手工选择主节点,并在其他从节点上执行change master操作,当然这一步中间件(mycat)可以会解决,或者对主做高可用,但是即使主节点收到ack之后再提交,也不能保证从节点在应用relay log时没有问题


3 并行复制


并行复制:复制->广播->正式复制

并行复制其实是半同步复制的升级,提高其同步复制的效率,并使得数据强一致性

从MYSQL5.6开始,mysql开始支持GTID复制,GTID的全称是global transaction id,表示的是全局事务ID

其保证为每一个在主上提交的事务在复制集群中可以生成一个唯一的ID

GTID实际上是由UUID+TID (即transactionId)组成的,其中UUID(即server_uuid) 产生于auto.conf文件(cat /data/mysql/data/auto.cnf),是一个MySQL实例的唯一标识

TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增,所以GTID能够保证每个MySQL实例事务的执行(不会重复执行同一个事务,并且会补全没有执行的事务)


基于GTID主从复制的优点有:

  • 保证同一个事务在某slave上绝对只执行一次,没有执行过的gtid事务总是会被执行
  • 不用像传统复制那样保证binlog的坐标准确,因为根本不需要binlog以及坐标
  • 故障转移到新的master的时候很方便,简化了很多任务
  • 很容易判断master和slave的数据是否一致,只要master上提交的事务在slave上也提交了,那么一定是一致的


image5.jpeg


slave1 : 将自身的UUID1:1 发送给 master,然后接收到了 UUID1:2、UUID1:3 event

slave2 : 将自身的UUID1:1,UUID1:2 发送给 master,然后接收到了UUID1:3 event

GTID在一组复制中,全局唯一并在整其个复制架构中GTID是不变化的,只有后面binlogevent变


GTID可简化MySQL的主从切换以及Failover,GTID用于在binlog中唯一标识一个事务,当事务提交时,MySQL Server在写binlog的时候,会先写一个特殊的Binlog Event,类型为GTID_Event,指定下一个事务的GTID,然后再写事务的Binlog

主从同步时GTID_Event和事务的Binlog都会传递到从库,从库在执行的时候也是用同样的GTID写binlog,这样主从同步以后,就可通过GTID确定从库同步到的位置了,也就是说,无论是级联情况,还是一主多从情况,都可以通过GTID自动找点儿,而无需像之前那样通过File_name和File_position找点儿了


GTID的工作流程为:

  • master更新数据时,会在事务前产生GTID、Binglog Event一同记录到binlog日志中
  • slave端的i/o 线程将变更的binlog,写入到本地的relay log中
  • sql线程从relay log中获取GTID、binglog Event然后对比slave端的binlog是否有记录
  • 如果有记录,说明该GTID的事务已经执行,slave会忽略
  • 如果没有记录,slave就会从relay log中执行该GTID的事务或者GTID中的binglog event,并记录到binlog
  • 在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描


mysql主从结构在一主一从情况下对于GTID来说优势不太大,而对于2台主以上的结构优势异常明显,可以在数据不丢失的情况下切换新主

从MySQL 5.6版本中开启GTID复制代替传统的复制方式

而在5.7版本中引入组复制的概念,即使不开启GTID,每个事务开始前也是会存在一个Anonymous_Gtid ,而这GTID中就存在着组提交的信息

MySQL 5.7推出的Enhanced Multi-Threaded Slave还解决了困扰MySQL长达数年的复制延迟问题


4 组MGR复制



MGR定义


组复制MySQL Group Replication(简称MGR)

它是MySQL5.7以上版本出现的新特性,它提供了高可用、高扩展、高可靠的MySQL集群服务,是一个全新的高可用与高扩展的解决方案

它以插件形式提供,以组复制的方式实现了分布式集群下数据的最终一致性,同时可以自动切换,具备故障检测功能、支持多节点写入

是MySQL官方在已有的Binlog复制框架之上,基于Paxos协议实现的一种分布式复制形态


单主与多主


MySQL组复制分:单主模式(单写)和多主模式(多写)


image1.png


单主模式

在单主模式下, 组复制具有自动选主功能,每次只有一个 server成员接受更新

单写模式group内只有一台节点可写可读,其他节点只可以读

对于group的部署,需要先跑起primary节点(即那个可写可读的节点,read_only = 0)
然后再跑起其他的节点,并把这些节点一一加进group,其他的节点就会自动同步primary节点上面的变化,然后将自己设置为只读模式(read_only = 1)

当primary节点意外宕机或者下线,在满足大多数节点存活的情况下,group内部发起选举,选出下一个可用的读节点,提升为primary节点

primary选举根据group内剩下存活节点的server_uuid变量和group_replication_member_weight(权重)变量值,选择下一个slave谁作为主节点,group_replication_member_weight的值最高的成员被选为新的主节点,该参数默认为50,建议可以在各节点上设置不同权重值;

在group_replication_member_weight值相同的情况下,group根据数据字典中 server_uuid排序,排序在最前的被选择为主节点


image2.png


多主模式


在多主模式下, 所有的server成员都可以同时接受更新,group内的所有机器都是primary节点,同时可以进行读写操作,并且数据是最终一致的,多主模式下不再有master-slave的概念


单主与多主对比


单主模式:比多主模式多一个选举程序,第一次引导开启集群的为主,后加入的为追随者(也可以叫从机Slave),只有主的有读写权限,别的追随者在加入组的时候自动把权限禁了,如果主的挂了,其他服务器会根据UUID和一个值(类似权重)进行重新选主,每次选主都会重新把权限禁一遍

多主模式:所有服务器加入组时,读写权限全部放开,大家都可以读写,但是只能更改不同行的数据,如果后加入集群的服务器改了一行数据,那前面的服务器就不能再对这行数据进行改动了,如果改动则报事务回滚取消改动,而后加入的可以改前面加入集群改过的数据

单主与多主只是在数据库层面是否打开了读写 而同步/复制都是一致的

基于目前MGR的特性因此无论选择单主还是多主,都可以结合keepalived(vip)给上层应用一个固定的ip地址

或者结合数据库中间件,如读写分离结合ProxySQL

并且多主可以是多个数据库在多个数据库服务器同写,但不建议单个数据库进行同时写入


为什么要用MGR


传统的mysql的同步复制技术仅解决了数据同步的问题,但是对于数据一致性还不能完全保证,而组复制则解决了这一问题

即所有组内数据库中的数据要么都有,要么都没有,做到了不仅同步并且数据强一致性

而对于集群层面只要集群中大多数主机可用(半数以上),则服务可用,也就是说3台服务器的集群,允许其中1台宕机

MGR由多个实例节点共同组成一个数据库集群,每个实例节点都是一个独立的副本

系统提交事务(将变更持久化到磁盘)必须经过半数以上节点同意方可提交,在集群中每个节点上都维护一个数据库状态机,保证节点间事务的一致性

它基于原生的主从复制,将各节点归入到一个组中,通过组内节点的通信协商(组通信协议基于Paxos算法),实现数据的强一致性、故障探测、冲突检测、节点加组、节点离组等等功能

MGR 是一个新的高可用与高扩展的方案,集群中的任何节点数据都是一样的,多主模式可以实现任何节点都可以写入,实现了真正意义上的多主

MGR核心是一个组同步机制,解决的主要问题在于集群中所有数据库的同步与数据一致性

读写分离需要配合读写分离解决方案如:ProxySQL、mysql route、mycat


MGR组复制的特点


  • 数据强一致性:组复制基于Paxos协议的多数派原则,确保数据可靠性,当多数派节点(指集群中超过半数的节点)接收到事务的Binlog并且冲突检测通过后事务才会提交(将变更持久化到磁盘)这保证了在多数派可用的情况下,任何少数派节点(集群中少于半数的节点)故障都不会导致数据丢失,
  • 传统主备复制的问题:主节点在写入Binlog后、传输到备节点前发生故障,可能导致主备数据不一致,组复制通过先传输事务到集群其他节点再写入Binlog的方式,确保主备节点数据一致性
  • 旧主节点故障重启后,会自动加入集群并拉取缺失的Binlog,从而获得最新数据
  • 高容错性:自动检测机制,只要不是大多数节点都宕机就可以继续工作,内置防脑裂保护机制
  • 高扩展性:节点的增加与移除会自动更新组成员信息,新节点加入后,自动从其他节点同步增量数据,直到与其他节点数据一致
  • 高灵活性:提供单主模式和多主模式,单主模式在主库宕机后能够自动选主,所有写入都在主节点进行,多主模式支持多个节点都可以读写


MGR组复制过程


image6.png


1. 本地事务执行‌:

当数据库发起一个更新时该事务首先会在本地数据库节点上执行,这意味着数据库会按照事务中的SQL语句,在本地进行数据的修改、插入或删除操作

2. 事务提交准备‌:(将变更持久化到磁盘)

本地执行完成后,数据库节点会准备对事务进行提交操作,但在此之前为了确保数据的一致性,需要进行一系列同步和校验步骤

3. 复制写集广播‌:(Write Set 事务修改的所有数据项的集合)

在提交之前数据库节点会将事务产生的复制写集广播给组内的其他成员
复制写集包含了事务中所有数据更改的详细信息,如哪些数据被修改、插入或删除等

4. 冲突检测‌:

其他组成员接收到复制写集后,会进行冲突检测
这是为了确保没有其他事务在同时修改相同的数据,或者是否有其他成员已经提交了相同的事务,冲突检测是保持数据一致性的关键步骤

5. 事务提交决策‌:

如果冲突检测成功,即没有检测到冲突,组内的成员会达成一致决定该事务可以提交(将变更持久化到磁盘),随后所有组成员都会应用该事务,将数据更新同步到各自数据库中

如果冲突检测失败,即检测到冲突,组内的成员会协商决定回滚该事务,这意味着所有组成员都会撤销该事务对数据的更改,以避免数据不一致

通过这一流程,MySQL组复制能够确保在分布式环境中,多个数据库节点之间的数据一致性,即使在并发事务和网络延迟的情况下也能保持数据的正确性和一致性


MGR实现了基于复制协议的多主更新


复制组由多个server成员构成,并且组中的每个server成员可以独立地执行事务,但所有读写(RW)事务只有在冲突检测成功后才会提交,只读(RO)事务不需要在冲突检测,可以立即提交

换句话说,对于任何RW事务,提交操作并不是由始发server单向决定的,而是由组来决定是否提交

准确地说,在始发server上,当事务准备好提交时,该server会广播写入值(已改变的行)和对应的写入集(已更新的行的唯一标识符)

然后会为该事务建立一个全局的顺序,这意味着所有server成员以相同的顺序接收同一组事务,因此所有server成员以相同的顺序应用相同的更改,以确保组内一致

组复制使您能够根据在一组server中复制系统的状态来创建具有冗余的容错系统,因此只要它不是全部或多数server发生故障,即使有一些 server 故障,系统仍然可用,最多只是性能和可伸缩性降低,但它仍然可用

server 故障是孤立并且独立的。它们由组成员服务来监控,组成员服务依赖于分布式故障检测系统,其能够在任何 server 自愿地或由于意外停止而离开组时发出信号

他们是由一个分布式恢复程序来确保当有 server 加入组时,它们会自动更新组信息到最新。并且多主更新确保了即使在单个服务器故障的情况下也不会阻止更新,不必进行 server故障转移。因此,MySQL 组复制保证数据库服务持续可用

值得注意的一点是,尽管数据库服务可用,但当有一个 server 崩溃时,连接到它的客户端必须定向或故障转移到不同的 server。但这不是组复制要解决的问题,keepalived、连接器,负载均衡器,路由器或其他形式的中间件更适合处理这个问题

总之,MGR组复制提供了高可用性,高弹性,可靠的 MySQL 服务


image7.png


需要注意:MGR组复制也是一种 share-nothing 复制方案,其中每个server成员都有自己的完整数据副本 推荐最少3台数据库


MGR节点角色

Primary:处理所有写操作,协调事务复制

Secondary:接收 Primary 的变更,参与共识投票


MGR故障检测


通过心跳机制(默认2秒)检测节点状态,超时则触发视图变更

故障检测是提供关于哪些server可能已死的信息(猜测)的分布式服务, 某个server无响应时触发猜测,组中其余成员进行协调决定以排除给定成员。如果某个server与组的其余成员隔离,则它会怀疑所有其他server都失败了

由于无法与组达成协议(因为它无法确保仲裁成员数),其怀疑不会产生后果。当服务器以此方式与组隔离时,它无法执行任何本地事务。 在线 server 列表通常称为视图,新成员server的加入离开,无论是自愿还是被迫的离开,该组都会动态地重新规划其配置,并触发视图更新


故障转移流程:


当 Primary 节点不可用时:

集群检测到 Primary 失联(超过group_replication_member_expel_timeout)

Secondary 节点通过选举算法选出新 Primary(基于group_replication_member_weight权重)

新 Primary 开始处理写请求,集群继续提供服务


MGR新节点加入流程:


新节点向集群发送加入请求
现有成员验证节点身份并发送当前视图
新节点进行状态转移:
增量同步:若新节点有部分历史数据,从最新 GTID 开始同步
全量同步:若新节点无历史数据,通过克隆(Clone Plugin)复制完整数据
集群更新视图,新节点开始参与共识


MGR的限制


  • 存储引擎必须为Innodb,即仅支持InnoDB表,并且每张表一定要有一个主键,用于做write set的冲突检测;
  • 每个表必须提供主键;
  • 只支持ipv4,网络需求较高;
  • 必须打开GTID特性,二进制日志格式必须设置为ROW,用于选主与write set;
  • COMMIT可能会导致失败,类似于快照事务隔离级别的失败场景;
  • 目前一个MGR集群组最多支持9个节点;
  • 不支持外键于save point特性,无法做全局间的约束检测与部分部分回滚;
  • 二进制日志binlog不支持Replication event checksums;
  • 多主模式(也就是多写模式) 不支持SERIALIZABLE事务隔离级别;
  • 多主模式不能完全支持级联外键约束;
  • 多主模式不支持在不同节点上对同一个数据库对象并发执行DDL(在不同节点上对同一行并发进行RW事务,后发起的事务会失败);


MGR组复制优势:


  • 弹性复制(高扩展性):server动态添加移除
  • 高可用分片(高扩展性):分片实现写扩展,每个分片是一个复制组。
  • 替代主从复制(高扩展性):整组写入,避免单点争用。
  • 自动化系统:自动化部署Mysql复制到已有复制协议的自动化系统。
  • 故障检测与容错:自动检测,若服务faild,组内成员大多数达成认为该服务已不正常,则自动隔离。
  • 组内成员会构成一个视图,组内成员主动加入或离开(主动或被动),都会更新组配置,更新视图。成员自愿离开,先更新组配置,然后采用大多数成员(不包含主动脱离的成员)意见是否确认该成员离开更新视图。如果是故障要排除,则需大多数服务确认(包括故障成员意见),然后才会更新组配置和视图。
  • 最大允许即时故障数:f=(n-1)/2,多数正常则正常


关机顺序: 主库先设置只读----所有节点关mysql服务----所有节点关机

开机顺序: 先启动所有备节点---启动主节点---开启读写---最后开启mgr







0

评论 (0)

取消