开发者学堂课程【PolarDB-X 开源人才初级认证培训课程:X-Paxos 三副本与高可用】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1075/detail/15546
X-Paxos 三副本与高可用
内容介绍:
一、DN 高可用方案
二、X-Paxos 协议
三、DN 高可用体系
四、DN 部署和优化
五、实验演示
六、常见问题
课程分四个部分,第一个是 dn 集群的高可用方案,如何一步一步形成现在的这种模式,第二个是高可用方案所给予的 X-paxos 一次性协议,第三个是 dn 集群怎么使用一次性协议构建高可用体系,第四个是 mysql 集群常见的部署方式和优化。
一、DN 高可用方案
1、polarDB-X 存储节点 DN
这个图纸前面课程上讲了很多次,是polarDB-X的系统结构。其中dN是存储服务。
(1)一个dn节点就是一个逻辑节点,架构里有多个副本,也就是有多个码,mysql节点组成X-paxos集群来保证高可用。在之前的版本里面,dn集群不是X-paxos的。
(2)存储服务的要求,第一个是要有多副本。其中一个坏了,其他几个副本还能够保存原来的数据,并且通过副本的数据传输方式还可以达到其他的备份节点,可以继续提供服务,也就是高可用。
另外一个是存储服务要求自管理,比如说dn是polarDB-X集群中的存储组件,运行的时候不希望再引入其他的组件来管理集群,自己就是自闭环的存储服务,这是polarDB-X存储架构对存储服务的要求。
2、MySQL 经典高可用模式
(1)介绍
这几种是mysql家族里常见的几种高可用方式,比如一主一从,还有一主多从,还有mysql社区的MGR,还有其他基于共享存储的部署方案。这些高可用模式都有自己的应用场景。
(2)但总的来说,每一种高可用的模式,关注的问题无外乎几个,一个是有多少副本,副本的组织方式是什么样的。这些决定了集群在分析故障的可用性以及全局数据的一致性,还有高可用模式工程的复杂度以及性能。单机的性能是最高的,只要加上任何其他的高可用模式,性能都有可能会打折扣。
一开始dn的集群就是最基础的一主一从的结构,用SOMETHING和半同步构建组备的模式,这个模式最大的问题就是在对数据的一致性要求比较高的场景,比如金融场景中有丢数据的风险。比如说在运行过程中走库挂掉了,备库去接管。备库去接管的时候,和主库之间的数据之间没有标准。只有备库以现有的数据为标准,继续提供服务,但数据在用户的视角是不是他们之前已经提交的事务,是不是在存储上还有是不一定的。也就是ipu不等于零。
3、dn 集群强一致方案
现在dn采用的方案是一次性协议来组织的多副本。在这个模式里面,副本有2n+1个,可以容忍最多N个节点故障,只要不超过n个节点故障,集群就可以正常提供服务。但是如果超过N个节点故障,那集群就拒绝服务。就是用牺牲的可能性来保证数据的一致性。当节点数大于n+1个的时候,节点间,副本间数据的传输是用一致性协议来控制的,即可以达到ipu等于零。
现在采用的X-paxos一次性协议的模式,有一个leader节点,只有leader节点才能提供读写服务。所以leader节点一旦挂了,剩下的节点如何选主就特别重要。
所以故障检测,leader快速切换,这也是一个比较关键的问题。
这个图画的是X-paxos协议的基本结构图,下面展开看一下协议的运作模型是什么样的。
二、X-Paxos 协议
1、协议简介
X-paxos协议的理论基础就是那几篇经典的X-paxos关于一致性关系的论文,在实现里把这个模型抽象出下面几个部分。
一个节点的数据就是一个状态机,把节点数据的一次修改抽象为一条日志,把日志应用到状态机上,说明这个节点的数据变化了一次。
(1)角色
当集群正常运转的时候,有一个leader。集群初始化的时候,状态基是初始化状态,日志都是空的,可以随机选取一个节点作为leader,接下来系统在运行的时候就围绕leader来展开。运转过程大概是这样的,client对这个节点的数据做了一次修改,就会形成一条日志。Leader节点将日志写到本地的日志里。同时把这条日志广播到其他所有的follower节点。在收到其他follower节点的应答之后,就说明在集群里面提交了,就可以应用状态机,给客户端返回应答。
这是正常系统运行的过程。
在这个过程里,leader主节点提供读写服务,参与选组,follower接收主节点的日志。当leader挂掉之后,也会参与选组,会发起选主请求。另外图里面没有画的一个节点是叫learner,它也接收leader的日志,但不参与选主。learner节点就是集群数据的订阅者。可以用learner节点来构建只读节点,不参与集群的运作,只订阅集群的数据。
(2)算法
①在模型里面,关键的部分有三个,第一部分是选主,选主怎么选,集群刚初始化的时候状态机为空,可以随机选主。
当系统运作一段时间之后,如果当前的leader挂了,剩下的节点里面再去选主,剩下节点都可以发起选主请求,只有拥有集群中已经达到一次性状态的日志的那个节点,才有可能选为新的主节点。这是选主的原则。
②日志复制,日志复制就是消息从client进来,在进行中怎么广播的。另外还有一个是节点的维护,就是往集群中添加节点或者删除节点。这是协议抽象出来的运转模型。
2、工程架构
工程分为四个部分。
(1)最右边的网络层是阿里内部实现的异步网络通信的框架。
(2)服务层,它提供定时器服务,提供消息的异步传输服务,还有提供线程池功能。服务层是协议运转的驱动层,驱动了协议模块的运转。
(3)最关键的就是算法层,逻辑就是选组,日志传输以及集群管理这些内容。这个是算法模块。
(4)日志模块本身就属于算法模块中的内容,因为算法里面它维护的就是日志,工程中专门把日志模块抽出来的目的是为了做性能优化。比如说算法里面对日志的管理接口aps很简单,就那么几个,把接口的api定了之后,日志模块的具体实现就可以拿出来进行深度优化,比如说可以用缓存,可以用异步队列,可以用预取这些方式来达到优化性能的目的。
三、DN 高可用体系
1、数据一致性
首先,就是在dn的集群里面,传输binlog。现在看一下binlog是怎么在节点间进行传输的。
mysql的事务提交在有binlog参与的情况下是分为几个阶段的。
第一阶段是引擎提交,最常见的是in6db prepare。第二阶段进入有binlog协调的oddid Commit阶段,其分为三个部分。所有进来的事物都会进入队列。
第一个部分是FLASH阶段,是将日志写入到binlog。
第二个阶段是senk,是将队列中所有已经写入binlog的日志一起就刷到盘上。
第三阶段是引擎的commit。
引入x-paxos协议之后过程有点变化。在第一阶段,在FLASH阶段,在leader节点,日志写入到本地的binlog的同时,会将日志同时广播到所有的follower节点,这个是网络传输。
然后在senk阶段,这一组的事务的binlog都已经持久化到盘上,会形成一个持久化的位点。这个地方跟协议层同步一下位点。
接下来就到提交阶段,这个时候要等刚才那一批的binlog在大多数节点应答之后,才能够进行这一组事务的提交。最终这一批事务的提交点要根据这批日志在其他的节点上的接收情况来决定。这是最关键的一步。
多数派后主提交事务。这个过程其实就跟刚才x-paxos协议的抽象模型是差不多的,只不过这个图显示的是具体的binlog是怎么传输的。
在这个模型里leader是一个很重要的角色。在集群中同一时刻不允许多个leader存在。leader节点挂了之后,要迅速选出新的leader来提供服务。
2、集群选主
(1)租约
对所有节点来讲,每一个leader都有任期,在这个任期之内,所有的follower节点都不会再接受其他节点的选主请求。所以在正常的时候,leader节点通过向其他的follower节点发送心跳来不断延长任期,这是大部分的工作状态。
但一旦leader发生异常,follower就会检测到leader不存在,或者服务异常,每个follower都会发起选主请求,选自己为主。
如果其他节点大多数还健康的话,就能选出新的节点,这是对于follower节点。
对于leader节点而言,如果在它的任期之内,大部分follower节点都失去联系了,那么这个集群不能再提供服务,就会主动把自己降级为follower,然后从follower再发起选主请求。这个过程保证了集群中,同时只有一个leader存在,而当leader发生异常的时候,集群会自发进行选主,选出一个新的leader。
(2)权重选主。
默认情况之下,集群中的每个节点当选leader的概率是相等的。但是在有些情况之下,可能希望集群中某些节点或某个区域的节点具有更高的优先级当选leader。这个时候就可以给每个节点配置一个选主权重。权重高的节点有更高的概率当选leader,但是这只是当选leader的概率比较高,并不能保证高权重节点就会当选leader,因为选主最基本的原则还是这个节点要拥有这个集群已经达到共识的最新的日志,如果日志不够不能当选为leader。
权重选组是部署方面的优化或者是功能项。
3、状态机诊断
集群节点间复制的是binlog日志,那么主节点将binlog传输到follower之后,follower也收到了,然后集群对这个日志就达成了共识,说这个日志在集群中都存在了,但是对于follower节点而言,并不会要求把当前的日志应用到一次性状态位点,然后才能继续。
所以系统集群正常运转的时候,只有leader节点是保持了集群中最新的数据的,follower节点有最新的日志,但是状态机或者说MySQL集群的数据不一定是最新的。因为binlog可能还有一段没有应用。这里是有一个间隔的,所以当原leader异常之后,新的leader被选出来,新的leader在对外提供读写服务之前,首先要把binlog应用到最新的位点,就是追平日志才能服务。
在一些特殊的情况下,binlog延迟可能比较大,这个时候,原来的leader又起来了,但是最新的leader节点作为服务更合适。因为日志是最新的,不需要回放,所以这里面就是我们刚才说的被选为新的follower节点,在它还不能及时提供服务的时候,也会不断探测其他现在已经接到集群的节点,如果发现有更合适的节点,就会把leader节点主动让出去。
可能别人应用的日志更快更新,或者别人的权重更大等等,就会把自己的角色让出去,为了更快地恢复服务。这是复制延迟场景下快速恢复服务的优化。
4、反向心跳
leader节点能不能对外服务,就是指MySQL能不能对外服务。从协议层来看,集群是健康的,每个节点的心跳或是日志复制都是健康的。但是leader或MySQL节点可能因为其他的原因,不能对外提供服务。比如说有一些系统号的情况。那这种情况下,如果没有外力干扰,集群可能会僵死,因为实际上没有问题。
leader点因为其他的系统原因导致无法服务,没有人来终结这个状况,所以在开源的galxay引擎里,协议上面有一个反向心跳的功能,也就是说,follower节点会定期向leader节点发起探测请求。这其实就是把自己认为正常的客户端,或者APP的视角来探测leader节点的数据库服务是不是好的。如果有问题,原leader节点会自动进行角色降级,然后整个集群重新选主。反向心跳的功能是为了整个集群高可用的自闭环功能。
四、DN 部署和优化
1、场景优化
(1)logger节点。从协议层面来看logger节点不是新的角色。只不过这种节点从协议层面来看,就是一个正常的节点,大部分情况下,它是一个follower,即从leader节点接收binlog日志,但是不应用,也就是说它没有状态机,只保留一份日志,没有MySQL的整个数据,这个是为了节省成本,因为在这种模式之下,只有leader和follower两个节点真正有数据,logger是没有数据的。logger节点的引入是为了使用两份数据数据拷贝的情况之下,达到整个集群的数据强一致这种特殊的场景优化。
(2)learner节点。learner节点是只读节点,会从集群同步binlog,也有自己的状态机,要应用binlog,是一份正常的数据拷贝,但是可以对外提供只读服务,这个是为了进行计算能力的扩展。原来只有一个leader提供读写服务,那么io可以提供计算服务。这是一种场景优化。
2、部署模式
(1)同城三副本。就是在三个可用区各有一个节点,两个实体节点,一个logger节点,这种简化的模式相比组备模式,基本上不增加存储成本,但是可以达到强一致性的状态。现在在很多场景,比如在公共云上能够达到使用要求。
(2)更强一点就是跨城五副本,跨城五副本在协议的层面没有特殊的地方,也就是把几个副本是在多个可用区组合部署,如何配置权重的问题。可以达到中心容灾的效果。
五、实验演示
演示一下挂上整个polardb-x集群构建之后,高可用的情况。
实验大概分为两部分。
第一部分是先按之前的步骤构建一个polarDB-X的集群,第二部就是看一下高可用是怎么样的。高可用分两种,一种是随机杀掉一个cn节点,或者随机杀掉一个dn节点,看一下集群的服务。
多节点,单节点和原来的半同步有很大的区别,就是半同步在slave异常的时候会退化为异步,其实就是为了保证可用性,优先选择可用性,但牺牲了数据一致性。
三节点这种模式就是要保证强一致,如果大多数节点都不健康,系统就不能用。
1、构建 polarDB-X 集群
集群已经搭建好,登上去后创建一个压测用的数据库。
下面的阶段就是用压测工具起一个sisbench,然后kocn和dn,看一看sisbench的流量情况。
压测之前在集群里面有两个的cn,它们是对等的。这里是一个集群,就是一个逻辑dn,只建立一个逻辑dn,因为环境资源有限,就建了一个逻辑dn,有三个节点。有两个正常的数据节点还有一个logger节点。
看一下部署出来的dn集群或者MySQL集群的基本情况。登录到其中一个节点的系统里,看一下比普通MySQL集群多出来的关于协议的东西。
在Information这里多出来的一些系统表是关于x-paxos协议的东西,先关注其中比较关键的几张表。global可以看当前节点的角色,这张表只有leader角色的节点才有数据,follower节点是空的,如果查出来数据就说明当前这个节点是leader,leader有两个follower。
第一个是follower,第二个leader就是自己,第三个也是follower,因为看不到logger,在协议层没有logger这种角色,logger只是没有应用状态机而已。
看INDEX,一条日志的标识是由二元组来形成的,一个是产生这条日志的当时的leader的任期编号,另外一个是index,就是索引。index和任期编号都是只递增向上,不会变小。
这两个follower的日志都已经发过去了。
现在还没有起压力,所以说看那个apply index这个字段就是在follower节点,binlog应用到哪个位点了,他和最新的位点有多少差距,从这个表就能看出来。
一个是leader,另外两个肯定是follower。这张表是空的,但是可以看自己的信息,可以看当前leader的任期,IP端口,最新的index,还有最新应用的apply index。这几张表可以看一下每张表是什么含义。
记录了节点的状态,它的协议信息,节点信息以及健康状况等等,都从系统表里可以看到。
2、高可用。
准备起sisbence,这是客户端和流量。
cn有两个对等的,随便删掉一个。流量是有下跌的。cn刚才被杀了一回,现在起来了,流量又恢复了。杀一下dn的leader。跌零了,因为只有一个dn,杀掉leader之后会停止服务。
现在恢复了。
有一个细节,流量已经恢复,但是有一个副本还没起来,已经有一个follower被选为新leader承接流量。刚才被干掉的那个流量也起来了。
六、常见问题
1、原来那个被干掉的dn又起来后会重新选主吗?
被干掉的那个leader重新起来之后,会以follower的身份加入到集群里。
因为被干掉之后,有一个follower被选为新leader,原leader再起来之后没必要一定要用原来的新leader再做。
除非原来被干掉的leader权重比较高,就有更大更高的概率被选为leader。
logger节点没有数据,只有日志,但是依然有可能被选为leader,因为有可能日志就是就是集群中最新的。但是自己又没有数据,不能提供服务,就会把日志同步给其他节点,等其他节点把日志接收完毕之后,logger会把leader角色自动让出去。
2、权重高的有更高概率当选leader。
即使权重高,也不一定选为leader,如果在生产场景中,一定要某个节点当选leader,比如说只要不坏,就是leader,可以人工干预,人工干预的意思就是万一权重也没有选为leader,可以在集群里面用一条命令指定哪个节点成为leader。
但是这种指定不破坏协议,只是如果有条件,或是能够当选为新leader,才能成为leader。