本章内容包括:
- 展示数据流程如何以任务图的形式在工作流中表示
- 了解Airflow如何适应工作流管理器的生态系统
- 判断Airflow是否适合您的需求
人们和企业日益趋向于更加数据驱动,并且正在开发数据流程作为其日常业务的一部分。随着业务流程涉及的数据量逐年增加,从每天的兆字节增加到每分钟的千兆字节,处理这些数据洪流可能看起来是一个巨大的挑战,但适当的工具可以有效地管理这些不断增加的数据量。
本书重点介绍Apache Airflow,这是一个用于构建数据流程的批处理框架。Airflow的关键特性在于它允许您使用灵活的Python框架轻松构建定时数据流程,并且提供了许多构建块,使您能够将现代技术领域中遇到的许多不同技术融合在一起。
Airflow最好被视为蜘蛛在网中:它位于数据处理过程的中心,并协调在不同(分布式)系统中进行的工作。因此,Airflow本身不是一个数据处理工具,而是编排负责在数据流程中处理您的数据的不同组件。
在本章中,我们将首先为您简要介绍Apache Airflow中的数据流程。然后,我们将讨论在评估Airflow是否适合您时需要考虑的几个因素,并演示如何开始使用Airflow。
数据流管道介绍
数据流程通常由多个任务或操作组成,需要执行这些任务或操作以实现所需的结果。例如,假设我们想要构建一个小型的天气仪表板,用于告诉我们未来一周的天气情况(见图1.1)。为了实现这个实时天气仪表板,我们需要执行类似以下的步骤:
- 从天气API获取天气预报数据。
- 清理或转换获取的数据(例如,将温度从华氏度转换为摄氏度或反之),以使数据适合我们的目的。
- 将转换后的数据推送到天气仪表板。
正如您所见,这个相对简单的数据流程已经包含了三个不同的任务,每个任务都执行部分工作。此外,这些任务需要按特定顺序执行,因为(例如)在获取数据之前尝试转换数据是没有意义的。同样,只有在数据经过所需的转换后,我们才能将任何新数据推送到仪表板上。因此,我们需要确保在运行此数据处理过程时也执行了这种隐式的任务顺序。
数据流程作为图形
使任务之间的依赖关系更加明确的一种方法是将数据流程绘制为图形。在基于图形的表示中,任务被表示为图中的节点,而任务之间的依赖关系则通过任务节点之间的有向边来表示。边的方向表示依赖关系的方向,从任务A指向任务B的边表示任务A需要在任务B开始之前完成。请注意,由于图中边的方向,这种类型的图通常被称为有向图。
将这种图形表示应用于我们的天气仪表板数据流程,我们可以看到图形提供了对整个流程相对直观的表示(见图1.2)。仅需快速浏览一下图形,我们就可以看到我们的数据流程由三个不同的任务组成,每个任务对应于所列出的一个任务。除此之外,边的方向清楚地指示了任务需要执行的顺序:我们只需按照箭头的方向来追踪执行顺序。
这种类型的图通常被称为有向无环图(DAG),因为该图包含有向边,并且不包含任何环路或循环(无环)。这种无环属性非常重要,因为它防止我们在任务之间遇到循环依赖(见图1.3)的情况(即任务A依赖于任务B,反之亦然)。这些循环依赖在尝试执行图形时会产生问题,因为我们会遇到任务2只有在任务3完成后才能执行的情况,而任务3只有在任务2完成后才能执行的情况。这种逻辑上的不一致导致了一种死锁类型的情况,其中既不能运行任务2也不能运行任务3,从而阻止我们执行该图形。
请注意,这种表示与循环图表示不同,循环图可以包含循环以说明算法的迭代部分(例如),这在许多机器学习应用中很常见。然而,DAG的无环属性被Airflow(以及许多其他工作流管理器)用于高效地解析和执行这些任务图形。在数据流程中,我们通常希望避免循环依赖,以确保数据流程可以在没有死锁的情况下正确执行。有向无环图(DAG)提供了一种很好的方式来管理任务之间的依赖关系,使得数据流程的调度和执行更加可靠和高效。
执行数据流程图
这种DAG表示的一个良好特性是它提供了一个相对直接的算法,可以用于运行数据流程。从概念上讲,这个算法包括以下步骤:
对于图中的每个未完成任务(即开启状态的任务),执行以下操作:
-
对于指向该任务的每个边,检查边的另一端是否已经完成了"上游"任务。 如果所有上游任务都已完成,则将考虑中的任务添加到执行队列中。
-
执行执行队列中的任务,一旦它们完成工作,将其标记为已完成。
-
回到步骤1并重复,直到图中的所有任务都已完成。
为了看到这是如何工作的,让我们跟踪一下我们的仪表板数据流程的一个小执行过程(见图1.4)。在我们算法的第一次循环中,我们可以看到清理和推送任务仍依赖于尚未完成的上游任务。因此,这些任务的依赖关系尚未满足,所以在此时它们不能被添加到执行队列。然而,获取任务没有任何入边,意味着它没有任何未满足的上游依赖关系,因此可以将其添加到执行队列中。
完成获取任务后,我们可以开始第二次循环,检查清理和推送任务的依赖关系。现在我们看到,由于上游依赖关系(即获取任务)已经完成,可以执行清理任务。因此,我们可以将该任务添加到执行队列中。推送任务无法添加到队列中,因为它依赖于我们尚未运行的清理任务。
在第三次循环中,完成清理任务后,推送任务终于可以执行,因为其对于清理任务的上游依赖关系现在已经满足。因此,我们可以将该任务添加到执行队列中。在推送任务执行完毕后,我们已经没有更多的任务需要执行,从而完成了整个数据流程的执行过程。
数据流程图 vs 顺序脚本
虽然使用图形表示数据流程提供了对数据流程中任务及其依赖关系的直观概述,但您可能会想知道为什么我们不直接使用简单的脚本来运行这个由三个步骤组成的线性链。为了说明基于图形的方法的一些优势,让我们来看一个稍微复杂一点的例子。在这个新的用例中,我们受到了一家雨伞公司业主的委托,该业主受到了我们天气仪表板的启发,希望尝试使用机器学习(ML)来提高公司的运营效率。为了实现这一目标,该公司希望我们实现一个数据流程,创建一个将雨伞销售与天气模式相关联的ML模型。然后,该模型可以根据未来几周的天气预报来预测公司雨伞的需求量(见图1.5)。
为了构建训练ML模型的数据流程,我们需要实现以下步骤:
-
准备销售数据,包括以下操作:
- 从数据源系统获取销售数据
- 清理/转换销售数据以符合要求
-
准备天气数据,包括以下操作:
- 从API获取天气预报数据
- 清理/转换天气数据以符合要求
-
将销售数据和天气数据集合并,创建合并后的数据集,可作为输入来创建预测性的ML模型。
-
使用合并后的数据集训练ML模型。
-
部署ML模型,使其可以被业务使用。
这个数据流程可以使用前面介绍的相同的基于图形的表示方式来表示,将任务表示为节点,任务之间的数据依赖关系表示为边。
与之前的例子相比,一个重要的区别是该数据流程的前两个步骤(获取和清理天气/销售数据)实际上是相互独立的,因为它们涉及到两个不同的数据集。这在数据流程图中通过两个分支清晰地表示出来(见图1.6)。如果我们应用数据流程图的执行算法,这两个分支可以并行执行,更好地利用可用资源,潜在地减少数据流程的运行时间,与按顺序执行任务相比。
基于图形的表示方式的另一个有用特性是,它将数据流程明确地划分为小的增量任务,而不是一个执行所有工作的单个庞大脚本或进程。虽然一开始可能认为拥有一个单一的庞大脚本并不是太大的问题,但当数据流程中的任务失败时,它可能会引入一些低效性,因为我们需要重新运行整个脚本。相比之下,在图形表示中,我们只需要重新运行失败的任务(以及任何下游依赖任务)。
使用工作流管理器运行数据流程
当然,在计算机领域中运行依赖任务的图形并非一个新问题。多年来,已经开发了许多所谓的"工作流管理"解决方案来解决这个问题,这些解决方案通常允许您将任务图形定义为工作流或数据流程,并进行执行。
您可能听说过一些知名的工作流管理器,其中包括表1.1中列出的一些。
尽管每个工作流管理器都有其优势和劣势,但它们都提供类似的核心功能,允许您定义和运行包含多个任务及其依赖关系的数据流程。
这些工具之间的一个关键区别在于它们如何定义工作流。例如,像Oozie这样的工具使用静态(XML)文件来定义工作流,这提供了易读的工作流,但灵活性有限。而其他解决方案如Luigi和Airflow允许您将工作流定义为代码,这提供了更大的灵活性,但可能更难阅读和测试(取决于实施工作流的人的编码技巧)。
其他关键区别在于工作流管理器提供的功能范围。例如,像Make和Luigi这样的工具不提供内置的工作流调度支持,这意味着如果您想要按照重复的时间表运行工作流,您将需要额外的工具,比如Cron。其他工具可能在平台内提供额外的功能,例如调度、监控、用户友好的Web界面等,这意味着您不必自己组合多个工具来获得这些功能。
总的来说,选择适合您需求的工作流管理解决方案将需要仔细考虑不同解决方案的关键功能以及它们如何符合您的要求。在接下来的部分中,我们将深入探讨本书的重点Airflow,并探讨使其特别适用于处理面向数据的工作流或数据流程的几个关键功能。
介绍Airflow
在本书中,我们专注于Airflow,这是一个用于开发和监控工作流程的开源解决方案。在本节中,我们将对Airflow的功能进行概述,然后详细讨论它是否适合您的用例。
使用(Python)代码灵活定义数据流程
与其他工作流管理器类似,Airflow允许您将数据流程或工作流定义为一组任务的有向无环图(DAG)。这些图形与前面部分中示例中的图形非常相似,其中任务被定义为图中的节点,依赖关系被定义为任务之间的有向边。
在Airflow中,您使用Python代码在DAG文件中定义您的DAG。这些DAG文件实质上是Python脚本,用于描述对应DAG的结构。因此,每个DAG文件通常描述了给定DAG的一组任务及任务之间的依赖关系,Airflow会解析这些信息以识别DAG的结构(见图1.7)。除此之外,DAG文件通常还包含有关DAG的其他元数据,告诉Airflow如何以及何时执行DAG等信息。在接下来的部分中,我们将深入探讨这个调度过程。
在使用Python代码定义Airflow DAG的一个优点是,这种编程方式为构建DAG提供了很大的灵活性。例如,正如我们在本书后面将看到的,您可以使用Python代码根据特定条件动态生成可选任务,甚至可以基于外部元数据或配置文件生成整个DAG。这种灵活性使您能够在构建数据流程时进行高度定制,让Airflow适应您构建任意复杂数据流程的需求。
除了这种灵活性外,Airflow的另一个优点是其基于Python的架构使得任务可以执行任何您在Python中实现的操作。随着时间的推移,这导致了许多Airflow扩展的开发,使您能够在各种系统上执行任务,包括外部数据库、大数据技术和各种云服务,从而使您能够构建复杂的数据流程,将来自许多不同系统的数据处理结合在一起。
调度和执行数据流程
一旦您将数据流程的结构定义为DAG(有向无环图),Airflow允许您为每个DAG定义调度间隔,从而确定Airflow何时运行您的数据流程。通过这种方式,您可以告诉Airflow每小时、每天、每周等执行您的DAG,甚至可以使用基于Cron表达式的更复杂的调度间隔。
为了了解Airflow如何执行您的DAG,让我们简要地看一下开发和运行Airflow DAG涉及的整体流程。在较高层面上,Airflow主要由三个主要组件组成(见图1.8):
- Airflow调度器 - 解析DAG,检查其调度间隔,并在DAG的调度时间到达时开始调度DAG的任务,将它们传递给Airflow工作进程。
- Airflow工作进程 - 获取安排执行的任务并执行它们。因此,工作进程负责实际上"完成工作"。
- Airflow Web服务器 - 可视化调度器解析的DAG,并为用户提供主要界面,用于监控DAG运行及其结果。
通过这些组件的协作,Airflow实现了数据流程的调度和执行。调度器负责确定何时执行DAG,工作进程执行实际的任务,而Web服务器则提供了用户界面来监控和管理DAG的运行。这样的设计使得Airflow成为一个功能强大且高度自动化的工作流管理解决方案,为您提供了一个强大而灵活的平台来管理和执行数据流程。在接下来的部分中,我们将更详细地探讨Airflow的各个组件以及它们如何协同工作来调度和执行DAG。
Airflow的核心可以说是调度器,因为这是决定何时以及如何执行数据流程的主要环节。在高层次上,调度器经过以下步骤(见图1.9):
- 用户编写的工作流程(DAG)文件被调度器读取,以提取每个DAG的任务、依赖关系和调度间隔。
- 对于每个DAG,调度器检查DAG的调度间隔是否已经超过上次读取它的时间。如果是,DAG中的任务被调度执行。
- 对于每个调度的任务,调度器检查任务的依赖项(即上游任务)是否已经完成。如果是,任务被添加到执行队列。
- 调度器在几个时间间隔后等待新的循环开始,然后跳回到步骤1。
通过这些步骤,调度器实现了对DAG的调度和任务的执行。一旦满足DAG的调度间隔和任务的依赖条件,调度器就会自动将任务添加到执行队列,从而实现了数据流程的自动化和可靠的执行。调度器的这种工作方式使得Airflow成为一个强大的工作流管理解决方案,可以有效地处理复杂的数据处理流程。在接下来的部分中,我们将更详细地探讨调度器的工作原理和调度算法,帮助您更好地理解Airflow的调度过程。
敏锐的读者可能已经注意到,调度器遵循的步骤实际上与第1.1节介绍的算法非常相似。这不是偶然的,因为Airflow实际上是遵循相同的步骤,在此基础上添加了一些额外的逻辑来处理其调度逻辑。
一旦任务被加入执行队列,它们将被Airflow工作进程池拾取,并在并行执行任务的同时跟踪任务的结果。这些结果被传递给Airflow的元存储(metastore),使得用户可以通过Airflow的Web界面(由Airflow Web服务器提供)来跟踪任务的进度和查看任务的日志。
监控和处理失败
除了调度和执行DAG外,Airflow还提供了一个全面的Web界面,可用于查看DAG和监控DAG运行的结果。登录后(见图1.10),主页会提供各个DAG的全面概览,并显示它们最近运行结果的汇总视图(见图1.11)。
例如,单个DAG的图形视图提供了DAG任务和依赖关系的清晰概览(见图1.12),类似于本章中我们绘制的示意图。此视图特别适用于查看DAG的结构(提供任务之间依赖关系的详细信息),以及查看单个DAG运行的结果。
除了图形视图外,Airflow还提供了详细的树形视图,显示了相应DAG的所有运行中和历史运行的情况(见图1.13)。这可以说是Web界面提供的最强大的视图,因为它让您快速了解DAG随时间的执行情况,并允许您深入了解失败的任务,以查看出现了什么问题。
默认情况下,Airflow可以通过尝试多次(可选择在尝试之间等待一定时间)来处理任务失败,这有助于任务从任何间歇性故障中恢复。如果重试无效,Airflow会将任务标记为失败,并在配置的情况下通知您有关失败的信息。调试任务失败非常简单,因为树形视图允许您查看哪些任务失败并查看它们的日志。同样的视图还允许您清除单个任务的结果以重新运行它们(以及依赖于该任务的任何任务),使您能够在更改任务代码后轻松地重新运行任何任务。
增量加载和回填
Airflow的调度语义中一个强大的特性是调度间隔不仅触发DAG在特定时间点运行(类似于Cron等),而且还提供了关于上一个和(预期的)下一个调度间隔的详细信息。这实际上允许您将时间划分为离散间隔(例如每天、每周等),并为每个间隔运行DAG。
这种Airflow调度间隔的特性对于实现高效的数据流程非常宝贵,因为它允许您构建增量数据流程。在这些增量流程中,每个DAG运行仅处理相应时间段的数据(数据的增量),而不是每次都重新处理整个数据集。特别是对于较大的数据集,通过避免对现有结果进行昂贵的重新计算,这可以带来显著的时间和成本优势。
当将调度间隔与回填(backfilling)的概念结合在一起时,调度间隔变得更加强大,回填允许您为过去发生的历史调度间隔执行新的DAG。这个特性使您可以轻松地创建(或回填)包含历史数据的新数据集,只需为这些过去的调度间隔运行您的DAG。此外,通过清除过去运行的结果,您还可以使用Airflow的这个特性轻松地重新运行任何历史任务,如果您对任务代码进行了更改,可以方便地重新处理整个数据集。
使用Airflow的时机
在这个简短的Airflow介绍之后,我们希望您对了解Airflow和深入了解其关键功能感到兴奋。然而,在继续之前,我们首先将探讨一些您可能选择使用Airflow的原因(以及可能选择不使用的原因),以确保Airflow确实是最适合您的选择。
选择Airflow的原因
在前面的部分中,我们已经描述了使Airflow成为实现批处理数据流程的理想选择的一些关键功能。总结起来,这些功能包括以下几点:
- 使用Python代码实现管道:Airflow允许您使用Python代码创建任意复杂的数据流程,您可以使用Python实现您所能想象的任何功能。
- 基于Python的灵活性:Airflow的Python基础使得轻松扩展和添加与许多不同系统的集成成为可能。实际上,Airflow社区已经开发了丰富的扩展,使得Airflow能够与许多不同类型的数据库、云服务等进行集成。
- 强大的调度语义:丰富的调度语义允许您按照固定的时间间隔运行数据流程,并构建高效的数据流程,使用增量处理来避免昂贵的现有结果重新计算。
- 回填等功能:回填等功能使您可以轻松地重新处理历史数据,使得在对代码进行更改后,可以重新计算任何派生的数据集。
- 丰富的Web界面:Airflow的丰富Web界面提供了方便的视图,用于监控数据流程运行的结果和调试可能发生的任何故障。
- 开源性:Airflow是开源的,这意味着您可以在Airflow上构建您的工作流而不会受到任何供应商限制。如果您需要技术支持,一些公司也提供了托管的Airflow解决方案,使您在运行和管理Airflow安装时具有很大的灵活性。
综上所述,Airflow是一个功能强大、灵活且开源的工作流管理工具,适用于实现各种批处理数据流程。它提供了丰富的功能和灵活性,使您能够高效地构建和管理数据流程,并监控其运行状态。
选择不使用Airflow的原因
尽管Airflow具有许多丰富的功能,但其设计选择可能使其在某些情况下不太适合。以下是一些不适合使用Airflow的用例:
- 处理流式数据流:Airflow主要设计用于运行定期或批处理任务,而不是流式工作负载。对于处理流式数据的场景,Airflow可能不是最佳选择。
- 实现高度动态的数据流程:在这种情况下,任务在每次数据流程运行时都会被添加或移除。虽然Airflow可以实现这种动态行为,但Web界面只会显示最新版本DAG中仍然定义的任务。因此,Airflow更适用于数据流程结构每次运行时不会发生变化的情况。
- 队伍中缺乏(Python)编程经验:对于缺乏Python编程经验的团队,使用Python来实现DAG可能会很困难。在这种情况下,使用带有图形界面(例如Azure Data Factory)或静态工作流程定义的工作流程管理工具可能更合适。
- 对于较大的用例,DAG中的Python代码可能会变得复杂。因此,实现和维护Airflow DAG需要适当的工程化方法,以确保长期内可维护性。
- Airflow主要是一个工作流程/数据流程管理平台,目前不包括更多的功能,例如维护数据血缘、数据版本控制等。如果您需要这些功能,可能需要考虑将Airflow与其他提供这些功能的专业工具结合使用。
综上所述,尽管Airflow具有许多优势,但它并不适合所有情况。在选择使用Airflow之前,需要仔细评估您的用例和团队的需求,以确保它是最佳选择。
本书的其余部分
到目前为止,您应该(希望如此)对Airflow是什么以及其功能如何帮助您实现和运行数据流程有了很好的了解。在本书的其余部分,我们将首先介绍您需要熟悉的Airflow基本组件,以便开始构建自己的数据流程。这几章应该适用于广泛的读者群体。对于这些章节,我们期望您具有中级的Python编程经验(约为一年的经验),这意味着您应该熟悉基本的概念,如字符串格式化、推导、args/kwargs等。您还应该熟悉Linux终端的基础知识,并具有基本的数据库(包括SQL)和不同数据格式的工作知识。
在这个介绍之后,我们将深入探讨Airflow的更高级功能,比如生成动态DAGs、实现自定义操作符、运行容器化任务等。这些章节需要更多关于所涉及技术的理解,包括编写自己的Python类、基本的Docker概念、文件格式和数据分区。我们期望这第二部分对数据工程师尤其感兴趣。
最后,本书末尾的几章聚焦于围绕Airflow的部署主题,包括部署模式、监控、安全性和云架构。我们预计这些章节对于有兴趣部署和管理Airflow部署的人员,如系统管理员和DevOps工程师,将特别有吸引力。