【是否原创】是
【首发渠道】TiDB 社区
一、用户手册
专栏 - DR Auto-Sync 搭建和计划内切换操作手册 | TiDB 社区
专栏 - DR Auto-Sync 搭建和灾难恢复手册 | TiDB 社区
专栏 - DR Auto-Sync 的 ACID 恢复功能简介和长期断网应急处理方案 | TiDB 社区
二、原生 Raft 的限制
- Raft
Raft 是一种分布式共识算法,在 TiDB 集群的多种组件中,PD 和 TiKV 都通过 Raft 实现了数据的容灾。Raft 的灾难恢复能力通过如下机制实现:
- Raft 成员的本质是日志复制和状态机。Raft 成员之间通过复制日志来实现数据同步;Raft 成员在不同条件下切换自己的成员状态,其目标是选出 leader 以提供对外服务。
- Raft 是一个表决系统,它遵循多数派协议,在一个 Raft Group 中,某成员获得大多数投票,它的成员状态就会转变为 leader。也就是说,当一个 Raft Group 还保有大多数节点(majority)时,它就能够选出 leader 以提供对外服务。
- 副本数目的选择
Raft 算法本身并没有限制一个 Raft 组的成员(即副本)的数目,这个成员数可以为任意正整数,当成员数为 n 的时候,一个 Raft 组的可靠性如下:
- 若 n 为奇数,该 Raft 组可以容忍 (n-1)/2 个成员同时发生故障
- 若 n 为偶数,该 Raft 组可以容忍 n/2 -1 个成员同时发生故障
在一般情况下,通常将 Raft 组的成员数设置为奇数,其原因如下:
- 避免造成存储空间的浪费:三成员可以容忍 1 成员故障,增加 1 个成员变为 4 成员后,也只能容忍 1 成员故障,容灾能力维持不变。
- 当成员数为偶数时,如果发生了一个网络隔离,刚好将隔离开的两侧的成员数划分为两个 n/2 成员的话,由于两侧都得不到大多数成员,因此都无法选出领袖提供服务,这个网络隔离将直接导致整体的服务不可用。
- 当成员数为奇数时,如果发生了一个网络隔离,网络隔离的两侧中总有一侧能分到大多数的成员,可以选出领袖继续提供服务。
- 原生 Raft 的限制
遵循 Raft 可靠性的特点,放到现实场景中:
- 想克服任意 1 台服务器的故障,应至少提供 3 台服务器。
- 想克服任意 1 个机柜的故障,应至少提供 3 个机柜。
- 想克服任意 1 个数据中心(机房)的故障,应至少提供 3 个数据中心。
- 想应对任意 1 个城市的灾难场景,应至少规划 3 个城市用于部署。
可见,原生的 Raft 协议对于偶数可用区(AZ,Available Zone)的支持并不友好,3 可用区或许是最适合部署 Raft 的高可用及容灾方案。而在现实情况中,大多数部署环境很少具备同城 3 可用区的条件。比如数字化程度非常高的银行业,基于传统单机系统点对点复制的特性,绝大多数银行都只建设了同城 2 可用区,两地 3 可用区的基础设施。
在同城双可用区部署原生的 Raft,主、备可用区按 2:1 的比例来分配 3 个成员,由于网络延迟的差异,灾备可用区会存在异步复制的成员。当主可用区由于故障无法恢复时,灾备可用区仅剩的 1 个成员是无法保障 CAP 中的一致性的。
我们对 Raft 做了一些功能上的扩展,基于这个扩展它可以在一定程度上克服主可用区故障后使用灾备可用区难以恢复一致性数据的难题。
三、DR Auto-Sync 方案
DR(Disaster Recovery),代指同城容灾数据中心,该方案用于应对上文所描述的 TiDB 同城双中心部署,或同城双中心+1个投票中心部署的需求。
DR Auto-Sync 是一种跨同城(网络延迟<1.5ms)两中心部署的单一集群方案,即两种数据中心只部署一个 TiDB 集群,两中心间的数据同步通过集群自身内部(Raft 协议)完成。两中心可同时对外进行读写服务,任意中心发生故障不影响数据一致性。
为了解决 Raft 天生对于双中心支持的不友好,我们对 TiKV 中的 Raft 以及 PD 的调度能力都做出了大幅加强。
图 1
如图所示,为了获得网络发生隔离后的自动恢复能力,本方案采用奇数副本进行部署,这里以 3 副本进行举例,TiKV 和 PD 的 3 个副本都按照主备机房 2:1 的比例进行资源分配,而 TiDB 可以在两中心部署任意多个来获得两中心双活的能力。
从图中可以看到,本方案与原生 Raft 方案不同的是,TiKV 上增加了 Primary/DR 的位置属性,用来让 PD 感知到各个 TiKV 所在的机房信息。同时对 TiKV 中的 Raft 做出了加强,使其根据 PD 下发的同步状态要求,自动的在同步复制和异步复制之间转换。
使用之前,请确保已对做了妥善的 TiKV Label 规划。关于 Label 的设计,请参考以下的文章:
TiDB 集群的可用性详解及 TiKV Label 规划 - 技术文章 / 原理解读 - AskTUG
- 同步状态
我们定义了三种状态来控制和标示集群的同步状态,该状态约束了 TiKV 的复制方式:
- sync:同步复制,此时 DR 与 Primary 至少有一个节点与 Primary 同步,Raft 保证每条 log 按 label 同步复制到 DR
- async:异步复制,此时不保证 DR 与 Primary 完全同步,Raft 使用经典的 majority 方式复制 log
- sync-recover:恢复同步,此时不保证 DR 与 Primary 完全同步,Raft 逐步切换成 label 复制,切换成功后汇报给 PD
- 状态转换
简单来讲,集群的复制模式可以自动在三种状态之间自适应的切换:
- 当集群一切正常时,会进入同步复制模式来最大化的保障灾备机房的数据完整性
- 当机房间网络断连或灾备机房发生整体故障时,在经过一段提前设置好的保护窗口之后,集群会进入异步复制状态,来保障业务的可用性
- 当网络重连或灾备机房整体恢复之后,灾备机房的 TiKV 会重新加入到集群,逐步同步数据并最终转为同步复制模式
- 当主机房整体故障且无法恢复时,使用灾备机房的副本来恢复一致性的数据。
状态转换的细节过程如下:
初始化
集群在第一次启动时是 sync 状态,PD 会下发信息给 TiKV,所有 TiKV 会严格按照 sync 模式的要求进行工作。
同步切异步
- PD 通过定时检查 TiKV 的心跳信息来判断 TiKV 是否宕机 / 断连
- 如果宕机数超过 Primary/DR 各自副本的数量,意味着无法完成同步复制了,需要切换状态
- PD 将 async 状态下发到所有 TiKV
- TiKV 的复制方式由双中心同步方式转为原生的 Raft 大多数落实方式。
异步切同步
- PD 通过定时检查 TiKV 的心跳信息来判断 TiKV 是否恢复连接
- 如果宕机数小于 Primary/DR 各自副本的数量,意味着可以切回同步了
- PD 将 sync-recover 状态下发给所有 TiKV
- TiKV 的所有 region 逐步切换成双机房同步复制模式,切换成功后状态通过心跳同步信息给 PD
- PD 记录 TiKV 上 region 的状态并统计恢复进度
- A) 所有 Regoin 都恢复后,PD 将状态切换为 sync,将 sync 状态下发给所有 TiKV
B) 如果在过程中又发生宕机,执行同步切异步流程
PD 在整个过程中扮演了极为重要的角色,在双中心同步复制方案中几乎所有的配置都在 PD 中完成,包括 Label 设置,Primary/DR 角色配置,阻塞窗口 wait-store-timeout 的配置等。为了有效的在分布式系统中表示当前的同步状态,PD 在向 TiKV 下发状态的同时会绕过原生的 Raft 通过一个新的接口将当前的复制模式同步的写入所有的 PD 磁盘中,这是为了当 PD leader 出现宕机时,用户可以准确的获取当前的复制模式。
3. RPO & RTO
RPO=0
排除同步转异步,降级以提供服务之后继而发生主机房整体故障的情况。
RTO 在不同的场景下的计算方法:
- 两机房网络断开时长小于 wait-store-timeout 所设置的时间时,RTO 为网络断开时间和 30s(基于默认的 Raft 心跳设置)中更大的那个。
- 两机房网络断开或灾备机房整体宕机时,RTO 为阻塞窗口 wait-store-timeout 所设置的时间。
- 主机房整体宕机时,RTO 为报警响应时间 + 重建 PD 操作时间(熟练 DBA 分钟级) + 恢复 TiKV 单副本时间(熟练 DBA 分钟级)+ 集群验证时间(用于验证数据库可用,应用连接顺畅),恢复后的单副本集群可以直接提供服务,后续的扩容以及扩副本操作可以在线执行。
4. 产品限制(5.2.x)
- 同城灾备中心故障触发 TiDB 进入保护窗口 (默认配置 60s),保护窗口内会禁止用户请求。保护窗口结束之后由双中心由同步复制转为异步复制,主中心抛弃灾备中心独立运转。
- 主中心进入异步复制状态后集群总计算能力下降,集群存储容量不变,容灾能力由可容忍一副本故障变为不能容忍副本故障。
- 主中心进入异步复制状态之后,集群不会主动补全副本到 3 副本状态,如果用户需要补全到三副本集群,需要解除 DR Auto-sync 的相关配置,这样做的代价是当灾备中心恢复连接后,需要重新配置为 DR Auto-sync 调度策略。
- 在主中心故障的场景中,需要通过状态标记文件确认灾备中心的副本处于同步复制状态还是异步复制状态。只有同步复制状态下的灾备副本才能恢复一致性的数据。
- 该方案无法应对接连发生的灾难场景,如:
双中心之间网络断开时间超过保护窗口(默认配置 60s),即主中心副本进入异步复制状态,继而发生了主中心故障引起主中心数据副本丢失或损坏。在这种场景下,无法依赖灾备中心的副本进行数据恢复。 - 当主中心故障后,使用灾备中心的少数副本重建集群,此时的集群并不是 DR Auto-Sync 架构,而是一个 n 副本的应急集群(副本数 n 取决于起初分配给灾备中心的副本数)。待恢复服务后,需要补充服务器资源,以在线扩容的方式恢复到初始的副本数量。该操作不可逆,即使主中心后续被修复,也只能以空白服务器的角色加入集群,通过在线重平衡等操作最终恢复到原本的 DR Auto-Sync 架构
5. 产品演进计划
DR Auto-Sync 正处在高速迭代的周期中,后续版本将会有一系列高可用和容灾能力的加强。如下图,从 5.3.0 开始将支持双中心对等部署,藉此获得快速恢复多副本的能力:
图 2
四、原理解读
为了解决分布式共识算法天生在双可用区(AZ)部署时容灾能力的缺陷,我们对分布式共识算法做了加强。
为了获得发生网络隔离故障后的自动恢复能力,需要选用奇数个成员,我们以双可用区部署 7 成员的 Raft 为例来说明这个技术方案。
图 3
如图 1 所示,一般的共识算法通过大多数成员(majority)来实现唯一修改提交并且容忍少数副本(minority)丢失。但是在跨双可用区的情况下,奇数成员的 majority 不一定能容忍可用区损坏。
核心技术 1 —— commit group
与原生 Raft 不同,我们给 Raft 成员增加了提交组(commit group)的概念。每个成员会分配在最多一个组(group)里。在进行日志提交时,除了要满足多数派的前提,还需要满足日志复制到至少两个不同的组里。多数派的前提保证了正确性;至少两个不同组保证了数据的安全。
提交组是可以运行时动态开关的。当要进行同步复制时,开启提交组,保证数据安全;当要切换成异步复制时,关闭提交组,保证可用性。而提交组的划分与 Raft 解偶,由上层指定。在本方案里,划分方式根据地理位置属性决定。
图 4
如图 2 所示,0、1、2、5 可以凑成大多数成员(majority),但是一旦 AZ 0 整个可用区损坏以后,最新的修改也将丢失。提交组将成员按照一定的规则给组织起来,分成不同的组。并且规定修改必须满足大多数成员落实,且复制到至少两个组才能提交。在这种情况下,上述 0、1、2、5 就不是一个符合要求的成员组合。虽然这个组合能满足大多数成员落实,但这个组合只包含了一个组 AZ 0。
图 5
如图 3 所示,图中的 0、1、2、6 就是一个合格的组合。它一共包含 4 个成员,满足了大多数成员落实的要求;这四个成员分布在两个不同的组 AZ 0、AZ 1 中,因此它是一个符合要求的组合。
核心技术 2 —— 保障同步复制的请求阻塞窗口
阻塞窗口用于在发生双可用区通信故障时,在一个预先设置的时间内,通过阻塞新请求的提交来保持双可用区同步复制模式。
- 当阻塞窗口设置为 0 时,两个可用区将保持在异步复制状态。
- 当阻塞窗口设置为 1 分钟时,网络断连或灾备可用区发生整体故障的最初 1 分钟内,主可用区会自动阻塞新的请求,来保障双可用区复制的同步性。
- 当阻塞窗口设置为一个足够大的时间时(如 1 年),网络断连或灾备可用区发生整体故障的 1 年内,都会阻塞新的请求,在实际使用中可以认为双可用区处于持久的同步复制状态。
核心技术 3 —— 自适应复制状态切换
图 6
如图 4 所示,双可用区部署的 Raft 基于这个状态机设计在同步复制和异步复制之间完成自动转换。
- 同步状态说明
我们定义了三种状态来控制和标示集群的同步状态,该状态约束了 TiKV 的复制方式:
- 同步复制状态:即图中“双可用区同步模式”,此时 Raft 在提交组(commit group)模式下工作,以确保灾备可用区具备同步(RPO=0)的数据;
- 异步复制状态:即图中“大多数成员模式”,此时采用经典的 Raft 大多数成员(majority )模式做复制,不保证灾备可用区具备同步的数据;
- 恢复同步状态:即图中“恢复同步模式”,此时逐步追平数据,追数过程中不保证灾备可用区具备同步的数据。
- 状态转换说明
复制模式可以自动在三种状态之间自适应的切换:
- 当集群一切正常时,会转换为同步复制状态来最大化保障灾备可用区的数据完整性;
- 当两个可用区间的网络断连或灾备可用区发生整体故障时,在经过一段提前设置好的阻塞窗口之后,集群会进入异步复制状态,来保障业务的可用性
- 当网络重连或灾备可用区整体恢复之后,灾备可用区的成员会重新加入到集群,逐步同步数据并最终转为同步复制模式;
- 当主可用区整体故障且无法恢复时,使用灾备可用区的成员来恢复一致性的数据。