深入解析 Raft 模块在开务数据库中的优化改造(上)
来源:SegmentFault
时间:2023-01-10 13:01:26 493浏览 收藏
对于一个数据库开发者来说,牢固扎实的基础是十分重要的,golang学习网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《深入解析 Raft 模块在开务数据库中的优化改造(上)》,主要介绍了MySQL、数据库、程序员、devops,希望对大家的知识积累有所帮助,快点收藏起来吧,否则需要时就找不到了!
Raft 简介
Raft 作为一种管理日志复制的分布式一致性算法,由斯坦福大学的 Diego Ongaro 和 John Ousterhout 在论文中提出。在 Raft 出现之前,Paxos 一直是分布式一致性算法的标准。但 Paxos 相对难以理解,Raft 的设计目标就是简化 Paxos,使得一致性算法更容易理解和实现。
Paxos 和 Raft 都是分布式一致性算法,其过程如同投票选举领袖(Leader),参选者(Candidate)需要说服大多数投票者(Follower)给他投票,一旦选举出领袖,就由领袖发号施令。Paxos 和 Raft 的区别在于选举的具体过程不同,社区中关于 Raft 算法的详细讲解非常丰富,这里就不再赘述。
开务数据库中的 Raft 算法
开务数据库(原:云溪数据库)是分布式数据库,与 OceanBase、CockroachDB、TiDB 一样都是NewSQL 家族的一员。开务数据库具备强一致、高可用的分布式架构,能够水平扩展,提供企业级的安全特性,完全兼容 PostgreSQL 协议,能够为用户提供完整的分布式数据库解决方案。开务数据库的整体架构如图 1 所示:
图1:开务数据库的整体架构
开务数据库各方面的强一致性都通过 Raft 算法实现。首先,Raft 算法保证分布式多副本之间数据强一致性以及外部读写的一致性。简而言之,开务数据库中数据会有多个副本,这些副本存放在不同的机器上,当其中一台机器故障宕机后,数据库依旧能够对外提供服务。此外,云溪数据库会根据插入数据的键,将数据划分为多个 Range,每个 Range 上的数据均由一个 Raft Group 来维持多个副本之间数据的一致性。因此,准确地说开务数据库使用的是 Multi-Raft 算法。
具体来说,开务数据库的存储层基于 RocksDB 开发,利用单机的 RocksDB,开务数据库可以将数据快速地存储在磁盘上;在出现单机故障时,利用 Raft 算法可以快速地将数据复制到机器上。在这个过程中,数据的写入是通过 Raft 算法接口实现的,而不是直接写入 RocksDB。通过 Raft 算法,开务数据库变成了一个分布式的键值存储系统,面对不超过集群半数的机器故障情况宕机,完全能够通过 Raft 算法自动把副本补全,做到业务对故障的无感知。
在项目开发前期,开务数据库中的 Raft 算法采用的是开源的 etcd-raft 模块,该模块主要提供如下几点功能:
· Leader 选举;
· 成员变更,可以细分为:增加节点、删除节点、Leader 转移等;
· 日志复制。
开务数据库利用 etcd-raft 模块进行数据复制,每条数据操作都最终转化成一条 RaftLog,通过 RaftLog 复制功能,将数据操作安全可靠地同步到 Raft Group 中的每一个节点上。不过在实际操作中,根据 Raft 的协议,只需要同步复制到多数节点,即可安全地认为数据写入成功。
但是在后续的生产实践中,开务数据库研发团队逐渐发现 etcd-raft 的模块仍存在诸多限制,于是陆续开展了如下多个方面的优化工作,具体包括:
· 新增 Raft 角色
· 新增 Leader 亲和选举
· 混合序列化
· Raft Log 分离与定制存储
· Raft 心跳与数据分离
下面将着重介绍第一点,即开务数据库团队根据业务需要为 Raft 模块新增的三种角色。
开务数据库对 Raft 模块的改进
新增 Raft 角色
1、强同步角色
为解决部署在跨地域的多数据中心数据同步问题,达到数据在多地共同写入的效果,实现地域级别的容灾能力,云溪数据库研发团队在 etcd-raft 模块中新增了强同步角色。
具体措施如下:
为副本增加强同步标识以及配置和取消强同步标识的逻辑。
etcd-raft 模块原有的日志提交策略:Leader 得到超过半数副本(包括 Leader 自身)的投票才能提交 Raft 日志。云溪数据库在原有的过半数提交策略基础上,增加了强同步角色的日志提交策略——日志提交还需要得到所有强同步副本的投票。
为强同步角色设计了如图 2 所示的故障识别与处理机制:通过心跳超时机制识别强同步故障,提交日志时忽略故障的强同步角色,并将故障信息录入数据库日志并告知用户。
为强同步角色的心跳超时 时间增加热更新功能。
图2 强同步角色的处理逻辑
经过以上四点改造后,etcd-raft 模块新增强同步角色,能够实现如下功能:
· 允许用户为指定副本配置或取消强同步角色,不影响强同步角色所在副本的原有特性。例如对全能型副本配置强同步角色后,该副本依然存储 Raft 日志和用户数据,参与投票,参与 Leader 选举,当选为 Leader 可提供读写服务,Follower 时可提供非一致性读。
· 强同步角色的数据与 leader 保持同步。
· 允许用户配置强同步角色的心跳超时 时间。如果强同步角色发生故障,Raft 集群将在该超时 时间后恢复写入功能,故障期间的写入也会在超时 时间后提交。Raft会在识别到强同步角色故障后暂时取消强同步标记,并在该强同步角色故障解决后自动恢复。强同步角色故障和恢复的信息对用户可见。
· 允许用户在 SQL 终端查询强同步角色的配置状态。
2、只读型角色
由于开务数据库具备 HTAP 的特性,因此需要在 Raft Group 中增加一种相对独立的特殊副本,对外仅提供读服务(例如将该类型副本的存储引擎替换成列存引擎)以实现 OLAP 的功能。为了在 Raft Group 中增加这种特殊副本,同时不影响原有的集群特性,开务数据库研发团队在 Raft 中设计了一种新的只读型角色。
具体实现措施如下:
- 增加只读型角色标识,增加只读型角色的创建、删除、重平衡逻辑。
- 增加只读型副本接收到请求后读取数据的逻辑:如果只读型角色的时间戳不小于请求的时间戳,则提供读服务;否则会重试多次,重试达到限制后会将读取超时错误返回到 SQL 终端。
- 为只读型副本的时间戳更新间隔、读取时的最大重试次数等参数增加热更新功能。
etcd-raft 模块新增只读型角色后,能够实现如下功能:
· 允许用户在指定位置创建、删除或移动只读型角色。只读型角色支持基于负载均衡的重平衡功能,移动到压力相对较小的节点。
· 该角色对外仅提供读服务,存储 Raft 日志和用户数据,不参与投票,不参与 Leader 选举,可提供读服务。
· 允许用户配置只读型副本的时间戳更新间隔、读取时的最大重试次数,可以用于对只读型副本的读取性能进行调优。
· 允许用户在 SQL 终端查询只读型角色的配置情况。
3、日志型角色
开务数据库不支持在两数据中心三副本部署模式下提供双活模式,无论如何部署副本的位置,总有一个数据中心拥有过半数的副本。当拥有过半数副本的数据中心故障时,另一个数据中心由于所拥有的可用副本数不满足过半数,会导致开务数据库无法对外正常提供服务。为解决此类问题,提高开务数据库的容灾能力,同时充分利用和整合资源,避免出现资源闲置造成的浪费现象,提升双活数据中心的服务能力,项目团队在 etcd-raft 模块增加了日志型角色。
具体实现措施如下:
- 日志型副本参与 Leader 选举,拥有投票权,并且可以成为 Leader。在普通副本缺少最新日志的故障场景下,为了恢复集群的可用性,需要日志型副本当选为 Leader,并向其他副本追加日志,使得该副本拥有最新的日志。然后发起 Leader 转移,拥有最新日志的副本当选为 Leader 和 Leaseholder,完成集群恢复。
- 日志型副本不能发送快照。由于日志型副本不含用户数据,若发送快照将导致其他副本丢失数据,因此禁止日志型副本发送快照。
- 日志型副本不能成为 LeaseHolder。禁止从日志型副本读取数据,且在日志型副本成为Leader 的情况下,在其他副本拥有最新日志后,将立即转移 Leader 到该副本上。
- 日志型副本保留日志。日志型副本的日志可用于故障恢复,因此延长其日志保留时间。原有的日志清理策略为当可清理的日志 index 数量大于等于 100 或实际大小大于等于 64KB 时,执行日志清理操作。当出现节点宕机时,待清理的日志超过 4MB 执行日志清理操作。日志型副本的日志清理策略为:将日志清理请求按小时打包、延迟处理,默认清理时间值为24,即将日志清理请求延迟24小时处理,达到日志保留的效果。用户可配置清理时间值,可配置范围是[-1, MaxInt],若配置为 -1 则表示不保留日志,按照原来的逻辑执行清理操作。
- 日志型副本异地重启。日志型副本异地重启时会因尝试提交心跳消息携带的 Commit 值而宕机。修改 follower 处理心跳的逻辑,如果日志型 follower 收到心跳消息的 Commit 值比实际的 lastIndex 值大,就将心跳回复消息的 Reject 字段置为 true、RejectHint 字段置为实际的 lastIndex。Leader 收到 Reject 为 true 的心跳回复消息时,将对应 follower 副本 progress 的 Match 和 Next 更新为实际值,并向该副本追加日志,将其丢失的日志补全。
针对日志型角色增加 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 种新的角色,云溪数据库在跨地域集群容灾、支持 OLAP 等方面的能力得到了显著加强。
好了,本文到此结束,带大家了解了《深入解析 Raft 模块在开务数据库中的优化改造(上)》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多数据库知识!
-
499 收藏
-
244 收藏
-
235 收藏
-
157 收藏
-
101 收藏
-
475 收藏
-
266 收藏
-
273 收藏
-
283 收藏
-
210 收藏
-
371 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习
-
- 快乐的萝莉
- 受益颇多,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢大佬分享文章!
- 2023-03-06 09:44:54
-
- 合适的书本
- 这篇文章真及时,大佬加油!
- 2023-02-24 08:51:29
-
- 快乐的宝贝
- 细节满满,已收藏,感谢作者的这篇技术文章,我会继续支持!
- 2023-02-20 09:01:33
-
- 时尚的铅笔
- 这篇文章内容太及时了,太全面了,太给力了,收藏了,关注作者了!希望作者能多写数据库相关的文章。
- 2023-02-04 22:37:45
-
- 畅快的豆芽
- 这篇文章内容真是及时雨啊,太细致了,真优秀,码住,关注大佬了!希望大佬能多写数据库相关的文章。
- 2023-01-19 12:53:08
-
- 饱满的手套
- 很有用,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢up主分享技术文章!
- 2023-01-11 17:33:50