mysql group replication,组复制,提供了多写(multi-master update)的特性,加强了原有的mysql的高可用架构。mysql group replication基于mysql插件架构实现,自己就是一个mysql插件。html
提供的特性:mysql
组复制基于mysql插件架构实现,自己做为一个mysql插件而存在。如上图所示,蓝色和绿色两部分表示组复制架构。linux
组复制依赖mysql server主模块(上图灰色部分)以及mysql的复制架构,包括binary log caches、binary log applier模块、GTID、relay log模块、replication applier threads(组复制distributed recovery第一个阶段会使用这些线程)和performance_schema(用于存储监控组复制的状态信息)。nginx
上图架构中各个模块的做用简单介绍以下:sql
API层提供了组复制与上层mysql server交互的接口。上层(mysql server)会主动通知下层(组复制)根据它的状态去作对应的动做,包括server的启动、恢复、接受链接、提交事务等等。组复制根据这些接口调用作出对应的响应动做。缓存
组复制中的三个核心模块,当上层API发生调用,将根据调用类型路由到下面这三个模块执行相应的逻辑。Capture模块负责追踪事务执行的上下文信息;Applier模块负责将远程事务加载到本地执行;Recovery模块管理组内节点的recovery。markdown
Replicaiton Protocol Logics模块实现了replication协议的逻辑,逻辑功能包括: 处理冲突检测、接收并传播事务到组内去执行。架构
提供状态机(Replication State Machine)的高层抽象API,以此分离与下层协议实现的逻辑。并发
根据上层的状态机API的抽象,这一层主要提供Paxos协议变种的核心实现。app
一个Group由若干个mysql节点组成,每一个Group有本身的惟一命名来标识,格式为UUID。Group内的mysql节点数据保持一致。一个组能够动态增长和删除节点。
组成员管理自动化。新增一个节点到一个组里面,这个节点会自动同步自身数据跟组内其余节点保持一致。保持同步会利用Asynchronous MySQL replication。当一个节点从一个组里移除,将自动更改group的配置,以让其余节点知道这个节点的移除。
组复制有两种运行模式: (1) Single-Primary Mode 和 (2) Multi-Primary Mode,其中Single-Primary Mode表示一个组里面只有一个节点用于写,而Multi-Primary Mode下组内全部节点均可以参与写,事务的提交能够在组内的任意一个节点进行。
看起来Multi-Primary模式好像很屌!可是,这个模式下目前存在挺多的使用限制:
Multi-Primary模式下,对于事务的提交,须要组内全部节点进行通信,共同决定事务是否能够提交。高并发模式下有可能出现分布式提交冲突——不一样的节点并发提交的事务操做了同一行数据。group replication提供的乐观的解决方案是——先提交(时间序靠前的)的事务,可以正确被提交,然后面提交的事务,将会失败。
官方建议,避免并发写冲突的最好的作法是将这些会产生冲突的写事务放到同一个节点上进行提交。
MySQL目前不支持事务类型的DDL,也就是说DDL操做不是一个原子操做,在Multi-Primary模式下,DDL操做并发地在多个节点执行,颇有可能产生数据不一致的状况。所以,官方提醒,在Multi-Primary下DDL操做最好在同一个节点上执行。
若是运行在Single-Primary模式下,就没有上面所提到的限制了。
当一个新节点(被叫做joiner)加入一个group,须要从group里面其余节点同步状态。这个新节点从其余节点获取这些落后数据,并接受新提交的事务,最终保持与group内其余节点数据一致的这个过程,称为distributed recovery(DR)。DR过程分为两个阶段:
Joiner选择group里面的一个节点做为复制源(这个节点被称做donor),基于原有的异步复制技术进行recovery。这个过程会创建从donor到joiner的replication channel,joiner不断接收从donor端发送的binary log,apply到自身。于此同时,joiner还会监听并缓存group里面自从它加入以来产生的新事务。阶段1结束后,将会关闭以前创建在donor和joiner之间的replication channel。
donor有可能在这个阶段挂掉,此时joiner将自动选择集群内的其余一个存活节点做为donor,继续以前的recovery。这个过程无需人为干预。
阶段2,joiner执行在阶段1缓存队列里的新事务(直到缓存队列为空),而后将joiner的状态标记为online
,表示这个节点的数据已经跟其余节点保持一致,能够被正常访问。
只有online的节点才能正常接收用户请求。
这里有个问题: 在阶段1,joiner怎么知道它在何时会完成全部缺失数据的recovery,单单依靠GTID机制是不够的(依靠GTID机制只能让joiner知道它是否少了这部分数据)。这个时候,须要有另一个机制,来表明一个时间点——这个时间点可以标识阶段1的结束,也就是说在这个时间点上,joiner已经完成了从donor上全部缺失数据的recovery,接下来能够进入阶段2了。
这个机制,就是binary log view change markers,在阶段1传输binary log流中,会带上view change markers。那么joiner在接受到binary log的时候,就能够利用这些标识来判断那个时间点的到来。
在解释view change markers以前,须要介绍view change markers关联的概念: View 和 View Changes。
一个Group里面全部节点在某个时间点上达成的配置,对外表示为一个View。
View Changes指引发Group配置发生变化的事件,好比新增节点,删除节点。
每一个View有一个惟一标识(View Identifier)进行标识。当发生View Changes时,就会生成这样一个惟一标识来表示这个新的View。
View changes产生的view ids做为新节点与donor同步数据的临界点。View change事件对应到binary log里面是一个新binary log event的实现——view change log event。在这个view change log event里面携带了view id。
假设在以前的multi-primary部署示例完成后,咱们经过登录S2执行如下语句检索到view change event log:
mysql > show binlog events\G;
能够看到以下view change event log:
*************************** 9. row *************************** Log_name: binlog.000001 Pos: 742 Event_type: View_change Server_id: 1 End_log_pos: 881 Info: view_id=14817781596395401:1
接下来咱们分析一个例子: 一个新节点加入一个group的过程
一开始group有3个节点S一、S二、S3,整个group处于稳定状态
接下来新节点S4准备加入group,引发view changes(VC4)。全部的节点都会在缓存队列里面缓存view change event log到队列。同时,新节点S4会选择group里面的某个节点做为donor。
全部的节点都要缓存view change event log到队列,由于这个event log以前有可能还存在着未apply的event log,这些event log是属于old view的。
当S4选择好donor后,就会创建与donor的replication channel,基于async replication机制从donor上同步状态进行recovery,直到S4遇到指望的view change marker为止。
于此同时,S4也会不断地接受group里面下发的新提交事务,缓存到队列里面。
当S4遇到指望的view change marker(根据view change event log 判断)之后,与donor之间的replication channel将会被关闭,这个时候,就会从以前的缓存队列里面取新的事务(图示中的T22)进行apply,直到缓存队列为空,而后就能够将S4的状态标记为online,这就是阶段2的主要动做。
注意,阶段2的执行周期是不肯定的,取决于系统的负载状况,由于在阶段2期间,有可能系统不断产生新的事务。系统的负载越高,产生的事务会越多,那么阶段2经历的时间天然也就越长了。
come from:http://www.voidcn.com/blog/d6619309/article/p-6349585.html