共计 2585 个字符,预计需要花费 7 分钟才能阅读完成。
不知大家是否曾经留意到,在 TDengine 3.0 的官网文档(https://docs.taosdata.com/tao…)中,有了这样一个命令:show transactions。顾名思义,这是“事务”。
在 Database 的语境中,满足 ACID 属性的数据库操作序列即可称为事务,它是数据库的一个不可拆分的工作单元,蕴含着一个数据库操作的序列,这些操作要么全副执行,要么全副不执行。换个角度也能够说,事务是为了实现 ACID 个性的一种工具。
不过在 TDengine 中,依靠于“一个数据采集点一张表”的设计理念,针对表的操作都是以队列形式一一进行的,所以在绝大多数状况下都不须要事务机制。那 TDengine 3.0 中的“事务”是用来解决什么问题的呢?答案就是:3.0 中的事务机制并没有利用在业务数据上,而是针对数据库的元数据的,它的目标是利用事务的 ACID 个性,来强化元数据的一致性,因而,普通用户对此是无感知的,然而对 TDengine 的运维人员而言,意义会更大一些。
大家都晓得 TDengine 3.0 是一款高性能、云原生的分布式时序数据库(Time Series Database),甚至能够反对十亿级别的表数量,因而它的元数据量是非常宏大的。那么如果应用了事务,会不会影响 TDengine 的高性能呢?
这里就须要联合 TDengine 2.x 时代的元数据架构来说起了。
一、2.x 的元数据架构
在 2.x 版本中,治理节点 mnode 中的 sdb 模块存储了大量元数据,如集群信息、用户信息、数据库信息、超级表信息以及一般表信息等。这些不同类型的信息,会在内存中别离以一个 hash 表的模式来保护。其中,一些元数据须要在治理节点(mnode)和数据节点(dnode/vnode)中别离存储,比方超级表、一般表。所以,当对数据库执行 DDL 操作时,须要在 mnode 上对这个 hash 表操作一次,还要再去 dnode 中的 vnode 也做一次。这里为了性能的优化,TDengine 抉择以异步的形式来实现操作。以删表为例,当 mnode 内存中的 hash 表删掉了这个表后,会立刻返回胜利。后续由 dnode/vnode 一侧删除本人的元数据,达成最终统一。
因为该流程的非强一致性,可能会导致在某些极非凡状况下(比方网络不稳固),呈现 mnode 与 vnode 元数据不同步的状况(有的用户遇到过这个错误信息:“Invalid table id”)。然而如果为了强一致性而在 2.x 中引入事务机制,那么对于存在超大规模 DDL 操作的场景来说(如删除一张领有百万千万子表的超级表),这种分布式的事务对数据库的性能损耗又将十分之大。
那么应该如何解决这个问题呢?咱们的思路是:利用“分布式事务”,解决 mnode 和 dnode 同步时的非原子性问题,然而又不能让其影响到数据库的性能。
二、3.0 的事务引入
以此为根据,TDengine 在 3.0 中抉择把开销最大的一般表元数据从 mnode 中移除,齐全只放在各个 vnode 中分布式存储,这样除了避免了上述 mnode 和 vnode 一般表元数据不统一的景象产生,更使得 TDengine 不再具备单点性能瓶颈,解决了业界的“高基数”难题,从而能够反对十亿级别的工夫线。 在其余的元数据模块中,咱们则引入了事务机制,确保了这部分元数据的 ACID 个性。
下图是一个两阶段提交的流程,其中 Coordinator(协调者)就是 mnode,而 Participants(参与者)就是 dnode/vnode。
创立事务后,协调者本地筹备事务所需的必要数据,redo、undo 日志等。而后向参与者们发送事务执行申请,如果参与者们的事务执行后果皆为胜利,那么则进入提交阶段,由协调者提交事务。
须要留神的是:如果作为协调者的 mnode 宕机,那么其余 mnode 在成为 leader 之后,会作为新的协调者持续驱动事务的执行。也就是说,Raft 协定保障了事务的一致性和持久性。
在当初的 3.0 架构中,为了防止不同的事务操作共享资源,治理节点针对不同类型的元数据把事务分成了几个级别,别离为无抵触级别、全局级别、数据库级别以及数据库外部级别。如果在内存中仍有未实现且具备雷同抵触类型的事务,后执行的事务将会期待前者执行结束再执行。
最终,一个事务的运行状态与行为是由该类元数据自身的抵触级别和失败策略等因素决定的,而这所有是对用户无感知的。用户只需晓得事务在执行阶段具备 PREPARE,REDO_ACTION,COMMIT,COMMIT_ACTION,ROLLBACK,UNDO_ACTION,FINISHED 7 个阶段。
其中,比拟要害的中央是:在 PREPARE 阶段,事务的根本信息在不同的 mnode 间达成统一;而后在 REDO_ACTION 阶段,执行 mnode 的本地操作、以及波及的 vnode 的远端操作。当 REDO_ACTION 的所有操作都实现后,进入 COMMIT 阶段。注:REDO_ACTION 不止蕴含了第一次执行工作,还包含执行失败后的重做。COMMIT 阶段则负责把数据最终写入到 SDB 对应的表中,实现长久化。在最初的 FINISHED 阶段,清理 SDB 模块中事务表的相干内存,实现整个工作的执行或者回滚。
通过 show transactions,咱们能够明确理解到以后事务运行的阶段。除了确保数据库的平安统一之外,也给了数据库运维人员更短缺的信息去诊断数据库的以后状态。不过,在绝大多数工夫,show transactions 的输入是没有后果的,因为元数据体量较小,所以执行速度都十分快。
总而言之,TDengine 3.0 的“事务”机制为集群信息、用户信息、数据库信息以及超级表信息等元数据带来了 ACID 的个性保障。
而在它背地的把一般表元数据齐全迁徙到 vnode 的架构变更,使得 TDengine 不再具备单点瓶颈,取得了超强的程度扩大能力,如果想取得更多的数据处理能力,只须要退出更多的数据节点即可。
在下一篇文章中,我会持续和大家分享该变更带来的诸多劣势,一起感触 TDengine 这款开源、高性能、云原生的时序数据库的架构变动之路。
欢送增加小 T(VX:TDengine),退出物联网技术探讨群,第一工夫理解 TDengine 官网信息,与关注前沿技术的同学们独特探讨新技术、新玩法。
想理解更多 TDengine Database 的具体细节,欢送大家在 GitHub 上查看相干源代码。