OceanBase高可用实践

背景

高可用是构建分布式系统的基石。一方面,出于成本考虑, 分布式系统每每采起比较廉价的硬件,其可靠性相对于小型机、专有硬件有很大的不足, 而分布式系统的规模通常比较大,假如硬件的可靠性只有三个9(99.9%), 一个1000台机器规模的集群天天将面临1台机器宕机的风险,在如此大规模的状况下,存储介质,好比硬盘可能会随时都有损坏,结点之间的网络可能随时都会有抖动,机房可能局部或总体断电,地区或数据中心可能会出现不可用,若是不在设计时考虑这些问题,当这些状况出现的时候,系统将很快处于不可用的状态;另外一方面,分布式系统的程序在设计与实现上也更为复杂,软件上既要容错硬件的不可靠,同时软件自身也有可能有问题, 在对外部环境容错的同时须要考虑对软件BUG的容错。linux

OceanBase在设计之初就充分考虑了高可用问题,确保OceanBase有能力在这些异常出现后,仍然能最大可能的提供服务。算法

高可用的基本策略

冗余是实现高可用的通用方法,为防止数据丢失,将数据冗余多份;为防止系统中某些节点故障,对某些功能节点进行冗余。 冗余带来的好处是能够抵御某些节点的损失,而带来的坏处则主要是成本、性能和一致性问题。数据库

成本主要包括额外的存储、网络、机柜等硬件成本,这是构建高可用分布式系统的必不可少的开销,其整体成本较专有硬件仍然要低,由于专有硬件实际上也须要在内部对某些模块进行冗余以获取高可用性。 性能和一致性问题则是高可用分布式系统必需要处理问题,这两个问题直接影响整个系统正确性、延时与吞吐量。安全

在传统myql或oracle中,咱们每每经过添加备机来实现高可用,且为了实现高性能和高可用,通常会使用“最大可用”模式:服务器

主机尽力将数据同步到备机,而无论是否同步成功,当主机挂掉之后,将备机升级成主机以继续提供服务,这就意味着若是主机在宕机前有数据没有同步到备机,要么经过某种特殊的手段将数据从宕掉的主机同步到备机,要么就接受暂时的数据不一致而继续提供服务,在这种状况下,若是出现主机永久损坏,则会形成数据丢失:网络

为了解决这个问题,可使用最大保护模式(早期的MySQL版本不支持),即主机将日志同步到备机成功后再应答客户,这样会引入另一个问题,即备机故障或网络抖动会致使失败,影响可用性; 小微引入了共享存储,将数据库redo log放在共享存储上,主机宕机之后,备机须要确保主机全部的数据都已经同步才能对外提供服务:并发

这样在主机宕机时,备机做一些额外的检查后升级为主机继续提供服务,这样能够确保数据一致性,但引入了共享存储。传统的主备模式还有另一个问题是主备之间没法经过自身决出主备,须要人工切换或者使用一个第三方组件:oracle

可是又引入了HA模块的稳定性问题,若是HA模块和主机的网络不通, HA将不能识别主机是活着仍是网络有问题,此时HA若是进行切换而主机还活着则会形成后果很严重的双主问题。异步

OceanBase高可用策略

故障能够分为单机故障(磁盘、内存等硬件介质损坏或单台软件Crash都属于单机故障),机架/机房故障(好比整个机架或机房的电源断电)以及地区/数据中心(好比地区地震形成该区网络隔离)故障,通常来讲,故障单位越小,出现频率越高,而除非天然灾害,一个地区出现故障的几率极小,故障单位越小,实现高可用的难度和成本越低,故障单位越大,因为引入环境、距离等因素,实现高可用的难度和成本会呈指数倍增加。好比为了预防单机故障,只须要在本机房预备冗余节点,故障时经过某些技术方案,能够作到实时切换;而为了预防数据中心故障,则须要在另一个地区预备冗余的数据中心,在故障时因为通讯距离等缘由,基本上没法作到无损切换。分布式

OceanBase虽然在设计之初就考虑到了硬件和软件的不可靠,但OceanBase的高可用并不是一蹴而就,在实现过程当中,为了快速实现或者绕过某个暂时没法攻克的技术难点,会进行综合权衡,只实现一些出现几率较高的基本高可用策略,而经过人肉或其它手段来保证在某些很难出现的灾难出现后能够尽快恢复。而后经过逐步迭代,逐渐完善,将高可用的范围提升,好比OceanBase最初的时候只考虑单机故障的高可用,到目前为止已经能够实现同城IDC之间的容灾。

分布式系统为了设计与实现的简单,每每会在系统中设置一个全局单点,来负责相对比较轻量的管理任务, OceanBase中的rootserver就是这样一个角色;它主要负责集群中其它角色的管理并做为用户的入口,一般其压力不高且无本地数据须要存储,所需信息均可以经过其它角色的汇报来重建。

而做为一个分布式数据库,OceanBase面临着两个很难解决的问题:数据一致性与分布式事务,在早期的OceanBase版本中,采起的策略是暂时绕过这两个问题,等技术积累到必定程度后再回过头来解决,因此在OceanBase中另外增长了一个单写入节点,这个节点的压力很高,数据没法经过其它节点来恢复,咱们须要保证这些单节点的高可用。另一个是保存基线数据结点的高可用,这些结点被设计成能够弹性伸缩,自己具有高可用属性,但仍然须要考虑磁盘故障以及数据副本之间的一致性。 咱们会在下面的章节分别描述对这两类节点的高可用策略。

系统单点

在早期OceanBase的版本中,主要依靠主备来为单点提供高可用, 使用两台机器,其中的一台角色为主的机器对外提供服务,另一台机器作为热备, 当主机挂掉后,备机切换为主,继续提供服务。

如前所述,这种“最大可用”模式的主备机制主要有两个问题:第一个问题在于这两台机器没法经过自身来决出主备,必需要依赖于一个第三方组件,早期咱们使用了HA(linux-ha.org) 来作为仲裁组件,HA使用VIP机制,两台机器共享VIP, 同一时刻VIP只会加载在其中的一台机器, VIP会提供给外部应用程序做为OceanBase集群的入口地址,即VIP加载在哪一台机器上,该机就会做为主对外提供服务,程序能够经过不断检测VIP是否存在来判断本机是否为主机,当HA经过咱们提供的检测程序检测到主机故障后,就会将VIP切换到备机, 此时外部请求就会路由到原来的备机,原来的备机检测到VIP“飘”到本机后,会将本身的角色置为主:

使用HA主要有几个问题:

  1. HA为了防止网络抖动带来的误判,要求将两台机器使用网线直连, 这就限制了两台机器只能放在一个机柜,若是整个机柜断电,则服务不可用,这样就不能抵御机柜以及机房的容灾。
  2. 数据一致性不能保证,通常不要求使用HA的角色持久化特别重要的数据。 其数据应该能经过其余角色的汇报而重建。

另一个问题在于这种机制没法保证数据不丢失, 某些极端状况下须要停机恢复,若是有机器永久损失,则可能会形成数据的丢失,在某些业务上可能没法接受。

而Updateserver是OceanBase中相当重要的节点,其数据丢失直接影响用户,也不能经过其它类型节点来重建,因此Updateserver最先抛弃HA模式,而改成经过Rootserver来选主:

Updateserver每次写入都会生成一条日志,每条日志有一个唯一且单调递增的日志号, 各Updateserver向Rootserver汇报本身的日志号, Rootserver选取日志号最大的Updateserver为主并发放租约,备Updateserver同时须要向主Updateserver注册,由主Updateserver发放租约。Updateserver使用一主多备的形式, 每次写入必需要写入多数派个节点成功才能应答客户,写入请求首先发送到主Updateserver,主Updateserver生成日志并同步到备机,收到多数派个成功回应之后应答客户。若是收不到足够多的回应,则不会应答客户端,该条写入可能生效,也可能不生效。

因为要求写入多数派个节点才算成功,因此主备间的网络延迟不能过高,目前OceanBase要求updateserver主备分布在同城的不一样IDC, 若是采起一主两备的模式, 最大能够容忍一个同城IDC故障。

当某一台机器同步日志失败时,主机会将其剔除在恢复以前再也不向其同步日志, 这对网络要求很高,若是网络连续出现抖动,则会形成可用性问题。在最新版本OceanBase, 将同步日志的方式也改成Paxos方式,一条日志只须要写到多数派个结点上成功便为成功,不须要各台备机顺序回应,进一步容忍短暂的网络问题。

虽然Updateserver去掉了对HA的依赖,但Rootserver仍然须要HA来选主,因为HA没法部署在两个IDC,因此咱们对IDC之间的容灾使用的策略是在另一个IDC部署一个备集群,在主集群出现故障时,经过人肉的方式将备集群切换为主来提供服务。

基于这个缘由,OceanBase 在0.5里完全取消了基于HA的主备机制,而是经过使用相似paxos的算法来进行选举:

让程序自身投票来决出主备, 当一台机器获得多数派的承认,它便可以成为主,这样系统能容忍必定数量节点的不可用,好比,若是是2台,则不能容忍有机器宕机,3台则能够容忍一台机器宕机, 3台机器能够部署在不一样的机房以容忍机房故障。

Updateserver仍然经过Rootserver来选主,但这样也存在一个问题,当Updateserver和Rootserver同时故障的时候,Updateserver必需要等Rootserver恢复完成后才能恢复,增长了故障恢复的时间 。在后续的OceanBase版本中,将去除Updateserver这个单写入节点,并将其选主的权力下放到自身,摆脱由Rootserver选主的局面。届时Rootserver的工做会更为简单,单点不会成为OceanBase的瓶颈。

基线数据

Rootserver/Updateserver是经过冗余节点来进行容灾,备节点通常不提供服务或只提供有限的服务,基线数据则是经过冗余数据来实现高可用与扩展服务能力。经过冗余3~6份数据来提供更多的服务能力。冗余的数据不能存储在相同的机器上,以免机器宕机后损失可用性。同时在可能的状况下,数据须要分布在不一样的机架上,以抵御整机架断电或断网,OceanBase在早期的实现中,为了简化实现与对机器分布的要求,未考虑数据分布在不一样的机柜,曾出现过整机架断网而形成服务不可用。

基线数据的副本数决定了一个集群同时有多少台机器能够宕机,若是使用三副本,则同时能够有两台机器宕机,每一个基线数据结点都和Rootserver保持心跳,当该结点宕机之后,rootserver会检测到并根据目前系统中所拥有的副本数量启动复制,为了不因网络抖动所带来的没必要要的副本复制,咱们设定在安全的状况下(好比剩余副本数大于1) 能够容忍副本丢失一段时间(好比8小时),当副本丢失超出该时长后才启动复制。

副本数的选择和集群中机器的数量、单机数据量以及数据恢复速度相关,通常状况下会选择至少3个副本,由于2副本状况下,若是出现一个副本丢失,集群须要当即启动复制,而此时集群可能正处于请求高峰期。阳老师有一个关于副本数选择的计算方法:

“假设总共有N个节点计算机,它们的平均无端障时间都是M,云计算系统对一个数据副本丢失并进行复制的时间为T,则一台计算机在T时间内出故障的几率是T/M,不出故障的几率是(1-T/M):

N台机器在该时间内都不出故障的几率是(1-T/M)的N次方;

N台机器在该时间内刚好有1台出故障的几率是:(1-T/M)的(N-1)次方T/MN;

N台机器在该时间内刚好有2台出故障的几率是:

(1-T/M)的(N-2)次方T/MT/MN(N-1)/(2*1)

所以,N台机器在该时间段内至少有两台机器故障的几率是:

P2(N, M, T)=1-都不出故障的几率-刚好1台出故障的几率

所以,N台机器在该时间段内至少有两台机器故障的几率是:

P3(N, M, T)=1-都不出故障的几率-刚好1台出故障的几率--刚好2台出故障的几率

所以假如N=1000,M=50,000小时,T=600秒,则

P2 (N=10台,M=50,000小时,T=600秒) = 5.0*10的-10次方;

P2 (N=1000台,M=50,000小时,T=600秒) = 6.1*10的-9次方;

P2 (N=5000台,M=50,000小时,T=600秒) = 1.4*10的-4次方;

P3 (N=10台,M=50,000小时,T=600秒) = 4.5*10的-15次方;

P3 (N=1000台,M=50,000小时,T=600秒) = 6.2*10的-9次方;

P3 (N=5000台,M=50,000小时,T=600秒) = 7.6*10的-7次方;

能够看出,当机器数量达到5000台时,至少3台机器出故障的几率低于百万分之一,而至少两台机器出故障的几率高于万分之一。所以采用3个数据副本时数据有比较高的可靠性。”

并计算出一个表格,假设故障时其它服务器以25MB/s的速度恢复丢失数据:

MTBF为机器的平均无端障时间,从表中能够看出三副本同时丧失的几率是极低的。

基线数据的另外一个较为广泛的异常为磁盘损坏, OceanBase存储基线数据的角色为ChunkServer, ChunkServer并未使用RAID方式来使用磁盘,一块磁盘损坏就意味着永久损失该盘上的全部数据,须要Rootserver从另外的机器上进行复制。 当ChunkServer检测到该磁盘出错(读取或写入失败)时,会主动将该盘剔除并上报, 让Rootserver启动复制程序补足副本。

基线数据须要和增量数据合并而产生新的基线数据,这个过程是由每台ChunkServer各自完成本身所负责的数据分区,即相同数据的几个副本会各本身完成这个合并过程,为了保证各台ChunkServer合并出来的新基线数据是一致的,每台Chunkserver在汇报副本信息的时候须要同时汇报校验值,以检查副本是否一致,若是出现不一致的状况,则是软件有bug或数据有问题,ChunkServer保留两个版本,解决问题后回退到上一个版本进行从新合并。这种问题出现通常都是软件Bug, 根据以前的经验,出现这种状况的时候,用户有可能已经读到不正确的数据,而形成这种问题的主要缘由是Updateserver节点的数据不一致,咱们经过改造Updateserver的日志同步方式(由主备改成一主多备且要求多数派成功)和增强校验后,这个问题已经获得杜绝。

跨数据中心容灾

到目前为止,OceanBase能够部署在同城的不一样IDC并容忍少数个IDC故障。OceanBase通常会在同城选择三个不一样的IDC进行部署。 目前还没法作到跨数据中心的容灾。 主要缘由是因为通讯距离的增长,异地数据中心之间的网络延时较高,没法作到同步复制数据,而经过异步的形式进行复制则没法作到无损容灾,咱们目前经过一些手段,好比实时拷贝数据库的redo log到异地数据中心,能够作到最坏状况只丢失几秒的数据。

总结

相较于传统的主备模式,OceanBase能够容忍少数派的节点损坏不中断服务且不丢失数据,为不少须要高可用且不能丢数据的业务提供了共享存储之外的解决方案。


原文连接 本文为云栖社区原创内容,未经容许不得转载。

相关文章
相关标签/搜索