宣布InfluxDB IOx - 使用Rust和Arrow构建的InfluxDB未来核心
作者:Paul Dix / 产品,用例,开发者
2020年11月10日
导航到
2013年11月12日,我发表了关于InfluxDB的第一场公开演讲,题目为:“InfluxDB,一个开源分布式时间序列数据库”。在那次演讲中,我介绍了InfluxDB,并阐述了关于时间序列的含义:具体来说,任何你可能随着时间提出问题的数据。例如,我展示了指标(人们通常在谈论时间序列时想到的就是指标),以及金融市场数据、用户分析数据、日志数据、事件,甚至是Twitter时间线。更广泛地说,我声称“所有进行数据分析的数据都是时间序列数据”。这意味着,每次进行数据分析时,要么是在时间上,要么是在时间的快照中进行。
在这篇文章中,我将阐述InfluxDB的未来愿景,并介绍一个将构成其基础的新项目:InfluxDB IOx(发音为“eye-ox”,代表氧化铁)。正如文章的标题所说,这个新项目是用Rust(氧化铁,顺理成章)编写的,核心是Apache Arrow。在深入探讨这个项目和其底层技术之前,我想先看看InfluxDB最初的目的是什么,以及自从它七年前问世以来发生了哪些变化。
但在那之前,这里有一些关于标题你可能有的疑问的答案
- InfluxDB 2.x开源版本将继续与常规点发布并行前进。
- InfluxDB IOx将支持SQL(原生)、InfluxQL和Flux(通过2.0和与独立守护进程的API)。
- InfluxDB IOx将成为InfluxDB未来某个点发布中可选的存储后端。
- InfluxDB云客户将在明年年初将InfluxDB IOx作为新桶的可选后端。
- InfluxDB云客户将在2021年某个时候实现无缝、零停机时间的过渡到这项新技术。
- InfluxDB企业客户将在2021年下半年获得InfluxDB IOx和InfluxDB企业商业支持版本。
- InfluxDB IOx将有它自己的构建版本,并且可以独立于平台的其他部分运行。
我最初对InfluxDB的愿景是,它将被用于各种分析任务,无论是实时还是大规模。它将用于服务器和应用程序性能监控、传感器数据应用程序和其他分析应用程序。基本的洞察是,时间序列是构建这些领域应用程序的有用的抽象,InfluxDB将形成这些应用程序的核心基础设施。
现在的InfluxDB是一个非常好的用于指标用例的数据库。它也适用于分析,前提是你没有数据具有显著的基数。也就是说,你定义的标签没有太多独特的值。随着Flux作为轻量级查询和脚本语言的加入,你现在可以在数据库内进行复杂分析,甚至可以在查询时与第三方API和数据库进行交互。
随着用户在数据库中做更多的事情,基数限制的问题越来越频繁地成为一个障碍。例如,我们希望能够存储和处理分布式跟踪数据,但这类用例超出了当前底层InfluxDB架构的范围。我们还想欢迎更广泛的用户群体,他们可能更喜欢在SQL和其他脚本语言中工作。
在分布式方面,目前开源版本的InfluxDB并不是一个分布式数据库,也没有为用户提供创建分布式操作环境的工具。我们将这一功能留给了我们的云和企业产品中的商业版。从开源项目的角度来看,这是当时一个不幸但必要的限制,因为我们需要建立一个企业来支持我们所做的一切开源工作。
自InfluxDB推出以来的七年里,我们看到了许多其他时间序列数据库被引入到开源和闭源领域中。我们也看到了基础设施软件领域的重大变化,Kubernetes的崛起,Hadoop的衰落,以及基于更通用对象存储的更灵活软件计算堆栈的兴起。
InfluxDB下一版本的需求
在更广泛的生态系统中的所有这些变化以及用户需求的不断增加,我们深思熟虑了InfluxDB应该走向何方,并确定了一系列更高层次的需求来努力实现。
- 没有基数限制。写入任何类型的事件数据,无需担心标签或字段。
- 在分析查询方面,除了我们已很好服务的指标查询之外,实现业界最佳性能。
- 将计算与存储分离,分层数据存储。数据库应使用更便宜的对象存储作为其长期耐用的存储。
- 对内存使用的操作员控制。操作员应能够定义用于缓冲、缓存和查询处理的内存使用量。
- 操作员控制的复制。操作员应能够为每台服务器设置细粒度的复制规则。
- 操作员控制的分区。操作员应能够定义数据如何在多台服务器以及每台服务器之间分割。
- 对拓扑结构的操作员控制,包括拆分和解除写入缓冲、订阅、查询处理以及长期存储的排序和索引服务器任务的能力。
- 设计为在短暂的容器化环境中运行。也就是说,它应该能够在没有任何本地附加存储的情况下运行。
- 批量数据导入和导出。
- 对部分或全部数据进行细粒度订阅。
- 更广泛的生态系统兼容性。在可能的情况下,我们应该旨在使用和拥抱数据和分析生态系统中的新兴标准。
- 在边缘和数据中心运行。设计为联邦化。
- 用于进程内计算的嵌入式脚本。
这是一个相当广泛的需求集合。此外,目前像复制和分区这样的需求不属于我们的开源范围。尝试实现这些需求有很多影响。我想首先谈论的是许可问题。
为什么MIT & Apache 2许可证很重要
我们在InfluxData生产的开源软件是按照宽松的MIT许可证授权的。我们一直认为我们的开源代码应该是真正开放的,而我们的商业代码应该是分开和封闭的。正如我之前提到的,我们保留了对商业产品的高可用性和集群功能。鉴于我们的新需求强调了复制、数据分区和其他分布式方面,我们不得不再次审视这个决定。
我们最初创建InfluxDB的原因之一是我们看到许多开发者和组织在分布式时间序列数据库方面重复造轮子。我们当时,现在也是这样认为,时间序列是一个特定的用例,它受益于专门为此设计的系统。
这是我在Cassandra、Redis和其他系统之上构建时间序列API时的经验。我最终不得不编写大量应用层代码来启用所需的功能。我认为InfluxDB可以成为那种共享基础设施。
然而,由于核心开源项目中没有分布式功能,这在市场上留下了很大的空白。过去几年中出现了许多时间序列数据库的事实证明了这一点。如果我们想让InfluxDB成为需要大规模处理和操作时间序列的项目的基石,我们需要找到一种方法,开源更多,而不是更少。
此外,这项工作必须采用真正的开放源代码许可,具有许可性。如果大型公司无法采用它,它们将不得不自己发明。如果其他公司不能基于它建立业务并向用户公开其API,它们将不得不自己建立。如果云服务提供商不托管它,它们将不得不创建自己的版本,这些版本可能不兼容,可能不是基于开放API构建的。
在源可用或受限制的许可下许可的基础设施项目,其本质上是进化的死胡同。只有有限的用户可以采用该软件,而实际上可以在此基础上构建产品的用户群更小。他们通常可以使用受限制的许可项目进行内部用途,但通常不能用于面向外部客户的用途。这些限制意味着许多开发者别无选择,只能从头开始构建或从其他真正开源的项目构建。
我理解为什么公司选择走这条路,但这限制了它们。这也令人遗憾,因为其中许多公司最初是从一个开源的核心构建的。社区和开源并不是关于您的公司能够捕获多少价值。开源是关于在软件中创造一次 Cambrian 大爆发,创造的价值远远超过单个供应商能够货币化的价值。开源不是零和游戏。更大的社区和生态系统为所有供应商带来更多机会。
我们有一个愿景,即InfluxDB将成为无数分析、传感器、监控和数据分析项目和公司的基石。实现这一目标的唯一途径是从一个可扩展的起点出发,任何人都可采纳和商业化。
为了实现这一更大的目标,InfluxDB IOx将以MIT & Apache 2双重许可,没有任何限制。
尽管如此,InfluxDB IOx被设计为作为一个松散联邦的无共享架构运行。操作员应完全控制单个服务器的行为。这也意味着任何涉及多个服务器的生产场景可能需要额外的软件进行操作。
在最基本的场景中,这可能是简单的shell脚本和cron作业。在更复杂的环境中,涉及临时环境和许多服务器,这可能是复杂软件。这个操作工具是我们商业产品的地方。这首先在我们的云产品中出现,稍后作为InfluxDB企业的一部分提供本地化产品。
在系统设计方面,我们不仅考虑了架构应该如何工作,还考虑了商业化的工作方式。我们希望我们的云产品运行与开源项目完全相同的位,而不是一个分支。我们希望本地化商业产品与开源产品互补,而不是替代。
康威定律指出,你发布的组织结构图。迪克斯的名言说,无论是有意还是无意,你的许可策略就是你的商业化策略。在InfluxDB IOx中,我们的目标是拥有许可宽松的开源软件,使其对项目目标最大化有用,并与开源软件互补的商业软件。
为什么InfluxDB IOx是一个新的项目
有几个要求使得这项工作成为我们无法逐步构建的目标。在一个理想的世界里,你可以重构并逐步构建现有的代码库,以达到你想要的目标。这对于进化改进来说很棒,但对于重大飞跃来说却很困难。
满足InfluxDB当前构建方式的难点之一是无限制的基数。以下是InfluxDB中数据组织的样子。数据通过我们的行协议发送,看起来是这样的
cpu,host=serverA,region=west user=23.2,system=53.2 1604944036000000000
这是cpu测量的数据,带有host和region标签,以及user和system两个字段和一个尾随纳秒纪元时间戳。InfluxDB摄取这些数据,并通过以下方式索引它们
测量,标签键/值对,字段名称
这是一个个体时间序列,其中有一个按时间顺序排列的值、时间对列表。此外,测量名称、标签键和值以及字段名称在倒排索引中索引。因此,InfluxDB的核心实际上是两个数据库:倒排索引和时间序列运行。这使得通过测量名称查找时间序列或通过标签维度过滤它们变得非常快。
然而,这意味着任何新的标签值都会创建一个新的系列,必须在倒排索引中索引。随着时间的推移,这意味着你的基数越高,你的倒排索引就越大。在分布式跟踪等病态情况下,每一行都有唯一的ID。这意味着你的二级索引将比底层时间序列数据本身更大。你还花费了大量的CPU周期和内存来持续索引。
这些用例的一个解决方案是将这些数据放入字段中。然而,这导致用户必须考虑标签与字段之间的区别,并在某些情况下限制了他们在查询时间可以做的事情,因为字段在没有任何方式被索引。
如果我们想要处理无限制的基数,倒排索引和时间序列的分割结构需要改变。然而,这种结构是数据库设计的核心。
严格的内存控制要求也使得重构变得困难。这意味着我们无法使用MMAP,这是当前InfluxDB中所有数据和索引文件使用的方法。MMAP是一个很好的工具,许多现代数据库都是用它构建的。然而,在容器化环境中,它与我们的本地附加磁盘运行要求不太匹配。
最后,使用对象存储作为持久性层和大量数据导入/导出要求与底层存储引擎难以实现。该设计基本假设使用本地附加的SSD,并且不利于将一些文件导出到对象存储,并在查询时再导入它们。使用我们分割的索引和时间序列数据库结构,实现大量数据导入/导出是困难的。
这些底层变化共同创造了一个情况,即我们无法逐步推进InfluxDB的核心。我们需要彻底重新思考数据库核心的组织方式。
押注Rust、Apache Arrow和列式数据库
一旦我们意识到需要重新构建核心的一部分,我们就开始思考可以使用哪些工具来使这项工作更快、更可靠、更具有社区导向。我长期以来一直是Rust作为系统语言的粉丝,它虽然难以学习且令人沮丧,但也是近年来软件开发中最激动人心的东西之一。[Rust](https://influxdb.org.cn/blog/rust-can-be-difficult-to-learn-and-frustrating-but-its-also-the-most-exciting-thing-in-software-development-in-a-long-time/) 和 Apache Arrow作为内存分析工具集。[Apache Arrow](https://influxdb.org.cn/blog/apache-arrow-parquet-flight-and-their-ecosystem-are-a-game-changer-for-olap/) 也让我印象深刻。我认为这两个是系统软件、OLAP和数据分析的长期未来。它们在过去几年里都取得了巨大的进步。
Rust让我们对运行时行为和内存管理有了更精细的控制。作为额外的好处,它使并发编程变得更容易,并消除了数据竞争。它的打包系统Crates.io非常出色,包含你需要的所有东西。去年秋天添加了async/await后,我认为是时候认真考虑它了。
Apache Arrow定义了一个用于列式数据的内存格式,以及持久化格式Parquet和客户端/服务器框架和协议Flight,用于“[高性能传输大数据集](https://arrow.apache.ac.cn/blog/2019/10/13/introducing-arrow-flight/)”。额外的好处是,在Apache Arrow工具集中有一个Rust原生SQL查询引擎DataFusion。鉴于我们使用DataFusion作为核心,这意味着InfluxDB IOx将支持SQL的子集,并随着DataFusion项目的发展而扩展功能,无论是在InfluxDB IOx中还是在InfluxData之外的合作者的开发努力中。然而,InfluxDB IOx也支持InfluxQL和Flux。我们再次认真考虑了向后兼容性。
这个架构的最后一部分是数据库的结构。我们的赌注是,一个针对时间序列优化的列式数据库可以用作未来InfluxDB的基础。这是Apache Arrow和DataFusion的结构,与我们更广泛的生态系统兼容的目标相吻合。以下是我们将InfluxDB的数据模型映射到列式数据库模型的方法:
- 度量成为表(即每个度量都是一个表)
- 标签和字段成为这些表中的列(因此它们由度量范围限定)
- 标签键和字段键必须在度量内唯一
- 时间是列
除了这种组织方案之外,我们还选择了Parquet作为长期持久化格式。每个Parquet文件包含单个表的一些数据,这意味着每个文件包含单个度量的数据。通过我们的研究,我们发现我们可以使用Parquet作为持久化格式,在现实世界数据上实现与我们的TSM引擎相当甚至更好的压缩。
此外,我们将所有数据划分为分区。数据如何划分为分区由操作员或用户在创建数据库时定义。最常用的分区方案将简单地基于时间(例如:每2小时一次)。
对于每个分区,我们保留一个包含其内容的摘要,这些摘要可以保存在内存中。这个摘要包括哪些表存在、它们的列是什么,以及这些列的最小值和最大值是什么。这意味着查询规划器可以在执行前通过查看分区元数据来排除数据集的大部分。
这种分区方案也使我们更容易将对象存储作为长期存储,并从内存到对象存储再到索引Parquet文件管理数据生命周期。
列式数据库并不新鲜,那么我们为什么要构建另一个呢?我们无法在开源中找到针对时间序列优化的一个。在查询方面,我们需要字典支持和窗口聚合是第一类和优化的。在持久化方面,我们需要旨在分离计算和存储的东西。
本项目中没有特别革命性的东西。在过去几十年中,列式数据库已经得到了广泛的研究。将计算与存储通过对象存储分离,是近十年来逐渐兴起的一种做法。《Snowflake》代表了封闭源代码领域中的一个更加明显的近期例子。
我们认为这些工具的组合和构成,以Apache Arrow作为开源服务器项目中的核心,代表了开源世界中的一个新而有趣的提供。我们认为这将是未来实时和大规模分析及监控项目的一个构建块。
我们已经在Rust和Go语言中为Arrow做出了贡献。这强化了我们对此的承诺。然而,我们的一些需求超出了Apache Arrow的目标。例如,我们需要一个能够将压缩数据保持在内存中并对其执行查询的系统。为此,我们正在为DataFusion创建扩展,使InfluxDB IOx能够处理比我们通常能处理更多的内存中的时间序列数据。
项目状态
该项目仍处于非常早期的阶段。我们目前没有生产构建版本,除了InfluxDB IOx项目的README之外,没有其他文档。团队是由一些经验丰富的工程师组成的小而专注的团队,我们的努力与我们的大型工程组织在平台其他部分的努力并行。我们的目标是明年早些时候推出开源构建版本,并在InfluxDB Cloud中提供alpha版本。
我们现在讨论这个话题,是因为我们认为让社区了解我们的方向是很重要的。我们还希望打开这个项目,让对它感兴趣的其他人可以跟随并甚至做出贡献。
InfluxDB开源用户的旅程
对于开源InfluxDB 2.0用户来说,这没有立即的影响。这项工作仍然非常早期,可能还需要一段时间才能准备好投入生产使用。您可以期待未来的InfluxDB 2.x版本能够使用InfluxDB IOx作为可选的存储和查询后端。
InfluxDB 2.x线的开发将在InfluxDB IOx开发和之后继续进行。这不会对API造成破坏性变化。然而,2.x API中将逐步推出额外的功能,将在可用时供社区使用。InfluxDB IOx的开发和采用周期应该是渐进的,而不是像1.x到2.0版本周期那样一次性完成。
InfluxDB客户的旅程
对于我们的InfluxDB Cloud客户来说,他们将在明年上半年的某个时候有一个选项,使用这项新技术作为新桶的后端。随着我们对该技术的成熟和获得更多的运营经验,我们将开始计划升级现有客户和桶。这不会影响API,将以零停机时间交付。
对于我们的企业客户来说,我们将集成InfluxDB IOx与InfluxDB Enterprise,并提供一个帮助在Kubernetes环境中运行此软件的产品。然而,Kubernetes不是运行InfluxDB Enterprise或InfluxDB IOx的要求。它只是使一系列与集群灵活性和弹性相关的功能变得可用。
参与其中
目前,所有的事情都在InfluxDB IOx仓库本身或我们的社区Slack频道 #influxdb_iox上进行。您也可以在我们的社区Discourse上InfluxDB IOx分类中发表问题或评论。
在这篇帖子中,我还有很多想说的。我甚至没有真正深入核心技术细节。如果你对此感兴趣,我将在每个月第二个星期三的早上8点太平洋时间,举办一个每月技术深度解析演讲。
最后,如果你对这个项目感兴趣,并希望全职参与并获取报酬,我们现在正在招聘。我们正在寻找具备以下一项或多项技能的人:Rust、分布式系统和列式数据库。缺点是你必须直接与我合作,但优点是你可以与我的杰出团队成员一起工作。请发送电子邮件至[email protected]并抄送我[email protected]。