Dagster:一种数据编排器


随着机器学习、数据分析和数据处理对企业变得越来越复杂和越来越重要,改进其背后的软件变得更加迫切。

企业内的数据是无序的,不受信的。工程师和从业者因此深感效率低下,深陷苦差事之中。数据科学家、数据工程师、分析师和其他构建复杂数据系统的角色之间的协作是痛苦的。处理和产生数据的软件不可靠且难以改变。

这种状况是Dagster存在的原因,我们曾在一年前首次公开讨论过这个问题

Dagster是一种新型的工作流引擎,即数据编排器。Dagster不仅仅管理数据计算的顺序和物理执行,它还引入了一个新的标准:一个数据感知的、类型化的、自我描述的逻辑协调图。这个图明确地模拟了每个数据应用和平台中隐含的、预先存在的结构。我们相信,这个图对于整个应用程序生命周期是不可或缺的,并且,当通过API访问和操作它时,它可以形成工具和库的整个生态系统的基础。

Dagster主要针对两类受众,第一种是负责整个端到端数据应用和基础设施的全栈工程师和数据科学家,第二种是使其他数据团队能够高效自主地交付特性和功能的平台团队。他们都非常关心角色、工具和基础设施之间的交互和接口。技术选择并没有限制他们,Dagster灵活且适配性强,可以运行任何工具,使用任何存储,并部署到任何基础设施。

将这些受众团结在一起的还有一个信念,那就是当今的数据系统中存在一些“不对劲”的地方。代码不够抽象,测试不足。低效的开发环境和重复的基础设施管理困扰着开发者的体验。使用到的系统太不可靠,难以改变。解决问题的方法就是引入新的抽象和工具,使这些系统更具可测试性、可靠性和构建乐趣。

自推出以来,我们与许多用户一起使用Dagster构件了出色的系统。我们最新的版本0.9.0,代号为“Laundry Service”,代表了这一年来努力工作和学习的结束。这篇文章将讨论我们学到了什么,我们构建了什么,以及我们用来指导系统演进的设计原则。

数据应用程序和编排图

经过一年的时间,我们对数据应用这个概念的广泛适用性更有信心了,它将一组软件实践、工件和系统,如ETL、ELT和ML训练统一起来,尽管这些有着不同的历史渊源,但它们的需求和特性是趋同的。我们将数据应用定义为消费和生产数据资产的计算图。

这些系统的共同特点转化为数据团队今天所感受到的挑战:
  • 具备快速反馈周期的本地开发
  • 部署前的有效测试
  • 与数据从业者使用的各种工具集成
  • 构建它们的不同角色之间的协作
  • 出现问题时进行调试
  • 将数据资产链接到产生它们的代码上
  • 根据不断变化、日益苛刻的要求管理应用程序复杂性


最终结果是系统会具有惊人的复杂性,而如何支持这些系统的软件生态系统无法满足这个艰巨的需求。

当前,Airflow等传统工作流引擎使用纯操作依赖图,确保正确的执行顺序,管理重试,合并日志等等。这些系统对比松散耦合的计划任务和其他没有正式定义依赖的方案,是一个巨大的进步。专注于执行结果允许这些系统可以最大限度地发挥通用性,同时要求它们对编排的代码进行最小的更改。

Dagster做了不同的权衡,启用一种更加结构化的编程模式来暴露一个更丰富的、语义感知的图。Dagster内部的数据计算包括:
  • 以输入和输出类型化的粗粒度函数建模,而不是以无参数的任务建模
  • 与数据依赖链接而非单纯的执行依赖
  • 通过模式化配置与代码分离,而不是紧密耦合、结构松散的代码和配置
  • 可在多个环境(dev、test和prod)中执行,不受特定部署的限制
  • 可通过元数据事件流观察,而非完全的“黑盒”计算
  • 可在不依赖任何基础设施的本地环境中的工具中查看,不仅在部署和执行之后


我们称此有异议的结构为编排图。这个图和在其API上构建的工具支持一种显著改进的方式来构造数据系统。它可以灵活地进行测试、部署、执行、重用和调试。可以围绕它构建一个软件工程流程,其中多个团队和角色可以有效地发挥作用,并且它自然而然地成为你的数据流程的记录系统。


编排图是链接所有从业者的抽象概念。
我们在设计这个图和系统时考虑了更广泛的原则。这些原则编码了我们对数据应用的潜在性质和更广泛的生态系统方向的信念。

  1. 承认和管理复杂性。数据应用建设是一项极其艰巨的工作,而现状是软件不够抽象导致混乱和难以控制的复杂性。这类复杂性无法随愿望而消失,相反,承认它并采用管理它所需的抽象和工程流程。

  2. 拥抱异质性。数据工具和系统的异质性是有原因的,拥有不同技能,需求和工具偏好的人构建了这些工具和系统。它们在各种基础设施上部署和执行。与其强求同质性和垂直整合,不如拥抱异质性,并利用交叉工具和软件抽象来管理它。

  3. 数据感知编排。数据应用程序中的计算会消费和产生数据。编排器应意识到这一点。类型化数据依赖意味着正确的、可测试的和可理解的软件。计算发出的结构化元数据事件是操作数据和创建资产的明确日志,形成了数据目录、数据系列和自助服务操作的关键基础层。


编排图是连接所有从业者的公共抽象。从业者可能使用不同的计算运行时,存储系统,编程语言和工具,但是它们消费和生产的数据资产必须是从哪来到哪去。这种通用性使其成为共享工具、协作和管理系统复杂性的天然优势。编排图不仅应该为计算排序,它还应该将计算和它们产生的资产结构化、组织化和相互关联。

承认和管理复杂性

这是软件

值得反复强调的是,数据应用程序仍是软件应用,软件工程的许多原则在数据领域都有其必然结果。但是,尝试盲目地将传统的软件工程技术应用于数据的做法往往没有达到预期的效果,尤其是与笔记本等非传统类型的工具的影响对比。我们需要使软件工程概念融入这个相邻的领域,在这个领域中,不受控制的输入和严重的副作用是常规而非例外。

我们认为,今天的数据工程与十年前的Web前端工程地位类似。都是在一个新的复杂的领域里角力,严重缺少工具,并且经常被那些拥有更成熟工具的,在其他更易理解的领域(如系统编程)的实践者无端地轻视。当时,前端工程需要对Web标准和浏览器API,新的编程模型和运行时进行修改,以及对工具的投入。今天,即使是初级前端开发人员也能使用复杂的框架,这些框架大都建立在被认为是神秘的函数式编程原则之上,使用由健康的生态系统支持的高质量的工具。

就如十年前的Web前端一样,我们相信数据应用工程需要一些新的方法。Dagster提供了一套新颖的抽象,从而使代码更具弹性、可测试、可重用。

这里有个例子,它将我们的许多抽象合并到Pandas中执行的数据计算中:
1.png

这个例子使用Pandas来加载关于谷物的数据,计算sugar_per_cup这个值,然后过滤掉低于该值的某个可配置百分比的谷物。然后将结果保存为数据湖中的文件。

这段代码演示了Dagster的一些值得注意的属性。

  1. 函数计算。核心抽象是一个实体,是编排图中的一个功能计算单位。这些实体描述了它们的数据需求(以类型化输入和输出的形式),配置(使用config_schema)和环境需求(使用required_resource_keys表示)。

  2. 数据依赖性。实体使用数据感知依赖关系相互连接。该系统负责将数据(或数据指针)从一个实体的输出封送到另一个实体的输入。这段代码构建编排流程图结构,但不直接执行它。

  3. 渐进式输入和输出。Dagster使用了一个渐进的、可选的类型系统。注意add_sugar_per_cup的输入是一个DataFrame类型,其内部结构没有约束。然而,它的输出定义了列模式和其他在运行时验证的约束。这些都是在软件中指定的灵活的用户定义类型。

  4. 可配置。实体(以及其他工件)同样可以定义一个具有嵌入式文档、默认值和其他特性的类型化的配置模式。该模式确保传递的配置值符合特定的格式和类型。类型化模式意味着更早的错误检测,高质量的错误信息以及更易于使用和重用。它还能实现工具支持,比如在Dagit中的自动完成配置编辑器。

  5. 抽象的环境。上下文对象对环境进行抽象。任何严重的外部依赖都可以被建模为用户提供的资源并附加到系统提供的上下文中。资源在流水线中贯穿基础设施,并提供一间接层以便用户可以在测试或本地开发中接入资源的不同实现。

  6. 事件流。实体在计算过程中会生成结构化的元数据事件流。这个事件流是持久化的,并作为你的系统中所发生的一切的不可改变的记录。事件日志明确地将数据与产生它们的计算联系起来,并包含操作数据。


采用这个API使编排图可以在本地开发环境和生产操作时通过Dagit这样的工具访问。

视频:https://v.qq.com/x/page/l3139de836q.html

这些抽象的东西具有生态系统效应,我们慢慢开始感受到。以这个PySpark实体为例:
3.png

请注意该作业是使用原生PySpark API编写,并且仅定义了业务逻辑。值得一提的是,这段代码无需修改就能在你的笔记本上的Spark集群或是AWS上的远程的EMR集群,或Databricks运行时上执行。唯一需要改变的是pyspark_step_launcher资源的配置。库文件包含了该资源的特定的实现。实际上,Databricks变体是由社区贡献的,将其扩展到GCP、Azure、Qubole或其他运行时也会相对简单。Dagster提供了足够的架构,使这些基础设施的关注点可以使用资源从业务逻辑中抽象出来,然后在更广泛的生态系统中共享

正确地使用这些抽象意味着代码将会更容易测试,更容易被重用,更具可观测性,并且更易于在不同的环境中执行。我们的用户通常会构建可重复使用的实体和资源的库以加速开发他们的数据平台。我们也开始感受到整个生态系统的再利用效应,这非常令人振奋。实体成为数据处理的可重用组件,资源成为封装基础设施的可重用组件。

拥抱异质性

多角色,多工具,多团队,多环境

历史上,非工程师在纵向一体化的图形工具中编写ETL工作流程。有些工具至今还在使用,例如Informatica PowerCenter或Talend。这些都是受到严格限制的开发环境,通常没有纳入正式的工程流程中。

这些工具以该种形式存在是有一定道理的,没有理由所有数据领域的主题专家和业务用户都要成为受过正规训练的软件工程师。但数据应用的复杂性和集成要求早已超过了这些封闭的专有系统的能力。今天,很多公司通常会建立内部数据平台,由各种工具组成,由软件工程师集中管理。

这些集中式的系统释放了另一种组织病理学:了解该领域的数据从业者并没有端到端能力。然后,这些领域专家必须将生产工作交给一个完全不同的团队,这个团队拥有专门的技术技能,但领域知识有限。在这种孤立的结构中,端到端所有权是根本不可能的。

将每个数据从业者转变为经过训练的软件工程师这个目标既非合理,又非理想。但是要构建可靠的多角色的应用,数据从业者需要获得适当的工具支持,并集成到一个更广泛的系统中,以便他们成为软件工程过程中的开发者。

异构数据工具

dbt是一个软件开发工具的出色的例子,其旨在让没有受过正规训练的软件工程师的用户构建数据应用。dbt背后的团队正在将无数的分析师转变为分析工程师。通过使用一个经过深思熟虑设计的工具,使得SQL分析师可以构建模块化、可测试、可重复的软件。

该类别的另一个工具是Papermill,一个开源的库用于参数化以及执行Jupyter notebooks。Jupyter是一个在数据科学届广泛使用的工具,提供具有内联可视化的交互式编程环境。Notebook被誉为是废弃的、不可重复使用的代码的温床,只能在原作者的环境中执行。Papermill提供了一个新的中间地带,即参数化的notebook,可作为粗粒度的函数调用,可以在生产工作流程中进行测试和调度。

这些工具的用户不必学习Dagster编程模式中的每个概念。生态系统库和内部数据平台团队提供的集成可以使工具适配Dagster环境。我们的团队和用户将此策略应用于dbt、Papermill和其他工具集成上。在这些特定领域工具中创建的计算被纳入到一个更广泛的编排图中,这个编排图定义了整个多角色数据应用。

下面是我们与Papermill集成的例子,名为Dagstermill。
4.png

该集成使这些notebook成为实体,可在Dagster工具中使用:

视频:https://v.qq.com/x/page/l31396q5vol.html

所有的数据处理工具都会消费数据,进行计算并产生结果。Dagster灵活得足以将它们中的任何一个集成到编排图中。随着我们的生态系统的发展,我们预计会有更多与特定领域工具的集成。

异质性团队

数据平台不可避免地服务于许多想要某种程度的操作隔离和独立的团队。我们之前提到过编排图触及管理数据的每个团队和工具。它可能会演变成一个集中式的,最小化结构的,隔离度极低的无人管理的垃圾场。

Python的依赖冲突问题往往是这种不希望出现的依赖关系的第一个表现。数据科学团队编写的Pipeline不应该与数据工程团队在系统的其他地方使用到PySpark和JVM的依赖关系纠缠在一起。每个团队希望使用自己的工具,有各自的具体依赖性,按自己的计划部署,同时仍然利用共享的基础设施。

由于我们的用户在多个团队中部署Dagster,他们与我们都亲身经历了这种痛苦。以前,我们在工具中直接将用户代码加载到进程中,导致系统环境与用户定义的环境和单体部署计划混合在一起。错误的用户代码也会使我们的服务崩溃或不稳定。

我们现在在工具与用户定义的流水线间实施了严格的进程隔离,通过gRPC接口与这些进程进行通信:
6.png

该架构允许不同团队在共享基础架构上独立执行。

进程隔离意味着团队可以使用不同的Python环境甚至是不同的Python版本,这意味着用户代码不大可能会将不稳定性引入到核心基础设施上。团队特定的代码可以独立于其他团队和平台进行部署和版本管理,同时仍然共享关键的基础设施和运营工具。

异构的基础设施

数据领域的异质性不仅适用于工具,同时也适用于基础设施和部署。正如Dagster与任何数据工具例如Spark、Python等的接口一样,它也可以部署到任何云和执行底层,例如Kubernetes,内部裸机节点或定制化的PaaS平台。

Dagster拥有用于部署到通用基础设施栈的库和工具。例如,由于广泛采用Kubernetes作为执行底层,我们做了很大投入,为使用Helm部署Dagster和它的组件提供了预制解决方案。

然而,尽管我们支持在Kubernetes上的开箱即用部署,但我们并不严格要求Kubernetes。虽然Kubernete是一种流行的技术,其发展势头不可否认,但我们不相信Kubernetes将成为管理计算的通用答案。实际上,我们认为很多团队太快跳到Kubernetes上,或许会出现一种反潮流,回归到PaaS或FaaS等更简单的管理计算底层。

即使你是部署到Kubernetes上,你也不想运行你的整个集群来测试你的流水线。部署应该独立于测试。Dagster的可插拔能力意味着你能独立于你的部署目标来进行开发和测试。
7.png

早期用户使用我们预搭建的Kubernetes基础设施,将Dagster生产实例快速部署到现代云环境中。但架构的灵活性也让我们的用户能在许多其他规格配置上部署Dagster。例如在定制化的PaaS,分配短暂的每次运行的计算资源,在一个使用Dask作为执行程序的空数据中心,使用Docker-in-Docker在隔离的容器中运行Dagster。随着生态系统的成熟,我们期待更多的部署策略和对库的支持。

异构的一切

我们已经描述了数据生态系统异质性的三大纬度:处理工具、团队和基础设施。但是数据领域的异质性远远超出这篇文章的范围。投资者们试图用这样的技术图谱来描述当前的生态系统:
8.png

这很令人费解,不是因为作者不够努力或不聪明,而是因为世界的潜在现实。这种情况短期内不会改变。没有单一的数据仓库、存储系统、计算运行时或纵向一体化平台来管理它们。

这个生态系统包含不同种类的数据和访问模式:大数据和小数据、图数据和日志数据、分析和事务性工作负载、流式与并行算法等等。多样性要求存储和计算系统具有异构性。适用于不同角色的人体工程学也要求在工具上有所变化。编写Spark的数据工程师,编写notebook的数据科学家,还有编写SQL的分析师,这些从业者使用截然不同的工具和流程在同一个逻辑数据应用中编写计算。虽然管理起来令人生畏,但这种差异性最终是一种优势。

数据感知编排

工作流引擎能正确地对计算进行排序和管理,但是在执行之前和运行时,它们通常都不知道自己在做什么。我们坚信这是一个缺失的机会。在编排层面采用数据感知可以在应用生命周期的各个阶段提高生产率和结果。

Dagster将编排流程图的元素与数据依赖项连接起来。这个属性有利于测试性、流程之间的中间数据的封送,并通过类型化提高正确性。然而,这并不是数据感知的唯一维度。

在编排层采用数据感知可以提高应用程序生命周期的所有阶段的生产率和结果。

Dagster计算在运行时也会发出结构化的元数据事件流。其中一些事件是系统生成的,但也可以由用户提供。它们被发送到我们的运行时,存储在我们的基础设施中,然后流回到我们的工具。此事件日志是用于本地开发和生产操作的实时、交互式工具的基础。

这个不可变的事件日志同时也是数据系统中所有活动的最终记录。如果没有这样的记录,要可靠地回答诸如“我的报表是在最近的数据导入前还是之后更新的”这样的问题将会出奇的困难。我们预计该事件日志将成为数据基础设施中的重要组成部分,并成为整套有用工具套件的基础。
9.png

事件类型反映了资产的具体化。我们对资产的定义包括任何可能在计算范围之外产生的实体。资产可以是传统的,如数据仓库中的表和对象存储中的文件,也可以是非传统的,如Slack消息和GitHub拉取请求。

在资产元数据仓库上,我们建立了一个新的工具,叫资产管理器。它为计算过程中产生的资产提供索引,其独特价值在于资产和产生这些资产的计算之间的深度联系。你可以查看流水线或独立的运运行看到它所创建的资产。同样你也可以查看一项资产并快速定位到是什么流水线以及什么时候创建或生成它们的。

我们相信,由我们的编程模型实现的这种可验证,可信的链接,是数据可观察性和自助服务操作中的一个重要的,缺失的基石。这种开箱即用的链接是数据感知编排器能够独特提供的功能。它可以作为数据目录的基础层,而不需要加入其他工具。我们的目标不是成为通用的数据目录,我们期望能与更复杂的数据目录(如Amundsen和Marquez)进行整合。

用户可以在资产管理器中检查一个流水线并立即看到它所创建的资产,而不需要去检查代码或是在Slack频道上发问。相反地,用户可以在不离开工具的情况下查找资产并查看是什么计算产生了它。

这为那些首先考虑资产的用户提供了操作和监控,许多用户甚至不知道生成资产的流水线或计算是什么。他们可以在资产管理器中查找它,至少可以快速定位并联系具体负责维护和产生这些数据资产的人或团队。我们的用户同样反映,资产管理器支持自助操作,使得领域专家对资产生产的端到端的所有权几乎不需要平台团队的干预。

全生命周期的数据编排器

在过去的十年间,数据技术有了巨大的进步,特别是在管理规模方面。只要有合适的工具和足够的资源,任何组织都可以使用构建在无限、廉价的存储和弹性计算之上的高级计算运行时和云数据仓库。大规模将打入大众市场。

现在主要的挑战在更高的层次:生产力,测试,集成,协作,正确性和调试。解决这些挑战并不是一个分布式系统问题,而是如何组织和架构软件,以及如何使用它来实现流程和影响组织设计。

我们相信,一种新型的工作流引擎,数据编排器将有机会问世。它的核心是一个新的工件,即编排图。

编排图是数据系统中一个强大的杠杆点。它管理所有的业务逻辑,调用每一个数据处理运行时,并通过扩展,从企业中的每个存储系统写入和读取数据。每个数据从业者都必须与此工件交互。

与其在部署后管理狭隘的执行问题,我们认为图应该是一个丰富的工件,以应用程序的生命周期的每一个阶段为核心。
  • 本地开发:Dagster仅需很小的系统依赖就能在本地运行,编排图可以在部署和执行前查看
  • 测试:该图有一个为可测试性设计的编程模型。可参数化的计算和可插拔的环境意味着在不同的数据和不同的背景下执行。
  • 部署:系统代码与用户库之间的进程隔离支持平台和用户团队独立可靠地部署。
  • 操作性:我们的运营工具建立在结构化事件流的基础上,能够实现数据和计算的联动,从而加快数据团队的调试和端到端所有权。


我们的用户报告说,他们通过这个系统提高了个人的生产力,更早地发现了缺陷,提高了涉众的自主性,更好的协作,增加了代码的重用,更容易理解系统,更好的数据跟踪,并提高了软件的可靠性。单独考虑,列出的每个维度都有相当大的价值。综合起来,它的好处是多种多样的。最终结果是,这个系统可以让你有效地管理复杂性,而这在结构较松散的系统中是不可能实现的。

未来的路

这个版本标志着Dagster的质量和成熟度达到了一个新的水平。我们相信,它可以为大规模的数据应用提供强大的动力,这个生态系统可以支持更多的用户。我们期待着就该项目进行更公开的交流。我们希望我们已经证明,一个可操作的、数据感知的编排图及其产生的元数据能够轻而易举地支持所有工具的开发。

欢迎查看我们的代码和改版后的文档,并加入我们的Slack。要使数据应用的开发、操作、调试和扩展感觉更现代化,我们还有很多工作要做。如果你也对这个问题充满热情,可以考虑与Dagster、Elementl背后的团队合作。

原文链接:Dagster: The Data Orchestrator(翻译:冯旭松)

2 个评论

要回复文章请先登录注册