前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >李岩:CynosDB for MySQL高可用系统介绍

李岩:CynosDB for MySQL高可用系统介绍

原创
作者头像
腾讯云开发者社区技术沙龙
发布2019-03-29 16:18:01
2.3K0
发布2019-03-29 16:18:01
举报

3月16日在北京举行的腾讯云自研数据库CynosDB交流会圆满落下帷幕。现将技术团队分享的内容整理如下。

任何系统都需要高可用,CynosDB也不例外,下面主要从研发的角度来看CynosDB的高可用系统方案是如何一步一步设计的。主要内容包括:首先是说下CynosDB高可用系统设计的思路,然后是CynosDB是如何快速恢复的,以及高可用系统的整体架构,最后是针对高可用系统中经典的“脑裂”问题是在CynosDB是如何解决的。

对于高可用来说,其实是一个老生常谈的问题,为什么要高可用,大家都熟悉了,这里简单提一下。首先用户要求所使用的服务是7×24小时的;其次我们知道服务所运行的环境是不可靠的,这种不可靠有来自软件的bug、硬件的损坏,还有来自自然环境的不可抗因素;最后数据是很重要的,数据丢失或者数据库服务的不可用带来的结果是,小到DBA被开除,大到导致一个公司的破产,所以无论在任何情况下,都要保证数据服务的可用性,这是我们做数据高可用的最重要的原因。

CynosDB的高可用系统是如何设计的呢?从开发角度来说我要设计一个高可用系统,首先我要看一下业内是怎么做的,业界的方案有两种,一种是基于一致性协议,这个是近两年比较热门的一个话题,就是Paxos和Raft。这种方案基本思想是,使用可证明的一致性算法,各节点通过心跳来探测整个集群的可用性,出现心跳超时就剔除超时节点,重新发起选主。这个方案中,最典型的就是MySQL官方的5.7版本的MGR架构。它的优点是,有可证明的理论基础,整个数据都强一致的。但是有一定的问题,首先它存在特定的版本中,MySQL官方5.7.17版本才有这个特性,5.6版本就无法使用,所以如果想在低版本中使用,需要修改MySQL代码嵌入一致性算法,业界有些产品是这么做的。这就导致对MySQL存在一定的侵入性,后续版本升级都需要打这个patch,从而带来升级上的不方便。还有就是,这种架构必须要求是三个节点或者更多的节点,对于云上的用户来说可能考虑更多的是成本问题,有时候可能需要的只是双节点架构或者基础版单节点,所以,在需要适配多种MySQL主从架构的情况下基于一致性协议的方案就不合适了。

第二种是基于外围系统的方案,这种方案的基本思路是,外围会有一个服务系统,不断地去探测MySQL集群各个节点的状态,出现问题的时候,会做一个切换或者恢复,这种方案中一个典型代表就是比较流行的MHA组件。它的优点是,首先不管MySQL集群有多个个节点,都是适用的,对这个外围系统来说,都是做探测;然后,由于是通过外围服务来做,不需要修改MySQL内部代码,不存在侵入性;再者,不管MySQL什么版本,只要能支持MySQL访问协议,都可以探测状态,所以这种方案对版本是透明的。但是它也有自己的问题,需要实现一套外围系统,这就增加了运维成本,还有就是整个外围系统本身的高可用性需要保证。

以上是业界比较流行的两种高可用设计方案。我们设计CynosDB的高可用系统的时候,是采用基于外围系统这个方案,当然外围系统本身的高可用性我们也是有考虑的。

具体我们是怎么设计的呢?我们在设计的时候,其实是将设计一个高可用系统划分成了三个子问题:第一个是如何探测故障,就是说当有故障发生的时候我要如何发现;第二个是如何决策,即当我知道有故障发生时,我该怎么做,是原地拉起还是立即切换,是恢复主从状态还是用冷备数据重建这个节点;第三个问题是如何恢复,即我知道怎么做之后,具体的恢复操作是怎么样的。后面是针对这三个问题来介绍怎么设计CynosDB的高可用系统。

首先,我们来看第一个问题:如何故障探测。目前大致有三种方式,第一种方式是基于内部心跳,MGR架构中leader和follower会保持心跳,心跳超时就发起故障投票,这种方式要求系统至少有三个节点。第二种方式是基于外部Server,比如MHA使用MHA Manager来不断探测master节点的存活,发现异常时开始切换。但是外部Server的探测是通过网络来访问MySQL节点的,这会带来几个问题:第一个就是故障发现不够及时,如果网络出现波动,可能一次探测并不能说明MySQL已经故障了,需要多次探测,这就导致故障发现不够及时;第二由于Server是非同机部署的,那MySQL机器本身的状态,比如机器高负载、机器假死,这种导致MySQL无法访问的故障类型也是感知不到的;第三点它容易导致脑裂,如果网络出现隔离,Server无法访问MySQL,认为MySQL故障了,就去切换,很容易出现“脑裂”的问题。第三种方式是基于本地Agent,就是MySQL本地会部署一个探测Agent,通过Agent去检测MySQL的一些状态。这种方式下,由于Agent与MySQL同机部署,与MySQL之间的通信不通过网络,一次探测就能发现MySQL是否正常,所以及时性没问题;另外,Agent可以探测机器本身的负载状态,当然,这种方式在某些场景下也会导致脑裂,但是针对这个问题是有解决方案的。针对这几种故障探测方式,我们选择的是基于本地Agent做探测故障。在探测的时候,我们不仅要探测MySQL进程的状态,比如进程是否存活或者正在做恢复,或者已经挂掉;还要探测MySQL内部的状态,比如在主从架构下,还会探测Slave节点的IO线程和SQL线程状态,主从差距的大小,如果发现有问题,会做一个自动修复;更进一步,我们还会探测机器的负载状态,出现高负载或者磁盘坏块之类的问题,也能及时发现,做出决策。目前我们的故障探测主要考虑了这三种情况。对于每种故障的RTO,目前是:针对进程故障,我们可以原地拉起,这个时间在5s内,如果无法拉起,需要做切换,我们的系统可以在10s内完成切换,针对于机器故障的情况,目前设置的超时时间是20秒,再加一个切换时间,可以保证在30秒内能够恢复。

现在,我们来看第二个问题,发现故障之后,我该做什么?我们知道,MySQL是分主从的,对于不同角色的节点来说,会有不同的做法。首先,对于Master节点,在发生故障的时候,我们一般会做自动切换,比如MHA,但是在有些方案中,会选择自动剔除故障的Master节点,比如MGR;在做完切换后,一般会做对旧Master节点做自动降级,把旧的Master节点角色降为Slave,这样在旧节点恢复后,它就不会认为自己还是Master,从而规避一些不必要的麻烦问题。对于Slave节点,如果进程挂掉,我们在拉起进程后,只需要重建主从关系就可以了,但是如果主从关系无法重建,或者机器故障重建不了,就可能需要通过冷备数据或者Master数据来重建这个节点。我们将这几个操作抽象为三种决策,对于Master节点,我们是决策是自动切换(switch),对于Slave节点是重新加入拓扑(rejoin)和重新构建从节点(rebuild)。

最后一个问题就是怎么做恢复了,对于Master节点,在主从架构下,恢复时第一个要考虑的问题是如何选主,根据前面提到的业界两种高可用方案,我们把选主抽象为分布式选主和集中式选主。分布式选主是指集群内所有可用节点同时参与选主,比如Raft/Paxos多数派投票选主;集中式选主是根据Agent上报的状态信息,以及一定的策略来进行选主,比如数据最新优先或者权值优先。我们采用的选主方法是,在满足多数派情况下的多策略选主。比如,策略1:可以指定节点优先,这种策略主要使用场景是手动发起切换;策略2:最大权值优先,其应用场景是多个从节点设备配置不一致,在故障发生时,期望优先切换到配置高的从节点,这个策略在MGR中有用到;策略3:数据最新优先,这个策略一般都是要保证的。

为了说明我们选主的过程,这里给出一个示例图。我们会把一个MySQL集群抽象为一个节点集,比如说一主两备架构下,有三个节点A、B、C,A是Master,B和C是Slave,在A节点故障时,我们得到一个异常集A和正常集B、C,这里正常集节点数需要满足多数派,如果不满足不能发起切换;在正常集中挑选候选集,这时就用到刚才提到的策略,首先如果指定了某个节点,该节点就为候选集节点,如果没有指定就去比较权值,权值大的为候选集节点,如果权值都相同,则都为候选集节点,图中我们假设B、C权值相同;然后,我们会在正常集节点中找数据最新的节点,假设B节点数据最新,然后其他节点去跟最新节点同步数据,得到一个同步集B、C,同步集也需要满足多数派;同步集中数据回放完成的节点跟候选集中的节点做一个交集,从交集中选择一个做目标节点。选择好节点后,下面要做的事情就是恢复了。针对恢复,一个很重要的问题是,如何能够尽可能快的恢复?

下面针对CynosDB的基础版,说明一下我们是如何做快速恢复的。首先我们看下CynosDB的实例架构,大致是这样,上下分为计算层和存储层,计算层每个实例机器是由一组Mysqld进程和一个与存储层交互的的Client组成;存储层是一个分布式的存储系统,我们叫TXStore。熟悉MySQL恢复过程的小伙伴都知道,恢复的原理其实是获取一致性位点的过程,只要拿到这个位点,MySQL就会知道恢复到哪个位置,然后根据保存的Redo和Undo去做事务提交或者事务回滚。对于CynosDB来说,这个一致性位点我们称为卷持久化序列号,简称VDL。下面说下在CynosDB中如何快速获取VDL。

这里先说下迷你事务(mtr)的概念,MySQL中的每个事务在InnoDB引擎层会有很多个mtr,每个mtr在Redo中有很多个log组成。这里假设我们上次的一致性VDL是3(L-VDL=3), 现在正在写入3个mtr:mtr1、mtr2、mtr3,其中mtr1有三个log组成L1~L3,mtr2有两个log组成L4和L5,mtr3有L6和L7组成。具体VDL的恢复原理是:首先,client通过广播L-VDL的方式获取存储层所有tablet的已完成的最大持久化点(CPL),这里假设从三个tablet获取到的CPL是4、7、5;然后,我们使用二叉堆对获取到的所有CPL排序,得到系列3、4、5、7,由于6还没有持久化,所以获取的最大连续CPL=5,同时L5是mtr2最后一个log,所以我们得到新的VDL=5。

具体是怎么恢复的?我们来看一个示例,在做恢复的时候,client会去做广播,获取每一个tablet的CPL点。对于每一个tablet,我们作为二叉堆上的一个节点,根据每个节点最头部的日志号(LSN)构建一个最小二叉堆。恢复的时候,我们从二叉堆中获取第一个最小的LSN=1, 从堆顶节点拿到1之后,节点剩下一个5,此时最小堆会有一个调整的过程,调整后变成图②,这样5被调整到最下面;然后继续从堆顶节点得到一个2,然后拿到3,以此继续,最后我们会得到这样一个从1~11的CPL序列。由于LSN=8的日志还没有持久化,所以会把8及其以后日志都truncate掉,这样就得到一个1~7的连续CPL序列。此时,如果7是一个mtr最后的一个日志,则得到的最终VDL=7。但是如果7是mtr中间的日志,比如,假设1~3属于mt1,4~5属于mtr2, 6~8属于mtr3, 则此时会进一步truncate掉日志6和7,得到最后的VDL=5。这样我们最终得到返回给计算层,计算层去做进一步的恢复。这就是CynosDB中VDL快速恢复的基本过程,我们通过并发广播和二叉堆排序来保证恢复的性能。

说完恢复之后,我们来看一下CynosDB高可用系统的整体架构。主要有两个模块,Agent和Scheduler。Agent与Mysqld同机部署,不断地去采集Mysqld状态,上报状态数据给Scheduler;Scheduler根据任务调度策略和切换策略,发起HA任务;不同的HA任务完成不同的恢复工作,比如switch主要做多策略下的多数派选主及主从切换,rejoin负责修复主从状态,rebuild在rejoin失败的情况下对从节点进行重建。对于Agent,是无状态的,在故障时,我们抛弃了crontab,使用supervisor来秒级拉起;对于Scheduler,我们通过ZK保证它的高可用,同时保证同一时间只有一个Scheduler正常服务。

介绍完CynosDB的高可用系统后,现在我们来看下针对高可用系统设计中的经典“脑裂问题”,在CynosDB中是如何解决? 首先我们以CynosDB基础版为例,描述一下“脑裂问题”。假设我有一个CynosDB的基础版实例,高可用系统中的Agent在不断的采集实例状态上报Scheduler,突然在某个时刻,实例机器与Scheduler机器发生了网络隔离,由于Agent与Scheduler之间通信超时,Scheduler此时认为机器故障了(实际上并没有),发起主节点的切换操作,假如切换到另一台机器后,网络又恢复了,这样对于应用来说,存在两个同时可写的实例,于是就产生了“脑裂”。

CynosDB是如何解决这个“脑裂”问题的呢?我们在每个实例最开始创建的时候,会在存储层记录下每一个实例的实例版本号,也就是记录在TXStore这块,如果出现网络隔离的发生切换的时候,高可用系统会通知TXStore把实例版本号加1,这样旧节点上写下来的IO请求使用的是旧版本号,版本号落后于新版本号,会返回IO失败,这样MySQL内核发现IO失败原因是版本号过低,就会自动退出。以此达到规避“脑裂”的目的。

以上就是本次介绍的全部内容,这里对本次内容做一个总结。首先从三个问题的角度介绍了如何一步一步设计CynosDB的高可用系统的,然后介绍了CynosDB中VDL的快速恢复原理,接着是整个CynosDB高可用系统的整体架构介绍,最后阐述了CynosDB是如何解决经典“脑裂”问题的。

Q:我们因为业务需要要部署不同地区的系统,要不同地域之间实施数据的一致性,用CynosDB的话,有比较成熟的方案吗?我们系统现在主要是用腾讯云的北京和广州,咱们这边有没有好的方案。

A:CynosDB在计算层是一主多从的架构,在存储层可以保证数据的多个副本分布在多个可用区,数据的一致性在存储层来保证。所以CynosDB可以满足跨AZ数据一致性的需求。

Q:意思是不同的地域往一个地区写吗?现在我们好像需要多写。

A:多写这种架构,除了spanner,还没有能搞定的存储系统,多主架构我们也在开发中,可以关注一下后续CynosDB的进展。

Q:还有是我们的数据量,数据量每天在一个表里面是三千万左右,我们现在的开发也很简单,每天一个表,现在的存储已经比较吃力了,所以说如果用CynosDB之后,里面数据会在存储层自动分层还是会有什么好的优化?

A:对于存储,CynosDB其实解决了用户一个最大的痛点,单机存储量的上限, CynosDB一个实例可以做到上百TB,存储量基本没问题。你刚才说的每个表,可能有三千万行的数据,对于这个,分库分表还需要业务去做,CynosDB不会自动分库分表,每个表中具体数据量多少比较合适,这个是MySQL自己本身的限制,一般情况建议最多千万级的,上亿的话对整个查询性能都有影响了。

Q:比如我们现在还是一种架构直接迁移到CynosDB上,性能会有提升吗?

A:架构整个迁移不会有任何问题的,迁移会带来性能上很大的提升,以及不用考虑存储上限的问题,这些都能解决。

Q:我们的业务跟之前类似,是跨地区的,如果这种情况下写入的时候会有延迟是吧。

A:是多个地区写同一个Master吗?

Q:对,仅单数的情况,对性能的损耗和延迟,相对传统的MySQL来说,数据库对于一个连接数和处理的性能方面,有什么更好的提高吗?

A:连接数方面跟传统MySQL保持一致,性能方面,CynosDB由于在计算层和存储层都做了很多优化,比如锁拆分和减少IO,所以会带来性能上很大的提升。

Q:这个大并发是对于磁盘还是?

A:不是基于磁盘,因为CynosDB不会在本地有保存数据文件,所有的数据都存在底层,这个大并发下的性能提升主要是通过在计算层砍掉了很多不必要的IO、锁拆分以及线程池等手段来保证的。

Q:因为之前我们使用腾讯的MySQL,它对于IOPS是针对磁盘以及存储的。

A:CynosDB主要是网络IO。

Q:也就是用新数据库会避免这个问题是吗?

A:对,首先本地磁盘IO少了很多,在不开启binlog的情况下,基本都是网络IO,其次,存储层的IO包括写日志的顺序IO和apply时的随机IO,随机IO是异步的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档