大家都晓得:因为单机数据库在数据规模、并发访问量等方面存在瓶颈,无奈满足大规模利用的需要。因而才有了把数据切割分片,散布存储散布解决在多个节点上的数据库,也就是分布式数据库的由来。
而为了实现数据库的高可用,又有了多正本的概念,正本之间的数据须要用特定算法保持一致,从而能够随时切换身份对外提供高可用服务——TDengine 就是一款这样的分布式时序数据库(Time Series Database)。
抉择什么样的一致性或者共识算法,能够间接代表一款数据库的产品思路。
一.Why RAFT
在 3.0 之前,联合时序数据的十大特点(《我为何要开发一个专用的物联网大数据平台,还开源它?》),咱们针对性地发明了多项时序数据处理专利,使得 TDengine 对大时序数据的解决能力与过后世界上的同类型产品拉开了微小的性能劣势。而在 3.0,咱们则引入了规范的 RAFT 算法,以更通用规范的实现形式,去实用更宽泛的利用场景。
通过 RAFT 算法所保障数据统一的多个节点,被称为一个 RAFT 组 (group);这些节点,被称为这个 RAFT 组的成员(member)节点。
在 RAFT 组中,每个节点都保护了一份间断的日志(Log),用于记录数据写入、变更、或删除等操作的所有指令。日志是由一系列有序的日志条目 (Log Entry) 组成,每个 Log Entry 都有惟一的编号(Index),用于标识日志协商或执行的进度。
此外,每个 RAFT 节点都有本人的角色,它们能够是 Follower(跟随者)、Candidate(候选人)、Leader(领导者)。
二. Raft in TDengine
对于 TDengine 来说,一个虚构节点组(vgroup)就形成了一个 RAFT 组;而这个虚构节点组的虚构数据节点(vnode),便是该 RAFT 组的成员节点,咱们也称之为正本(全副治理节点(mnode)也形成一个 RAFT 组)。
Leader 角色的 vnode/mnode 依照协定机制负责提供读写服务,在容忍故障节点不超过半数的状况下保障集群的高可用性;此外,即便产生了节点重启及 Leader 节点从新选举等事件后,RAFT 也可能始终保障新产生的 Leader 节点能够提供曾经写入胜利的全副残缺数据的读写服务。
对于 TDengine 来说,每一次对数据库的变更申请(比方 insert into test.d1 values(now,1,2,3)),都对应一个 RAFT 日志记录(Log Entry)。在继续写入数据的过程中,TDengine 会依照协定机制在每个成员节点上产生完全相同的日志记录,并且以雷同的程序执行数据变更操作,以 WAL 的模式,存储在数据文件目录中。
而每一个 Log Entry 携带的 Index,就代表此前讲过的数据或数据变更的版本号(https://mp.weixin.qq.com/s/F-zWYr3FVqhpbfTqzD5PwA)。
当一个数据写入申请收回后,必然至多过半数节点上实现写入才会把“写入胜利”返回给客户端。这部分波及 Log entry 的两种重要的状态,committed 和 applied。
对应到 TDengine 中,只有当过半数的节点把该条 SQL 的写入信息追加到文件系统上的 WAL(即图中的步骤 2),并且收到确认音讯之后,这条 Log entry 才会被 Leader 认为是平安的。此时该日志进入 committed 状态,并告诉 Follower 节点,实现数据的插入(即图中的步骤 4),随后该 Log Entry 便被标记为 applied 的状态。
applied——示意数据变更曾经被利用,即该 SQL 执行结束。
数据的整体写入流程能够参考官网文
档 https://docs.taosdata.com/tdinternal/arch/。如果须要更多理解 RAFT 细节能够参考论文《In Search of an Understandable Consensus Algorithm》
三. 注意事项
对于用户而言,数据的同步形式其实是无需感知的,大家只须要关怀最终后果即可。然而对于选主流程大家有必要理解一些,因为它波及到服务的压力负载是否平衡,以及到遇到突发状况后解决问题的思路。
在 RAFT 的规范实现下,每个节点都领有随机的选举超时工夫(election timeout),当任意一个 Follower 超过这个工夫没有收到 Leader 发来的心跳后,便会变成 Candidate 并发动申请成为 Leader 的选举申请。
可见,每一个 Vgroup 的选举后果都齐全随机的,所以这样会低概率呈现很多 Leader Vnode 集中在某一个节点的场景,比方在集群启动时、滚动降级时(企业版)。因为 RAFT 的读写全副只能由 Leader 节点来提供(2.0 版本 TDengine 的 Follower 也可提供查问服务),因而这会导致单个节点的工作压力较大。
为了优化这种非凡状况,企业版 TDengine 提供了一种简便易用的命令,可能使集群的负载再次实现平衡。
balance vgroup Leader;
开源版则能够通过重启服务从新选主刷新选举后果。(相比 2.0 版本,优化后的 3.0 即使是体量很大的集群也能够迅速启停)
此外,因为 RAFT 的选举流程规定只需失去半数以上节点的投票就能够选出 Leader,所以在 3.0 版本,原则上讲,只须要半数以上节点失常便能够提供服务。(2.0 须要节点全副启动才可从无到有选出 Leader,后续才会依照半数以上的多数派准则提供高可用服务)
四. 常见问题:
问题 1:“Sync leader is unreachable”(3.0.3.1 版本之前,该错误码为 sync not Leader)
该报错的具体逻辑是:因为 RAFT 要求只有 Leader 才能够提供读写服务,一个申请发现自己拜访的 vnode/mnode 不是 Leader 后,会把申请重定向到新的 vnode/mnode 上。如果最终还是没有找到 Leader 才会返回客户端谬误:“Sync leader is unreachable”,所以实质上这个报错是因为 Leader 不存在导致的。
问题景象及解决思路:
数据库 /mnode 在没有设置 3 正本的状况下呈现故障:这时须要关上 debugFlag 143 , 生成高级别日志,通过日志信息判断问题所在,或者查看硬件。
多正本状况无奈选出 Leader:同样须要关上 debugFlag 143 , 生成高级别日志,通过日志信息判断问题所在,或者查看硬件。
数据库主程序呈现 bug 导致程序无奈启动,因而无奈选出 Leader:这种状况须要通过微信群或 github 分割官网团队帮助解决。
除此之外,凡是在日志中发现“not leader”相干字样的报错信息,都能够依照上述思路排查。
常见问题 2 : Sync leader is restoring。
该报错的具体逻辑是:如果数据库节点呈现了断电,或其余起因导致数据库过程异样停止。这样内存中的数便会被清空,数据库须要把曾经写入磁盘的 WAL 数据再次执行,使内存复原到异样产生之前的状态。(上图红色箭头局部)
这个时候,该 vnode 便处于 restoring 的状态,须要完全恢复后才能够失常提供服务,在复原实现之前如果拜访了这个 vnode 数据就会报错“Sync leader is restoring”。
通常咱们不认为这是一个异常情况,而是数据库的失常复原行为,此时咱们能够察看日志中该条输入的“items”,直到归 0 即可恢复正常应用,如果复原较慢,或中途呈现其它问题,通过微信群或 github 分割咱们官网即可。
五. 结语
RAFT 的引入是 3.0 大规模重构中最大的亮点之一,在保住了 TDengine 的性能劣势的前提下,使得 TDengine 能以更规范的形式解决数据的一致性问题。
在存储引擎,一致性协定,查问引擎全副做了大规模重构之后,TDengine 3.0 将会在更宽泛的时序数据处理场景中发挥作用,欢送大家退出咱们一起摸索可能。