Raft 简介
Raft 作为一种管理日志复制的分布式一致性算法,由斯坦福大学的 Diego Ongaro 和 John Ousterhout 在论文中提出。在 Raft 出现之前,Paxos 一直是分布式一致性算法的标准。但 Paxos 相对难以理解,Raft 的设计目标就是简化 Paxos,使得一致性算法更容易理解和实现。
Paxos 和 Raft 都是分布式一致性算法,其过程如同投票选举领袖(Leader),参选者(Candidate)需要说服大多数投票者(Follower)给他投票,一旦选举出领袖,就由领袖发号施令。Paxos 和 Raft 的区别在于选举的具体过程不同,社区中关于 Raft 算法的详细讲解非常丰富,这里就不再赘述。
KaiwuDB 中的 Raft 算法
KaiwuDB 是分布式数据库,与 OceanBase、CockroachDB、TiDB 一样都是NewSQL 家族的一员。KaiwuDB 具备强一致、高可用的分布式架构,能够水平扩展,提供企业级的安全特性,完全兼容 PostgreSQL 协议,能够为用户提供完整的分布式数据库解决方案。KaiwuDB 的整体架构如图 1 所示:
图1:KaiwuDB 的整体架构
KaiwuDB 各方面的强一致性都通过 Raft 算法实现。首先,Raft 算法保证分布式多副本之间数据强一致性以及外部读写的一致性。简而言之,KaiwuDB 中数据会有多个副本,这些副本存放在不同的机器上,当其中一台机器故障宕机后,数据库依旧能够对外提供服务。此外,KaiwuDB 会根据插入数据的键,将数据划分为多个 Range,每个 Range 上的数据均由一个 Raft Group 来维持多个副本之间数据的一致性。因此,准确地说KaiwuDB 使用的是 Multi-Raft 算法。
具体来说,KaiwuDB 的存储层基于 RocksDB 开发,利用单机的 RocksDB,KaiwuDB 可以将数据快速地存储在磁盘上;在出现单机故障时,利用 Raft 算法可以快速地将数据复制到机器上。在这个过程中,数据的写入是通过 Raft 算法接口实现的,而不是直接写入 RocksDB。通过 Raft 算法,KaiwuDB 变成了一个分布式的键值存储系统,面对不超过集群半数的机器故障情况宕机,完全能够通过 Raft 算法自动把副本补全,做到业务对故障的无感知。
在项目开发前期,KaiwuDB 中的 Raft 算法采用的是开源的 etcd-raft 模块,该模块主要提供如下几点功能:
KaiwuDB 利用 etcd-raft 模块进行数据复制,每条数据操作都最终转化成一条 RaftLog,通过 RaftLog 复制功能,将数据操作安全可靠地同步到 Raft Group 中的每一个节点上。不过在实际操作中,根据 Raft 的协议,只需要同步复制到多数节点,即可安全地认为数据写入成功。
但是在后续的生产实践中,KaiwuDB 研发团队逐渐发现 etcd-raft 的模块仍存在诸多限制,于是陆续开展了如下多个方面的优化工作,具体包括:
下面将着重介绍第一点,即 KaiwuDB 团队根据业务需要为 Raft 模块新增的三种角色。
KaiwuDB 对 Raft 模块的改进
新增 Raft 角色
1、强同步角色
为解决部署在跨地域的多数据中心数据同步问题,达到数据在多地共同写入的效果,实现地域级别的容灾能力,KaiwuDB 研发团队在 etcd-raft 模块中新增了强同步角色。
具体措施如下:
图2 强同步角色的处理逻辑
经过以上四点改造后,etcd-raft 模块新增强同步角色,能够实现如下功能:
2、只读型角色
由于云溪数据库具备 HTAP 的特性,因此需要在 Raft Group 中增加一种相对独立的特殊副本,对外仅提供读服务(例如将该类型副本的存储引擎替换成列存引擎)以实现 OLAP 的功能。为了在 Raft Group 中增加这种特殊副本,同时不影响原有的集群特性,KaiwuDB 研发团队在 Raft 中设计了一种新的只读型角色。
具体实现措施如下:
etcd-raft 模块新增只读型角色后,能够实现如下功能:
3、日志型角色
KaiwuDB 支持在两数据中心三副本部署模式下提供双活模式,无论如何部署副本的位置,总有一个数据中心拥有过半数的副本。当拥有过半数副本的数据中心故障时,另一个数据中心由于所拥有的可用副本数不满足过半数,会导致 KaiwuDB 无法对外正常提供服务。为解决此类问题,提高 KaiwuDB 的容灾能力,同时充分利用和整合资源,避免出现资源闲置造成的浪费现象,提升双活数据中心的服务能力,项目团队在 etcd-raft 模块增加了日志型角色。
具体实现措施如下:
针对日志型角色增加 Logonly 语法支持,使用 Alter 语句配置样例如下,表 t 拥有 3 个副本,其中将 2 个全能型副本放在北京和济南,日志型副本放在天津:
ALTER TABLE t CONFIGURE ZONE USING num_replicas=2, num_logonlys=1, constraints=’{"+region=beijing": 1,"+region=jinan": 1}’, logonly_constraints=’{"+region=tianjin":1}’;
以两中心三副本(一个全能型、一个强同步、一个日志型)模式进行部署为例,全能型副本与强同步副本分别存放在 DC-1 与 DC-2 的高配机器(或多数机器)中,日志型副本存放在 DC-1 或 DC-2 的低配机器(或少量机器)中,日志增量复制到另一个数据中心的低配机器(或少量机器)。若遭遇数据中心级别的故障,在失去两个副本(一个全能型、一个日志型)后,在另一个数据中心手动启动存放日志型副本的节点,该日志型副本含有基于增量复制得到的日志数据。
遭遇数据中心级别的故障时的容灾处理(Node7 的日志型副本需要手动重启)
通过给 Raft 算法增加 3 种新的角色, KaiwuDB 在跨地域集群容灾、支持 OLAP 等方面的能力得到了显著加强。