【数据库】从系统架构上描述 OceanBase 的高可用与容灾

高可用架构

OceanBase 数据库体系架构

在这里插入图片描述
如图所示,数据服务层表示一个 OceanBase 数据库集群。该集群由三个子集群(Zone)组成,一个 Zone 由多台物理机器组成,每台物理机器称之为数据节点(OBServer)。OceanBase 数据库采用 Shared-Nothing 的分布式架构,每个数据节点都是对等的。

Shared-Nothing 的分布式架构,曾在之前博文中讲过,详见:
【数据库】各种并行架构如何进行进程和内存协调?

OceanBase 数据库中存储的数据分布在一个 Zone 的多个数据节点上,其它 Zone 存放多个数据副本。如图所示的 OceanBase 数据库集群中的数据有三个副本,每个 Zone 存放一份。这三个 Zone 构成一个整体的数据库集群,为用户提供服务。

根据部署方式的不同,OceanBase 数据库可以实现各种级别容灾能力:

  • 服务器(Server)级无损容灾:能够容忍单台服务器不可用,自动无损切换。
  • 机房(Zone)级无损容灾:能够容忍单个机房不可用,自动无损切换。
  • 地区(Region)级无损容灾:能够容忍某个城市整体不可用,自动无损切换。

当数据库集群部署在一个机房的多台服务器时,实现服务器级别容灾。当集群的服务器在一个地区的多个机房中时,能够实现机房级别容灾。当集群的服务器在多个地区的多个机房中时,能够丝线地区级别容灾。

OceanBase 数据库的容灾能力可以达到 RPO=0,RTO=30 秒的国标最高的 6 级标准。

高可用

OceanBase 分布式集群的多台机器同时提供数据库服务,并利用多台机器提供数据库服务高可用的能力。在上图中,应用层将请求发送到代理服务(ODP,也称为 OBProxy),经过代理服务的路由后,发送到实际服务数据的数据库节点(OBServer),请求的结果沿着反向的路径返回给应用层。整个过程中不同的组件通过不同的方式来达到高可用的能力。


在数据库节点(OBServer)组成的集群中,所有的数据以分区为单位存储并提供高可用的服务能力,每个分区有多个副本。一般来说,一个分区的多个副本分散在多个不同的区里。多个副本中有且只有一个副本接受修改操作,叫做主副本(Leader),其他叫做从副本(Follower)。主从副本之间通过基于 Multi-Paxos 的分布式共识协议实现了副本之间数据的一致性。当主副本所在节点发生故障的时候,一个从节点会被选举为新的主节点并继续提供服务。

选举服务是高可用的基石,分区的多个副本通过选举协议选择其中一个作为主副本(Leader),在集群重新启动时或者主副本出现故障时,都会进行这样的选举。选举服务依赖集群中各台机器时钟的一致性,每台机器之间的时钟误差不能超过 200 毫秒,集群的每台机器应部署 NTP 或其他时钟同步服务以保证时钟一致。选举服务有优先级机制保证选择更优的副本作为主副本,优先级机制会考虑用户指定的 Primary Zone,考虑机器的异常状态等。

当主副本开始服务后,用户的操作会产生新的数据修改,所有的修改都会产生日志,并同步给其他的备副本(Follower)。OceanBase 数据库同步日志信息的协议是 Multi-Paxos 分布式共识协议。Multi-Paxos 协议保证任何需要达成共识的日志信息,在副本列表中的多数派副本持久化成功后即可保证,在任意少数派副本故障时,信息不会丢失。Multi-Paxos 协议同步的多个副本保证了在少数节点故障时系统的两个重要特性:数据不会丢失、服务不会停止。用户写入的数据可以容忍少数节点的故障,同时,在节点故障时,系统总是可以自动选择新的副本作为主副本继续数据库的服务。


OceanBase 数据库每个租户还有一个全局时间戳服务(GTS),为租户内执行的所有事务提供事务的读取快照版本和提交版本,保证全局的事务顺序。如果全局时间戳服务出现异常,租户的事务相关操作都会受到影响。OceanBase 数据库使用与分区副本一致的方案保证全局时间戳服务的可靠性与可用性。租户内的全局时间戳服务实际会由一个特殊的分区来决定其服务的位置,这个特殊分区与其他分区一样也有多副本,并通过选举服务选择一个主副本,主副本所在节点就是全局时间戳服务所在节点。如果这个节点出现故障,特殊分区会选择另一个副本作为主副本继续工作,全局时间戳服务也自动转移到新的主副本所在节点继续提供服务。


以上是数据库集群节点实现高可用的关键组件,代理服务(ODP,也称为 OBProxy)也需要高可用能力来保证其服务。用户请求首先到达的是代理服务,如果代理服务不正常用户请求也无法被正常服务。代理服务还需要处理数据库集群节点故障,并做出响应的容错处理。

代理服务不同于数据库集群,代理服务没有持久化状态,其工作依赖的所有数据库信息都来自于对数据库服务的访问,所以代理服务故障不会导致数据丢失。代理服务也是由多台节点组成集群服务,用户的请求具体会由哪个代理服务节点来执行,应由用户的F5或者其他负载均衡组件负责,同时代理服务的某台节点故障,也应由负载均衡组件自动剔除,保证之后的请求不会再发送到故障节点上。

代理服务工作过程会实时监控数据库集群的状态,一方面代理服务会实时获取集群系统表,通过系统表了解每台机器的健康状态和分区的实时位置,另一方面代理服务会通过网络连接探测数据库集群节点的服务状态,遇到异常时会标记相应节点的故障状态,并进行相应的服务切换。

代理高可用

OceanBase 数据库代理 ODP(OceanBase Database Proxy,又称 OBProxy)是 OceanBase 专用的代理服务。ODP 自身就有高可用设计。

ODP 部署模式

合并部署
  • 以 OCP 方式启动
    • 可以访问多个集群。
    • 若 OCP 挂掉后,已访问过的集群可以正常访问,未访问过的集群不可访问。
  • 以 RSList 方式启动(只可以访问单集群,IP 为 127.0.0.1)
    • 固定访问某个集群,不依赖 OCP。本机有问题后,SLB 探测并切流,无需 ODP 额外动作。
    • 可处理部分 POC 机器故障场景。
独立部署
  • 以 OCP 方式启动
    • 可以访问多个集群。
    • 若 OCP 挂掉后,已访问过的集群可以正常访问,未访问过的集群不可访问。
  • 以 RSList 方式启动
    • 固定访问某个集群,不依赖 OCP。RS List 如果有问题,可能导致集群不可访问。

ODP 容灾能力

发现故障
  • 定时任务,刷新 OBServer、Zone、主备集群状态。
    • 方案限制:依赖 OBServer 的状态更新。可能存在 OBServer 出问题(如:磁盘 hang 住),但是没有 inactive 或者 stop server,这个时候状态不会变化。
  • Server 连接保持 与 KeepAlive 探活机制,探测 OBProxy 与 后端 OBServer 的连接状况,如果空闲连接异常断开,OBProxy 可以及时发现,剔除并新建。
  • Client KeepAlive 探活机制,探测 OBProxy 与 Client 的连接状况,同时可以避免 SLB 等负载均衡的空闲超时。
处理故障

处理进行中的请求 异步中止机制,当检测到机器故障后,及时中止,避免长时间等待,业务连接池被打爆 处理新请求

  • 黑名单机制,避免新请求发送到故障机器。
    • OBServer 多次访问失败会加入黑名单。在加入黑名单一段时间后,会发起探测请求,探测该机器是否可访问。
      方案限制:如果客户端先超时断开连接,不会加入黑名单。
    • OBServer 状态变更为非 active,也会加入黑名单。
      方案限制:RTO 依赖 【发现故障-定时任务】 的周期(目前是 20s,可配置) 和 OBServer 的探测时间。
  • 异步刷新 table location cache 机制,检测副本是否切换,如果机器故障后发生了副本切换,可以及时路由到新的副本上。
    方案限制:依赖 OBServer 告诉 ODP 路由有问题,如果 OBServer 有问题,一直没返回,table location cache 不会刷新。
  • 两中心主备库场景,有主备库切换机制,如果主集群发生了切换,可以快速切换到新的主集群。
    方案限制:RTO 依赖 【发现故障-定时任务】 的周期(目前是 20s,可配置) 和 OBServer 的切换时间。

分布式选举

在分布式系统的设计中,要解决的最主要问题之一就是单点故障问题(single point of failure (SPOF) )。为了能在某个节点宕机后,系统仍然具备正常工作的能力,通常需要对节点部署多个副本,互为主备,通过选举协议在多副本中挑选出主副本,并在主副本发生故障后通过选举协议自动切换至备副本。

主副本称为 Leader,备副本称为 Follower。

在分布式系统中,一个工作良好的选举协议应当符合两点预期:

  • 正确性
    即当一个副本认为自己是 Leader 的时候,不应该有其他副本同时也认为自己是 Leader,在集群中同时有两个副本认为自己是 Leader 的情况称为"脑裂",如 Raft 协议中的选举机制,通过保证为每个 Term 只分配一个 Leader 来避免脑裂,但是原生 Raft 中同一时刻可能有多个副本认为自己是 Leader(尽管它们分管不同的 Term,且更小的 Term 的主副本已经失效但是其不自知),使用原生的 Raft 协议必须读取多数派的内容来保证读取到的数据最新,OceanBase 数据库通过 Lease 机制避免对多数派的访问,确保在任意的时间点上只有一个副本能认为自己是 Leader。
  • 活性
    即任意时刻,当 Leader 宕机时,只要集群中仍然有多数派的副本存活,那么在有限的时间内,存活副本中应当有副本能够成为 Leader。

在满足正确性和活性的基础上,OceanBase 数据库的选举协议还提供了优先级机制与切主机制,优先级机制在当前没有 Leader 的情况下在当前可当选 Leader 的多个副本中,选择其中优先级最高的副本称为 Leader;切主机制在当前有 Leader 的情况下可以无缝将 Leader 切换至指定副本。

Lease 机制

Lease 机制,翻译过来即是租约机制,是一种在分布式系统常用的协议,是维护分布式系统数据一致性的一种常用工具。

Lease 机制特点
  • Lease 是颁发者对一段时间内数据一致性的承诺;
  • 颁发者发出 Lease 后,不管是否被接收,只要 Lease 不过期,颁发者都会按照协议遵守承诺;
  • Lease 的持有者只能在Lease的有效期内使用承诺,一旦 Lease 超时,持有者需要放弃执行,重新申请 Lease。
Lease 机制解决了什么问题?

分布式系统中,单使用心跳确认节点是否正常的情况下,如果仅仅是网络抖动或者网络中断则会有可能导致从节点认为主节点挂掉从而选举出新的主节点,产生脑裂。

这种情况有四种解决方式:

  1. 设计能容忍双主的分布式协议;
  2. Raft 协议通过 Term 版本高的同步低的;
  3. Lease 机制
  4. 涉及去中心化-Gossip协议。
Lease 原理
  1. 引入中心节点负责下发 Lease;
  2. 在已下发 Lease 过期之前,拒绝向其他节点申请 Lease,即不承认其他节点成为主节点;
  3. 如果原主节点在 Lease 过期之前续约,继续为其下发新的 Lease,如果原主节点未能续约,则向选举出的新主节点发放 Lease。
Lease 的容错
  1. 主节点宕机:Lease 机制天生即可容忍网络、Lease 接收方的出错时间即 Lease 剩余过期时长;
  2. 中心节点异常:颁发者宕机可能使全部节点没有 Lease,系统处于不可用状态,解决的方法是使用一个小集群而不是单一节点作为颁发者;
  3. 时差问题:中心节点与主节点之间的时钟可能存在误差,只需要中心节点考虑时钟误差即可。
建议

Lease 时间长短一般取经验值 1-10 秒即可。太短网络压力大,太长则收回承诺时间过长影响可用性。

假设与容错

OceanBase 数据库假定其运行的物理环境满足一定的约束:

  • 任意两台机器间的单程网络延迟应当满足小于某个上限值,称为 MAX_TST。
  • 集群中所有机器的时钟与 NTP Server 进行同步,且与 NTP Server 的时钟偏差小于给定的最大偏差,称为 MAX_DELAY。

目前参数:MAX_TST = 200ms,MAX_DELAY = 100ms。
注意到,若任意机器与 NTP 服务器的时钟偏差不超过 100ms,则任意两台机器间的时钟偏差不超过 200ms。

当时钟偏差和消息延迟的假设不满足时,将发生无主,但是由于安全接收窗口的检查,无论是否满足环境约束,选举协议的正确性都是可以保证的。

优先级

在选举的第一阶段,所有副本都会在同一时刻广播自己优先级,这将使得每个副本都具备足够的信息比较所有副本的优劣,集中投票给同一副本,这一方面避免了选举的分票,另一方面也让选举协议的结果更符合预期,更好预测。

选举优先级是一系列字段的集合,这些字段都有各自的比较规则,这些字段优先级从高到低包括:

  1. 成员列表版本号(越大优先级越高)
  2. 副本所在的 region 的属性(primary region > 非 primary region)
  3. 内存满状态(未满 > 已满)
  4. 程序初始化状态(已初始化 > 未初始化)
  5. 选举黑名单状态(不在黑名单 > 在黑名单)
  6. Rebuild 状态 (不需要 Rebuild > 需要 Rebuild)
  7. 数据盘状态 (数据盘无错误 > 数据盘有错误)
  8. 租户内存满状态 (租户内存未满 > 租户内存满)
  9. CLOG 盘状态 (CLOG 盘无错误 > CLOG 盘有错误)
  10. 副本类型(F 副本 > 非 F 副本)
  11. CLOG 盘满状态 (CLOG 盘未满 > CLOG 盘满)
  12. CLOG 日志数量 (越多优先级越高)

切主

用户可以指定分区 Leader,RS 会给对应的分区发消息以完成 Leader 的变更,这种变更通常是很快的。

用户也可以变更 primary region,RS 将指挥分区将 Leader 切换至新的 primary region 上。

当用户开启 enable_auto_leader_switch 选项后,RS 会在 primary zone 中使用切主的方式平滑的分散 leader 的分布。

多副本日志同步

日志服务作为关系数据库的基础组件,在 OceanBase 数据库中的重要性主要体现在如下方面:

  • 通过在事务提交时持久化 MemTable Mutator 的内容以及事务状态信息,为事务的原子性(Atomic)和持久性(Durability)提供支持。
  • 通过生成 trans_version,并通过 keepalive 消息同步到所有备机(以及只读副本),为事务的隔离性(Isolation)提供支持。
  • 通过实现 Paxos 协议将日志在多数派副本上实现强同步,为分布式数据库的数据容灾以及高可用提供支持;并进而支持各类副本类型(只读副本、日志副本等)。
  • 通过维护权威的成员组和 Leader 信息,为 OceanBase 数据库中的各个模块所使用。为 RootService 的负载均衡、轮转合并等复杂策略提供底层机制。
  • 提供外部数据服务,为 OMS 和增量备份等外部工具提供增量数据。

OceanBase 数据库日志服务的挑战

与传统关系型数据库的日志模块相比,OceanBase 数据库的日志服务主要有如下几点挑战:

  • 通过 Multi-Paxos 替换传统的主备同步机制,进而实现系统的高可用和数据的高可靠。需要支持全球部署,多个副本之间的网络时延达到几十甚至数百 ms。
  • 作为分布式数据库,OceanBase 数据库以 Partition 作为数据同步的基本单位。单机要求支持十万量级的 Partition,在此基础上,需要支持日志数据的高效写入和读取。同时,任何功能本身均需要考虑操作的批量化,以加速执行速度。
  • 日志服务维护副本的成员列表、Leader 等状态信息,需要为分布式系统的丰富功能提供高效的支持。

整体结构

整体结构示意图

Paxos Core

Paxos Core 是日志服务的核心。日志服务实现了一套标准的 Multi-Paxos 协议,保证在未发生多数派永久性故障的前提下,所有提交成功的数据均可恢复。

Paxos Core 实现了乱序日志提交,保证事务之间无依赖,同时对异地部署非常友好,避免单个网络链路故障影响后续所有事务的 rt。

为确保 Multi-Paxos 的正确性,日志服务提供了多层次的 checksum 校验:

  • 单条日志的 checksum 校验。
  • Group Commit 后 Block 整体的 checksum 校验。
  • RPC packet 的 checksum 校验。
  • log_id 的累积 checksum 校验,每一条日志都校验当前 Partition 之前所有日志的正确性。

正确、高效的协议实现、不间断运行的容灾切换测试用例以及实时完备的 Checksum 校验,一同确保日志服务的正确性。

成员组管理

日志服务维护着每个 Partition 的成员组信息。成员组信息包括当前 Paxos Group 的 member_list 以及 Quorum 信息。

支持的功能如下:

  • add_member/remove_member, 支持加减成员。负载均衡发起的迁移、宕机引起的补副本操作,均需要通过上述功能修改 Partition 的成员组。
  • modify_quorum,修改 Paxos Group 的法定副本数。执行 Locality 变更(例如, 3F->5F),地域级故障降级容灾(5F->3F),均需要通过上述功能修改 paxos group 的法定副本数。

上述功能均提供了批量操作接口,允许将多个 Partition 的操作批量执行,极大的提升了相关操作的执行效率。

如通过 batch_modify_quorum 接口,单机 1 万个分区 5F->3F 的降级容灾操作执行时间由 20 分钟优化到只需要 20s,极大的提升了系统在故障场景下的容灾能力和响应时间。

有主改选

OceanBase 数据库作为使用 LSM tree 实现的数据库系统,需要周期性的将 MemTable 的内容转储或合并到磁盘,在执行合并时需要消耗大量 CPU。为了避免合并时影响正常的业务请求,也为了加快合并速度,OceanBase 数据库通过轮转合并,在执行合并前将 Leader 切换到同 Region 的另外一个副本。

日志服务为有主改选提供支持。有主改选执行分两步:

  1. RS 查询每个待改选 Partition 的有效 candidates。
  2. RS 根据 candidates list 以及 Region、Primary Zone 等信息,确定改选目标,下发命令,执行改选请求。

故障恢复

OceanBase 数据库在线上实际运行过程中难免遇到各类故障(磁盘、网络故障,机器异常宕机等)。作为高可用的分布式数据库系统,必须能够在各种故障场景应对自如,保证 RPO = 0,RTO 尽量短。这里按照不同的故障类型分别讲述日志服务在其中所起到的作用:

  1. Leader 节点以外的其他节点出现少数派宕机:由于 Paxos 要求日志只需要同步到 majority 即可,对可用性无影响,RPO=0,RTO=0。
  2. 包括 Leader 节点在内出现少数派宕机:通过无主选举+paxos 恢复流程,保证在 lease 过期后很短的时间内即选出新的 Leader 提供服务,且数据无任何丢失,RPO = 0,RTO < 30s。
  3. Leader 节点以外的其他少数派节点出现网络分区:由于 paxos 要求日志只需要同步到 Majority 即可,对可用性无影响,RPO=0,RTO=0。
  4. 包括 Leader 节点在内的少数派节点出现网络分区:通过无主选举+paxos 恢复流程,保证在 lease 过期后很短的时间内即选出新的 Leader 提供服务,且数据无任何丢失,RPO = 0,RTO < 30s。
  5. 多数派节点宕机:此时服务中断,需要重启宕机进行副本恢复。
  6. 集群全部宕机:此时服务中断,需要重启宕机进行副本恢复。

除上述描述的宕机或网络分区场景外,真实业务的故障场景会更加多样化。OceanBase 数据库除了可以处理上述场景外,对于多种磁盘故障(完全 hang 住或写入缓慢)可以进行自动检测,在 1 分钟内切走 Leader 和备机读流量,保证业务及时恢复。

只读副本、级联同步以及副本类型转换

日志服务通过保证 log_id 和 trans_version 偏序,以及百毫秒级的 Keepalive,用以支持备机和只读副本的弱读功能。

只读副本不是 Paxos Group 的成员,我们通过自适应的结合 Locality 信息的级联算法,自动为只读副本构建上下游关系,实现数据的自动同步。

除只读副本外,日志服务支持日志副本(日志副本有特殊的日志回收策略)以及三种副本类型之间的相互转换。

Paxos 协议

OceanBase 数据库使用 Paxos 的优化 Multi-Paxos 实现多副本数据同步以及集群的高可用。

Paxos 一致性协议的原理

Basic Paxos

在节点宕机、消息无序等场景可能出现的情况下,相互独立的节点之间如何达成决议的问题,作为解决一致性问题的协议,Paxos 的核心是节点间如何确定并只确定一个值(value)。

proposer 为提议者,acceptor 为决策者。假设有多个 proposer 和 acceptor。如果proposer/acceptor 满足下面3点,那么在少数节点宕机、网络分化隔离的情况下,在“确定并只确定一个值”这件事情上可以保证一致性(consistency):

  • 每一轮决议都有唯一的ID标识;
  • 如果决议 B 被 acceptor 多数派接受,则确定决议 B;
  • 对于任意提议 B(n,v),acceptor 的多数派中如果存在 acceptor 最近一次(即 ID 值最大)接受的提议的值为 v’,那么要求 v = v’;否则 v 可为任意值。

并且对 acceptor 作两个要求:

  1. 记录曾接受的 ID 最大的提议,因 proposer 需要问询该信息以决定提议值;
  2. 在回应提议 ID 为 n 的 proposer 自己曾接受过 ID 最大的提议时,acceptor 同时保证(promise)不再接受 ID 小于 n 的提议。

至此,proposer/acceptor 完成一轮决议可归纳为 prepare 和 accept 两个阶段。prepare 阶段proposer 发起提议问询提议值、acceptor 回应问询并进行 promise;accept 阶段完成决议,图示如下:

示意图
还有一个问题需要考量,假如 proposer A发起 ID 为 n 的提议,在提议未完成前 proposer B又发起 ID 为 n+1 的提议,在 n+1 提议未完成前 proposer C 又发起 ID 为 n+2 的提议…… 如此 acceptor 不能完成决议、形成活锁(livelock),虽然这不影响一致性,但一般不想让这样的情况发生。解决的方法是从proposer中选出一个 leader,提议统一由 leader 发起。

learner 依附于 acceptor,用于习得已确定的决议。以上决议过程都只要求 acceptor 多数派参与,而我们希望尽量所有 acceptor 的状态一致。如果部分 acceptor 因宕机等原因未知晓已确定决议,宕机恢复后可经本机 learner 采用 pull 的方式从其他 acceptor 习得。

Multi Paxos

Basic Paxos 不断地进行“确定一个值”的过程、再为每个过程编上序号,就能得到具有全序关系(total order)的系列值,进而能应用在数据库副本存储等很多场景。我们把单次“确定一个值”的过程称为实例(instance),它由 proposer/acceptor/learner 组成,下图说明了 A/B/C 三机上的实例:

示意图
不同序号的实例之间互相不影响,A/B/C 三机输入相同、过程实质等同于执行相同序列的状态机(state machine)指令 ,因而将得到一致的结果。

proposer leader 在 Multi Paxos 中还有助于提升性能,常态下统一由 leader 发起提议,可节省prepare 步骤(leader 不用问询 acceptor 曾接受过的 ID 最大的提议、只有 leader 提议也不需要acceptor 进行 promise)直至发生 leader 宕机、重新选主。

OceanBase 数据库的 Paxos 协议与选举协议的关系

OceanBase 数据库的 Paxos 实现和选举协议一起构成了一致性协议(日志服务)的实现。两者有一定的相关性,但在实现上又尽量做到减少耦合。

选举协议会首先在多个副本中选出一个 Leader 节点,并通过 Lease 机制保证 Leader 的合法性。日志会基于选出的 Leader 推进 Multi-Paxos 的状态机,做未确认日志的恢复,并在恢复阶段完成后开始提供服务。

如何通过Paxos协议避免脑裂

什么是"脑裂"?

在传统数据库主备同步容灾方案中,系统正常工作时,会存在一个主节点(又称作 Master)对外提供数据读写服务,其余节点作为备节点(又称作 Slave)从主节点以日志的形式同步数据,作为容灾节点备用。

在系统出现异常时,以主节点和备节点之间出现网络分区为例:

  • 主节点和同机房的应用服务器连接正常,仍作为主节点提供数据的读写服务。
  • 作容灾决策的人或自动管控工具,在检查到主节点网络不通的场景下,为了保证服务的连续性,会尝试将备节点提升成主节点提供数据读写服务。
  • 在这种场景下,同时存在两个或多个主节点,应用出现多写,会造成严重的数据正确性问题。这个现象被称作"脑裂"。
如何避免"脑裂"?

Paxos 协议是基于多数派的协议,简单来说,任何决策的达成均需要多数派节点达成一致。

OceanBase 数据库的高可用选举,保证在任一时刻,只有得到多数派的认可,一个节点才能成为主节点提供读写服务。由于集合中任意两个多数派均会存在交集,保证不会同时选举出两个主节点。

在一个节点当选为主节点后,通过租约(又称作 Lease)机制保证服务的连续性。

  • 在少数派的备节点出现故障时,主节点的服务不受任何影响。
  • 在主节点故障或网络分区时,多数派的备节点会首先等待租约过期;在租约过期后,原主节点保证不再提供读写服务,此时 OceanBase 数据库会自动从剩余节点集合中选举一个新的主节点继续提供服务。

OceanBase 数据库的日志同步协议,要求待写入的数据在多数派节点持久化成功。以 OceanBase 数据库典型的同城三机房部署为例,任意事务持久化的日志,均需要同步到至少两个机房,事务才会最终提交。

  • 在少数派的备节点出现故障时,同样,主节点的服务不受任何影响,数据不会丢失。
  • 在主节点故障或网络分区时,余下节点中仍保留有完整的数据;高可用选举会首先选出一个新的主节点,该节点会执行恢复流程,从余下节点中恢复出完整数据,在此之后可以继续提供服务,整个过程是完全自动的。

基于上述分析,OceanBase 数据库通过基于 Paxos 协议实现的高可用选举和日志同步协议,避免了"脑裂",同时保证了数据安全性和服务连续性。

节点故障的自动处理

RootService 高可用

在 OceanBase 集群中,RootService 提供集群的各类管理服务,RootService 服务的高可用使用如下的方式实现:RootService 服务使用 Paxos 协议实现高可用,可以通过集群配置,指定 RootService 服务副本数,RootService 的各副本基于 Paxos 协议选举 leader,leader 副本上任后为集群提供 RootService 服务。当 RootService 的当前 leader 发生故障卸任时,其他的 RootService 副本重新选举产生新的 leader,并继续提供 RootService 服务,依次实现 RootService 的高可用。RootService 的各副本不是一个单独的进程,仅是某些 OBServer 上启动的一个服务。

OBServer 状态监测

作为集群的中控服务,RootService 负责集群的 OBServer 管理,各 OBServer 通过心跳数据包(heartbeat)的方式,定期(每 2s)向 RootService 汇报自己的进程状态,RootService 通过监测 OBServer 的心跳数据包,来获取当前 OBServer 进程的工作状态。

OBServer 心跳状态相关配置项

  • lease_time:当 RootService 累计超过 lease_time 时间没有收到过某 OBServer 的任意心跳数据包时,RootService 认为该 observer进程短暂断线,RootService 会标记该 OBServer 的心跳状态为 lease_expired。
  • server_permanent_offline_time:当 RootService 累计超过 server_permanent_offline_time 时间没有收到过某 OBServer 的任意心跳数据包时,RootService 认为该 observer 进程断线,RootService 会标记该 OBServer 的心跳状态为 permanent_offline。

RootService 对 OBServer 节点故障的处理

RootService 根据心跳数据包可以获得 OBServer 如下的工作状态:

  • OBServer 心跳数据包存在,心跳数据包中的 OBServer 磁盘状态正常。此种状态下,RootService 认为 OBServer 处于正常工作状态。
  • OBServer 心跳数据包存在,心跳数据包中的 OBServer 磁盘状态异常。此种状态下,RootService 认为 observer 的进程还在,但 OBServer 磁盘故障。此种状态下,RootService 会尝试将该 OBServer 上的全部 leader 副本切走。
  • OBServer 心跳数据包不存在,OBServer 心跳数据包的丢失时间还比较短,OBServer 心跳状态为 lease_time,此种状态下,RootService 仅将 OBServer 的工作状态设置为 inactive,不做其他处理。
  • OBServer 心跳数据包不存在,OBServer 心跳数据包丢失时间超过 server_permanent_offline_time,OBServer 的心跳状态为 permanent_offline,此种情况下,RootService 会对该 OBServer 上的数据副本进行处理,将该 OBServer 上包含的数据副本从 Paxos 成员组中删除,并在其他可用 OBServer 上补充数据,已保证数据副本 Paxos 成员组完整。

故障机器的恢复

集群中发生故障的 OBServer 存在两种情况:

  • 故障 OBServer 可以重新启动。这种情况下,不论故障机器之前处于那种心跳状态,重新启动后,OBServer与 RootService 之间的心跳数据包恢复以后,OBServer 可重新提供服务。
  • 故障 OBServer 损坏,无法重新启动。这种情况下,在确认 OBServer 损坏无法重新启动后,需要数据库管理员执行集群管理操作,将该 OBServer 中删除。删除流程可参考 alter system delete server 管理操作。

GTS 高可用

全局时间戳服务(Global Timestamp Service,简称 GTS),OceanBase 数据库内部为每个租户启动一个全局时间戳服务,事务提交时通过本租户的时间戳服务获取事务版本号,保证全局的事务顺序。

GTS 是集群的核心,需要保证高可用。

  • 对于用户租户而言,OceanBase 数据库使用租户级别内部表 __all_dummy 表的 Leader 作为 GTS 服务提供者,时间来源于该 Leader 的本地时钟。GTS 默认是三副本的,其高可用能力跟普通表的能力一样,保证单节点故障场景下 RTO < 30s。

GTS 维护了全局递增的时间戳服务,异常场景下依然能够保证正确性:

  • 有主改选
    原 Leader 主动发起改选的场景,我们称为有主改选。新 leader 上任之前先获取旧 leader 的最大已经授权的时间戳作为新 Leader 时间戳授权的基准值。因此该场景下,GTS 提供的时间戳不会回退。
  • 无主选举
    原 Leader 与多数派成员发生网络隔离,等 Lease 过期之后,原 Follower 会重新选主,这一个过程,我们称为无主选举。选举服务保证了无主选举场景下,新旧 Leader 的 lease 是不重叠的,因此能够保证本地时钟一定大于旧主提供的最大时间戳。因此新 leader 能够保证 GTS 提供的时间戳不回退。

OceanBase 数据库 3.x 及之前的版本 GTS 生成的时间戳并未持久化,依赖于宕机恢复时间 > 最大可能的时钟跳变时间来保证正确性;后续 OceanBase 数据库版本会持久化 GTS 分配的时间戳,解除上述对时钟跳变的依赖。

容灾部署方案

OceanBase 数据库提供多种部署模式,可根据对机房配置以及性能和可用性的需求进行灵活选择。

部署方案容灾能力RTORPO
同机房三副本机器级无损容灾 / 机架级无损容灾30s 内0
同城双机房主备库机房级容灾分钟级大于 0
同城三机房机房级无损容灾30s 内0
两地两中心主备库地域级容灾分钟级大于
三地三中心五副本地域级无损容灾30s内0

为了达到不同级别的容灾能力,OceanBase 数据库提供了两种高可用解决方案:多副本高可用解决方案和主备库高可用解决方案。多副本高可用解决方案基于 Paxos 协议实现,在少数派副本不可用情况下,能够自动恢复服务,并且不丢数据,始终保证 RTO 在 30 秒内,RPO 为 0。主备库高可用解决方案是基于传统的主-备架构来实现的高可用方案,是多副本高可用方案的重要补充,可以满足双机房和双地域场景下的容灾需求;它不能保证数据不丢,RPO 大于 0,RTO 为分钟级别。

多副本

部署三副本或更多副本,来达到机器级无损容灾。当单台 server 或少数派 server 宕机情况下,不影响业务服务,不丢数据。

主备库

任意一个节点不可用时,另一个节点可以接管业务服务。如果备节点不可用,此时数据不受影响,可以持续提供服务;如果主节点不可用,备节点需要激活成新主节点,接管业务服务,由于备节点不能保证同步所有数据,因此可能会丢失数据。

数据保护

数据保护概述

OceanBase 数据库提供了丰富的特性用来保护数据在各种人为或非人为的异常场景下都安全可靠不丢失、不出错。主要包括提供高可用服务的多副本的复制、主备库,以及回收站、闪回和备份恢复等。

硬件异常

当磁盘发生故障的时候,存储在磁盘上的数据可能发生错误。OceanBase 数据库的 redo 日志和 SSTable 中的数据都保存了校验和,读取数据的时候执行严格的校验检查,及时发现错误。磁盘静默错误检测机制还能够发现那些长期不读取的冷数据块中的错误。

当交换机等网络设备发生故障的时候,数据包可能发生错误。无论是客户端与 OceanBase 服务器之间,还是 OceanBase 集群内部的通讯,所有的网络数据包都有严格的数据校验和检查。

人为错误

当数据库对象被用户误删除的时候,可以通过回收站功能,从回收站中恢复误删除的对象。

当应用程序出现软件缺陷的时候,或者发生操作错误或恶意攻击的时候,表内数据被修改为错误数据。使用闪回查询功能,可以读取表数据的历史快照,从而恢复正确的数据。使用 restore point 特性,还可以在一些重大变更之前记录数据快照,以备异常的时候恢复到快照点。

当然,OceanBase 数据库的备份恢复功能提供了高效和丰富的备份所有数据和元数据的机制,它是保护用户数据最可靠的方式。

Restore Point 功能

多版本

OceanBase 数据库是一个多版本的分布式数据库。对于任意一行来说,都有一个 Rowkey 与之对应,行的每个修改称为该行的一个版本。在内存中,行的一个版本用 TransNode 记录,多个版本串成链表,从新到旧连在一起。

以下图为例,行 A 有上有 4 个多版本,版本号分别为:12、11、8、2。

当内存中的数据量积累到一定程度后,我们会通过转储将其转储到磁盘,转储到磁盘的文件称为 SSTable。SSTable 中也保留了数据的多个版本,其中, multi_version_start 指明了该 SSTable 中多版本的起始位点,也即从这个点开始保留了所有数据的多版本信息。base_version 和 snapshot_version 分别指明了 SSTable 中包含数据的事务的提交版本号的左边界和右边界。

Restore Point 保留多版本

Restore Point 指定一个名字,该名字关联到了一个版本号,这个版本号即 Restore Point 创建时的版本号,该版本号对应的数据会被保存起来,以便查询该版本号对应的数据,甚至是将整个数据库回退到该位点。OceanBase 数据库暂不支持将数据回退到 Restore Point,仅支持查询。此外,Restore Point 在 OceanBase 数据库中是租户级别的配置,创建 Restore Point 时,只会保留相应租户的数据。

创建 Restore Point 时,会取当前时间戳作为要保留的版本号,并会等到 GTS 推过后才返回。此时就可以通过 Flashback Query 的语法直接读取多版本数据了。

当 Restore Point 要查询的数据转储成 SSTable 后,后台线程会将这些 SSTable 管理起来,并与 Restore Point 相关联。在 SSTable GC 时,如果发现有 Restore Point 依赖,则不允许将它删除。

注意事项

  • 创建 Restore Point 以后,对创建 Restore Point 之前就存在的表,不允许执行 DDL 语句。
  • Restore Point 依赖全局一致性快照,因此在使用 Restore Point 时,需要开启 GTS。
  • 为了防止 Restore Point 占用过多资源,每个租户限制最多创建 10 个 Restore Point。

备份恢复

备份恢复概述

备份恢复是 OceanBase 数据高可靠的核心组件,通过纯 SQL 的命令就可以使用完整的备份和恢复功能。在 OceanBase 数据库的世界里,数据的高可靠机制主要有多副本的容灾复制、回收站、主备库和备份恢复等,备份恢复是保护用户数据的最后手段。

常见的数据异常问题如下:

  • 单机问题:常见的有磁盘错误、磁盘损坏、机器宕机等场景,这些场景一般通过多副本的容灾复制能力就能恢复正常。
  • 多机问题:常见的是交换机损坏、机房掉电等场景。
    • 少数派副本的问题:OceanBase 数据库的多副本机制能够保证缺少数派副本的时候正常运行,并且故障节点恢复正常后能自动补全数据。
    • 多数派副本的问题:这种场景下多副本机制无法自动的恢复数据,一般来说冷备的恢复时间会比热备的备库恢复耗时长。如果部署有备库,优先建议使用备库切主作为恢复服务的应急措施;如果没有部署备库,建议使用备份恢复来恢复数据。
  • 人为操作:常见的是删表、删库、删行、错误的程序逻辑造成的脏数据等操作
    • 对于一般的误删表、库的操作建议通过回收站的功能恢复数据。
    • 对于行级别的误操作或者更为复杂的程序逻辑错误造成的大规模数据的污染,建议通过备份恢复功能来恢复数据。

OceanBase 数据库的备份按照备份的形式区分,主要分为数据备份和日志备份两种:数据备份是指存储层的基线和转储数据,也就是备份时刻的 Major SSTable + Minor SSTable;日志备份是指事务层生成的 Clog,包含了 SSTable 之后修改的数据。

目前支持集群级别的备份和租户别级的恢复。恢复的时候允许通过白名单机制指定恢复的表或库。

备份恢复的元信息管理

OceanBase 数据库的备份数据主要分为数据备份和日志备份:

  • 单次的数据备份对应一个 backup_set。每次用户运行 alter system backup database 都会生成一个新的 backup_set 的目录,该目录包含了本次备份的所有数据。
  • 日志备份可以由用户指定是否按天切分目录:如果是配置了按天拆分目录,每一天的日志数据目录对应一个 backup_piece;如果没有配置拆分目录,那么整个备份的日志数据目录对应一个 backup_piece。

在 OceanBase 数据库中,备份恢复的元信息是指 backup_set 的信息、backup_piece 的信息和租户信息: * 租户信息:在备份介质上保存在 tenant_name_info 文件中,在源集群上保存在 oceanbase.__all_tenant 和 oceanbase.__all_tenant_history 内部表中。

备份架构

物理备份

OceanBase 数据库提供了在线物理备份的功能,该功能由日志备份+数据备份两大子功能组成。日志备份持续的维护了集群产生的日志,数据备份维护了快照点的备份,两者结合可以提供恢复到备份位点之后任意时间的能力。

日志备份

OceanBase 数据库提供了集群级别的日志备份能力。日志备份是 log entry 级别的物理备份,并且能够支持压缩和加密的能力。

日志备份的工作由 Partition 的 Leader 副本负责。每个 OBServer 负责本机 Leader 副本日志的读取、按照 Partition 拆分、日志聚合后发送的工作。

日志备份的周期默认为 2 分钟,提供了准实时的备份能力。

日志备份提供了按天拆分目录的功能,方便用户对于备份数据的管理。

数据备份

OceanBase 数据库提供了集群级别的数据备份的能力。数据备份目前是基于 restore point 的能力做的数据快照保留,保证了备份期间的数据能够保持全局一致性。数据保留带来了额外的磁盘空间的消耗,如果备份机器的磁盘水位线超过配置的警戒值,会导致数据备份失败。

数据备份的流程都是 RootService 节点调度的,将 1024 个分区作为一组任务发送给 OBServer 备份。备份数据包括分区的元信息和宏块数据。物理备份是指宏块数据的物理备份,元信息是内存序列化后的值。

OceanBase 数据库的基线宏块具有全局唯一的逻辑标识,这个逻辑标识提供了增量备份重用宏块的能力。在 OceanBase 数据库中,一次增量备份指的是全量的元信息的备份+增量的数据宏块的备份。增量备份的恢复和全量备份的恢复流程基本上是一致的,性能上也没有差别,只是会根据逻辑标识在不同的 backupset 之间读取宏块。

数据清理

OceanBase 数据库提供了当前配置路径下自动清理的功能,该功能由 RootService 定期检查用户配置的 Recovery Window,从而删除不需要数据备份。在删除数据备份的同时,会自动的根据保留的数据备份中最小的回放位点来删除不需要的日志备份。

备份的备份

备份的备份是指数据库备份的二次备份能力,通常一次备份为了较好的性能,会存放在性能较好的备份介质上,而这种介质的容量会比较有限,保留备份的时间会比较短;二次备份则是把一次备份的数据挪到空间更大、保留时间更长、成本更低的介质上。

目前 OceanBase 数据库提供了内置的备份的备份的功能,支持用户调度 OBServer 将一次备份的数据搬迁到指定的目录中。 目前支持 OSS 和 NFS 两种介质。

逻辑备份

OceanBase 数据库社区版不提供集群级别的逻辑备份功能,提供了数据的逻辑备份的 OBDUMPER 工具。该工具是 java 开发的一个并行的客户端导出工具,支持 SQL 或者 CSV 格式的数据导出,也支持全局的过滤条件。

恢复架构

恢复概述

OceanBase 数据库提供租户级别的恢复能力,支持微秒级别的恢复精度。

租户恢复保证了跨表、跨分区的全局一致性。

OceanBase 数据库的恢复主要包含下面几步:

  1. 恢复系统表的数据。
  2. 恢复系统表的日志。
  3. 修正系统表的数据。
  4. 恢复用户表的数据。
  5. 恢复用户表的日志。

对于单个分区来说,备份+恢复的流程和重启的流程比较类似,主要就是加载数据和应用日志。

恢复系统表的数据

RootService 根据数据备份的系统表的列表创建对应的分区,然后依次调度分区的 Leader 从备份的介质上拷贝分区的元信息、宏块数据。

恢复系统表的日志

日志恢复和重启后回放日志的流程比较类似,恢复的分区的 Leader 在完成数据恢复后,会主动从备份介质上拉取备份的分区级别的日志并保存到本地的 Clog 目录。Leader 将恢复的日志保存到本地的同时,Clog 回放的线程会同时开始回放数据到 MEMStore。等所有的 Clog 都恢复完成以后,一个分区的恢复就完成了。

修正系统表的数据

系统表恢复完成后,RootService 会进行系统表数据的修复:

  1. 清理未建完的索引表。
  2. 老版本的备份被恢复到新版本的集群上的兼容补偿:
    a. 补建新加的系统表
    b. 补偿跨版本的升级任务

恢复用户表

用户表的数据、日志的恢复流程和系统表类似,唯一的区别是创建分区的列表依赖的数据源不同。恢复用户表的时候,RootService 是从已经恢复的系统表中读取相关列表的。

恢复事务的一致性

OceanBase 数据库的物理备份恢复强依赖租户的 GTS 功能,GTS 保证了备份和恢复的数据是全局一致的。

逻辑恢复

OceanBase 数据库社区版不提供集群级别的逻辑备份恢复功能,提供了数据的逻辑备份的 OBDUMPER 工具和逻辑恢复的 OBLOADER 工具。该工具是 java 开发的客户端导入工具,提供了支持 SQL 或者 CSV 格式的数据导入,也支持导入的限流、断点恢复的能力。


如果想了解更详细的内容,请浏览官方文档

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随处可见的打字员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值