构建端到端的开源现代数据平台

2022-12-09 21:20:20 浏览数 (2)

在过去的几年里,数据工程领域的重要性突飞猛进,为加速创新和进步打开了大门——从今天开始,越来越多的人开始思考数据资源以及如何更好地利用它们。这一进步反过来又导致了数据技术的“第三次浪潮”。“第一次浪潮”包括 ETL、OLAP 和关系数据仓库,它们是商业智能 (BI) 生态系统的基石,无法应对大数据的4V[1]的指数增长。由于面向 BI 的栈的潜力有限,我们随后见证了“第二次浪潮”:由于 Hadoop 生态系统(允许公司横向扩展其数据平台)和 Apache Spark(为大规模高效的内存数据处理打开了大门)。

称之为“第三次浪潮”的是这个我们不再担心可扩展性或分布式存储的时代。相反我们正在成熟的分布式数据平台之上构建新功能,现在我们可以考虑元数据管理、大规模数据发现和数据可靠性等主题。我们正处于可互换的 SaaS 模块、基于云的平台、ELT 和民主化数据访问的时代。欢迎来到现代数据栈浪潮。

本文中我们将从头开始构建一个端到端的现代数据平台,完全依赖开源技术和云提供商提供的资源。这篇文章还附有一个 GitHub 存储库[2],其中包含构建平台所需的必要代码和基础设施即代码 (IaC) 脚本。该平台将由以下组件组成:

  • 数据仓库:这是我们平台设计中最重要的组件,因为无论其他组件变得多么复杂,低效的数据仓库都会给我们带来问题。从根本上说数据仓库背后的 40 年历史概念和范式至今仍然适用,但结合了“第二次浪潮”带来的水平可扩展性,从而实现了高效的 ELT 架构。
  • 数据集成:不出所料我们需要将数据输入至平台,而以前配置和实现连接器的繁琐任务现在已通过现代数据栈解决。
  • 数据转换:一旦数据进入数据仓库(因此完成了 ELT 架构的 EL 部分),我们需要在它之上构建管道来转换,以便我们可以直接使用它并从中提取价值和洞察力——这个过程是我们 ELT 中的 T,它以前通常由不易管理的大的查询 SQL 或复杂的 Spark 脚本组成,但同样在这“第三次浪潮”中我们现在有了必要的工具更好地管理数据转换。
  • 编排(可选):我们仍然需要执行编排管道以确保数据尽快可用,并且数据生命周期从一个组件顺利运行到下一个组件,但目前是可选的,因为我们使用的一些工具提供了开箱即用的调度功能,因此在平台生命周期的第一阶段不需要专门的编排组件(它会添加不必要的复杂)。尽管如此我们将在本文中讨论编排,因为最终需要将添加到平台中。
  • 数据监控(可选):更多数据意味着更多潜在的数据质量问题。为了能够信任数据,我们需要对其进行监控并确保基于它生成准确的见解,但目前是可选的,因为在开始时最有效的选择是利用其他组件的数据测试功能,但我们将在本文中讨论数据监控工具。
  • 数据可视化:这是我们实际探索数据并以不同数据产品(如仪表板和报告)的形式从中产生价值的地方。这个时代的主要优势之一是现在拥有成熟的开源数据可视化平台并可以以简化的方式进行部署。
  • 元数据管理:平台的大部分功能(如数据发现和数据治理)都依赖于元数据,因此需要确保元数据在整个平台中共享和利用。

最后请记住尽管讨论的技术和工具是开源的,但我们将在云环境中构建平台以及使用的资源(用于计算、存储等)、云环境本身并不免费,但不会超过 GCP 免费试用[3]提供的 300 美元预算。如果想避免设置云环境,可以在本地尝试不同的工具,只需将数据仓库(示例中的 BigQuery)替换为开源替代品(像 PostgreSQL 这样的 RDBMS 就可以了)。事不宜迟,让我们开始构建现代数据平台。

首先,谈谈数据

要构建示例数据平台,第一步是选择一个或多个要使用的数据集,这是一个探索在线可用的多个开放数据集之一的机会,建议使用一个感兴趣的数据集——这将使构建过程更加愉快,因为对数据真正感兴趣。如果您想要一些灵感,可以使用以下数据集之一:

  • • 一级方程式世界锦标赛(1950-2021):该数据集可以从 Kaggle 下载[4]或直接从 Ergast HTTP API[5] 检索,其中包含一级方程式比赛、车手、车队、排位赛、赛道、单圈时间、维修站的所有可用数据点停止,从 1950 年到 2021 年的冠军。如果你像我一样是 F1 粉丝,这个数据集可以为你提供关于这项运动的许多有趣的见解。
  • • 世界发展指标[6](1960-2020):世界银行提供的这个数据集无疑是可以在网上找到的最丰富的开放数据集之一,它包含大约 1500 个发展指标。

数据仓库:BigQuery

如上所述选择正确的数据仓库是我们难题中最重要的部分。主要的三个选项是 Snowflake[7]、BigQuery[8] 和 Redshift[9]。它们都不是开源但都是无服务器托管形态,这意味着我们可以利用复杂的现代数据仓库的功能,同时只需为消耗的存储和计算资源付费。无服务器托管正是现阶段寻找的,即使该产品不是开源的,那是因为我们的诉求是可以在存储和查询性能方面进行扩展,而不需要专门的运维。因此入门时的理想选择是无服务器托管产品——这适用于我们所有需要弹性的组件,而不仅仅是数据仓库。BigQuery 非常适合这个要求,原因有很多,其中两个如下:

  • • 首先它本质上是无服务器的。由于存储和计算的解耦,其背后的设计[10]提高了效率,使其成为所有类型用例的非常可靠的选择。另一方面Redshift 的无服务器产品仍处于测试阶段。
  • • 其次它是云提供商产品的一部分,因此已经与 GCP 生态系统的所有组件无缝集成。这进一步简化了我们的架构,因为它最大限度地减少了配置工作。

因此我们将 BigQuery 用作该平台的数据仓库,但这并不是一定的,在其他情况下选择其他选项可能更适合。在选择数据仓库时,应该考虑定价、可扩展性和性能等因素,然后选择最适合您的用例的选项。首先我们只需要创建一个数据集[11],也可以随时熟悉 BigQuery 的一些更高级的概念,例如分区[12]和物化视图[13]。在 ELT 架构中数据仓库用于存储我们所有的数据层,这意味着我们不仅将使用它来存储数据或查询数据以进行分析用例,而且还将利用它作为执行引擎进行不同的转换。现在已经选择了数据仓库,架构如下所示:

在进入下一个组件之前,将 BigQuery 审计日志存储在专用数据集中[14](附加说明[15]),这些信息在设置元数据管理组件时会被用到。

摄取数据:Airbyte

在考虑现代数据栈中的数据集成产品时会发现少数公司(使用闭源产品)竞相在最短的时间内添加更多数量的连接器,这意味着创新速度变慢(因为为每种产品做出贡献的人更少)和定制现有解决方案的可能性更少。异常亮点肯定是 Airbyte,这是该领域唯一一家从一开始就选择开源其核心产品的大公司,这使其能够迅速发展一个大型贡献者社区,并在其成立不到一年的时间内提供 120 多个连接器。 部署 Airbyte 对所有云提供商来说都是轻而易举的事[16]。在 GCP 上,我们将使用具有足够资源的 Compute Engine 实例。理想情况下希望通过 IaC 配置部署,这样可以更轻松地管理版本控制和自动化流程。(随附的存储库中提供了示例 Terraform 配置。) 一旦它启动并运行,我们只需要通过定义添加一个连接:

  • • Source:可以使用 UI 选择“文件”来源类型,然后根据数据集和上传数据的位置进行配置,或者可以利用 Airbyte 的 Python CDK[17] 构建一个新的 HTTP API 源,用于从您要使用的 API 中获取数据。
  • • Destination:这里只需要指定与数据仓库(在我们的例子中为“BigQuery”)交互所需的设置。

值得注意的是 Airbyte 目前专为批量数据摄取(ELT 中的 EL)而设计,因此如果正在构建一个事件驱动的平台,那么它不会成为选择之一。如果有这样的用例,那么可以选择 Jitsu[18],Segment[19] 的开源替代品。现在我们已经启动并运行了 Airbyte 并开始摄取数据,数据平台如下所示:

ELT 中管理 T:dbt

当想到现代数据栈时,dbt 可能是第一个想到的工具。该项目始于 2016 年(从一开始就是开源的)解决了当时普遍存在的问题:数据管道的版本控制不当、文档记录不完善,并且没有遵循软件工程的最佳实践。dbt 是第三次数据技术浪潮的理想典范,因为它代表了这一浪潮背后的主要目标:添加特性和功能以更轻松地管理现有数据平台,并从底层数据中提取更多价值。多亏了 dbt,数据管道(我们 ELT 中的 T)可以分为一组 SELECT 查询(称为“模型”),可以由数据分析师或分析工程师直接编写。然后此功能为数据血缘、版本控制、数据测试和文档等多种功能打开了大门。可以通过两种不同的方式设置 dbt 环境:

  • • dbt Cloud:这是由 dbt Labs 托管的基于 Web 的集成开发环境 (IDE)。该选项需要最少的工作量,但提供更多功能,如调度作业、CI/CD 和警报。值得注意的是它实际上对开发者计划是免费的。
  • • dbt CLI:此选项允许直接与 dbt Core 交互,无论是通过使用 pip 在本地安装它还是像之前部署的 Airbyte 一样在 Google Compute Engine 上运行 docker 映像。通过使用 CLI可以试验不同的 dbt 命令并在选择的 IDE 中工作。

要允许 dbt 与 BigQuery 数据仓库交互,需要生成所需的凭据(可以创建具有必要角色的服务帐户),然后在 profiles.yml 文件中指明项目特定的信息。这在 dbt Labs 的“入门[20]”教程中得到了很好的解释,该教程介绍了需要熟悉的所有概念。

现在可以享受数据乐趣了:您可以使用 dbt 来定义模型和它们之间的依赖关系。例如对于 F1 数据集,可以生成包含冠军数据(总积分、每场比赛的平均进站时间、整个赛季最快圈数、平均排位赛位置等)的 Championship_winners 模型。对于正在处理的任何数据集,当涉及到数据可以回答的问题时,您会发现无限可能性——这是一个很好的练习,可以让您在处理新数据集时感到更加自信。处理完模型后可以执行命令 dbt docs generate来生成项目的文档(目录和清单文件)。在完成 dbt 设置之后,我们现在拥有可以处理 ELT 流程的三个步骤的组件,架构如下所示:

当第一次介绍架构时,我们说过编排和数据监控/测试现在都可以由另一个组件处理——您可能已经猜到该组件是 dbt。使用 dbt Cloud可以管理管道的调度并定义不同的执行触发器(例如通过 webhook),而 dbt 还具有强大的基于 SQL 的测试功能,可以利用它来确保不会发现数据质量问题。

数据可视化:Apache Superset

现在我们已经处理了我们的数据并生成了可以提供见解的不同视图和表格,需要通过一组数据产品实际可视化这些见解。(如果你不熟悉这个词,这篇很棒的文章[21]对不同类型的数据产品进行了详尽的概述。) 这个阶段的目标是构建可以由我们的最终用户直接访问的仪表板和图表(无论是用于分析还是监控,取决于数据集)。BI 是少数几个没有被“第二次浪潮”数据技术打乱的领域之一,主要是因为 Hadoop 生态系统专注于大规模处理数据而不影响最终用户的消费方式。这意味着在很长一段时间内,BI 和数据可视化领域由专有工具(Tableau、PowerBI 和最近的 Looker)主导,缺乏开源项目,只有小众用例。然后是 Apache Superset。当 Airbnb 在 2016 年首次开源时,它通过提供企业级所需的所有功能,代表了现有 BI 工具的第一个开源真正替代品。如今由于其庞大的开源社区,它已成为“第三次浪潮”(以及 Metabase 和 Looker 等替代品)的领先技术之一。Superset 部署由多个组件组成(如专用元数据数据库、缓存层、身份验证和潜在的异步查询支持),因此为了简单起见,我们将依赖非常基本的设置。我们将再次利用 Google Compute Engine 来启动一个 Superset 实例,我们将在该实例上通过 Docker Compose 运行一个容器。本文随附的存储库中提供了必要的 Terraform 和 init 脚本。一旦 Superset 启动并运行,可以通过以下命令连接到实例:

gcloud --project=your-project-id beta compute ssh superset-instance -- -L 8088:localhost:8088 -N

登录到 Superset 实例后(通过官方文档中提供的步骤[22]),只需将其连接到 BigQuery[23] 即可开始与您的不同数据集进行交互。

建立连接后,您可以试验不同的图表类型、构建仪表板,甚至可以利用内置 SQL 编辑器向您的 BigQuery 实例提交查询。

现在我们可以通过 Superset 为最终用户提供对数据的直接访问,我们的数据平台如下所示:

在 Superset 的功能方面,上述我们只触及了皮毛,还可以管理访问角色[24]、利用缓存[25]、构建自定义可视化插件[26]、使用其丰富的 API[27],甚至强制执行行级访问策略[28]。此外通过 Preset[29],还可以选择一个托管版本而无需考虑部署。

技术栈的基石:OpenMetadata

元数据管理可能是数据社区存在最大分歧的领域,这是一个非常分散的空间(存在25 种工具并且还在增加[30]),不同的工具在如何解决这个问题上采取了截然不同的方法。在我个人看来 Uber 数据平台团队开源的产品 OpenMetadata[31] 在这个领域采取了正确的方法。通过专注于提供水平元数据产品,而不是仅仅成为架构中的一部分,它使集中式元数据存储成为可能。它有非常丰富的 API[32],强制执行元数据模式[33],并且已经有很长的连接器列表[34]。其他产品正在实施自己的元数据管理方式,并且是在闭门造车的情况下这样做,这会在将它们添加到我们的平台时造成不必要的开销,而 OpenMetadata 专注于为其他产品可以与之交互的元数据提供单一真实来源它的 API。通过将其添加到架构中,数据发现和治理成为必然,因为它已经具备实现这些目标所需的所有功能。如果您想在将其添加到平台之前了解它的功能,可以先探索它的沙箱[35]。与 Airbyte 和 Superset 一样,我们将通过 Google Compute Engine 实例部署 OpenMetadata(与往常一样,随附的存储库中提供了 Terraform 和 init 脚本)。部署完成后会注意到虚拟机上实际上运行了四个容器,用于以下目的:

  • • 在 MySQL 上存储元数据目录
  • • 通过 Elasticsearch 维护元数据索引
  • • 通过 Airflow 编排元数据摄取
  • • 运行 OpenMetadata UI 和 API 服务器

OpenMetadata 在后台尽职尽责地管理这些组件,而无需进行任何配置,因此我们可以立即开始像任何其他产品一样使用它,启动并运行后可以首先通过以下命令连接到 Airflow 端口:

gcloud --project=your-project beta compute ssh openmetadata-instance -- -L 8080:localhost:8080 -N

然后可以通过 http://localhost:8080/ 访问 Airflow UI(用户名:admin,密码:admin)。您会注意到一些 DAG 已经运行以加载和索引一些示例数据。之后通过以下命令连接到 OpenMetadata UI(然后可以通过 http://localhost:8585/ 访问该 UI):

gcloud --project=your-project beta compute ssh openmetadata-instance -- -L 8585:localhost:8585 -N

现在可以通过 SSH 登录 GCE 实例,并将 OpenMetadata 连接到 BigQuery[36]、BigQuery 使用数据[37]、dbt[38] 和 Superset[39]。然后可以探索其不同的特性和功能,例如数据发现和血缘。

现在已经将 OpenMetadata 添加到了平台中,来看看我们最终的架构:

提升到新水平:可选组件

在文章开头我们提到了两个可选组件:编排和数据监控。理论上这对于数据平台来说是两个非常重要的功能,但正如我们所见,dbt 在这个阶段可以很好地实现它们。尽管如此让我们讨论一下如何在需要时集成这两个组件。

编排管道:Apache Airflow

当平台进一步成熟,开始集成新工具和编排复杂的工作流时,dbt 调度最终将不足以满足我们的用例。一个简单的场景是在更新特定的 dbt 模型时使 Superset 缓存失效——这是我们仅通过 dbt Cloud 的调度无法实现的。自 2015 年 Airbnb 开源以来,Airflow 一直是数据工作流编排领域的首选工具。这使其成为多家科技公司大型数据平台不可或缺的一部分,确保了一个大型且非常活跃的开放式围绕它的源社区——这反过来又帮助它在编排方面保持了标准,即使在“第三次浪潮”中也是如此。应该推迟考虑 Airflow(或其替代方案)的原因是专用编排工具带来的额外复杂性。Airflow 以自己的方式处理问题,为了能够充分利用它,需要做出妥协并调整工作流程以匹配其特性。在集成编排工具时还应该考虑如何触发管道/工作流,Airflow 支持基于事件的触发器(通过传感器[40]),但问题很快就会出现,使您仅仅因为该工具而适应您的需求,而不是让该工具帮助您满足您的需求。

数据监控:Soda SQL

就像编排一样,数据监控(最终我们将考虑数据可观测性)是 dbt 最终将停止为我们的平台处理需求。我们不只是验证 dbt 模型的数据,而是希望在整个平台上跟踪数据问题,以便可以立即确定特定问题的来源并相应地修复它。与数据集成一样,数据可观测性是公司仍然采用闭源方法,这不可避免地减缓创新和进步。另一方面有两种开源产品可以满足我们实现这一目标的大部分需求:Soda SQL[41] 和 Great Expectations[42]。Soda SQL 是一个很好的开始,因为它不需要太多投资,而且提供了多种方便的功能,基本上只需要几个 YAML 文件即可启动和运行,然后可以定义自定义测试[43]和编排扫描[44]。

接下来是什么?

这是一段漫长的过程,我们经历了不同的技术——其中一些是我们正在目睹的“第三次浪潮”的产品,而另一些则是经过时间考验的“第二次浪潮”老手,在这一点上的主要收获是构建一个功能齐全的数据平台比以往任何时候都更容易——如果你跟着实施,你会发现自己在不到一个小时的时间内就构建了一个现成的现代数据平台。当然现代数据栈仍然是分散的,押注我们讨论的某些技术可能是一个冒险的决定。除了 dbt 之外,没有任何现代数据栈工具在其所做的事情上是明显的赢家,因此生态系统将在未来几年通过整合和竞争不断变化,不过可以肯定的是激动人心的时代即将到来。

引用链接

[1] 4V: [https://bernardmarr.com/what-are-the-4-vs-of-big-data/](https://bernardmarr.com/what-are-the-4-vs-of-big-data/) [2] GitHub 存储库: [https://github.com/mahdiqb/modern_data_platform](https://github.com/mahdiqb/modern_data_platform) [3] GCP 免费试用: [https://cloud.google.com/free](https://cloud.google.com/free) [4] Kaggle 下载: [https://www.kaggle.com/rohanrao/formula-1-world-championship-1950-2020](https://www.kaggle.com/rohanrao/formula-1-world-championship-1950-2020) [5] Ergast HTTP API: [http://ergast.com/mrd/](http://ergast.com/mrd/) [6] 世界发展指标: [https://datacatalog.worldbank.org/search/dataset/0037712](https://datacatalog.worldbank.org/search/dataset/0037712) [7] Snowflake: [https://www.snowflake.com/](https://www.snowflake.com/) [8] BigQuery: [https://cloud.google.com/bigquery/](https://cloud.google.com/bigquery/) [9] Redshift: [https://aws.amazon.com/redshift/](https://aws.amazon.com/redshift/) [10] 其背后的设计: [https://cloud.google.com/blog/products/data-analytics/new-blog-series-bigquery-explained-overview](https://cloud.google.com/blog/products/data-analytics/new-blog-series-bigquery-explained-overview) [11] 创建一个数据集: [https://cloud.google.com/bigquery/docs/datasets](https://cloud.google.com/bigquery/docs/datasets) [12] 分区: [https://cloud.google.com/bigquery/docs/partitioned-tables](https://cloud.google.com/bigquery/docs/partitioned-tables) [13] 物化视图: [https://cloud.google.com/bigquery/docs/materialized-views-intro](https://cloud.google.com/bigquery/docs/materialized-views-intro) [14] 将 BigQuery 审计日志存储在专用数据集中: [https://cloud.google.com/architecture/building-a-bigquery-data-lineage-solution#setting_the_environment](https://cloud.google.com/architecture/building-a-bigquery-data-lineage-solution#setting_the_environment) [15] 附加说明: [https://github.com/GoogleCloudPlatform/bigquery-utils/tree/master/views/audit#getting-started-with-bigquery_audit_logs_v2sql](https://github.com/GoogleCloudPlatform/bigquery-utils/tree/master/views/audit#getting-started-with-bigquery_audit_logs_v2sql) [16] 部署 Airbyte 对所有云提供商来说都是轻而易举的事: [https://docs.airbyte.io/deploying-airbyte](https://docs.airbyte.io/deploying-airbyte) [17] Airbyte 的 Python CDK: [https://docs.airbyte.io/connector-development/cdk-python](https://docs.airbyte.io/connector-development/cdk-python) [18] Jitsu: [https://jitsu.com/](https://jitsu.com/) [19] Segment: [https://segment.com/](https://segment.com/) [20] 入门: [https://docs.getdbt.com/tutorial/setting-up](https://docs.getdbt.com/tutorial/setting-up) [21] 很棒的文章: [https://towardsdatascience.com/designing-data-products-b6b93edf3d23](https://towardsdatascience.com/designing-data-products-b6b93edf3d23) [22] 通过官方文档中提供的步骤: [https://superset.apache.org/docs/installation/installing-superset-using-docker-compose#4-log-in-to-superset](https://superset.apache.org/docs/installation/installing-superset-using-docker-compose#4-log-in-to-superset) [23] 连接到 BigQuery: [https://superset.apache.org/docs/databases/bigquery](https://superset.apache.org/docs/databases/bigquery) [24] 管理访问角色: [https://superset.apache.org/docs/security](https://superset.apache.org/docs/security) [25] 利用缓存: [https://superset.apache.org/docs/installation/cache](https://superset.apache.org/docs/installation/cache) [26] 构建自定义可视化插件: [https://superset.apache.org/docs/installation/building-custom-viz-plugins](https://superset.apache.org/docs/installation/building-custom-viz-plugins) [27] 丰富的 API: [https://superset.apache.org/docs/rest-api](https://superset.apache.org/docs/rest-api) [28] 强制执行行级访问策略: [https://superset.apache.org/docs/security#row-level-security](https://superset.apache.org/docs/security#row-level-security) [29] Preset: [https://preset.io/](https://preset.io/) [30] 25 种工具并且还在增加: [https://twitter.com/MahdiKarabiben/status/1439221748994650115](https://twitter.com/MahdiKarabiben/status/1439221748994650115) [31] OpenMetadata: [https://open-metadata.org/](https://open-metadata.org/) [32] 丰富的 API: [https://docs.open-metadata.org/openmetadata/apis/overview](https://docs.open-metadata.org/openmetadata/apis/overview) [33] 元数据模式: [https://docs.open-metadata.org/openmetadata/schemas](https://docs.open-metadata.org/openmetadata/schemas) [34] 很长的连接器列表: [https://docs.open-metadata.org/connectors](https://docs.open-metadata.org/connectors) [35] 沙箱: [https://docs.open-metadata.org/take-it-for-a-spin](https://docs.open-metadata.org/take-it-for-a-spin) [36] BigQuery: [https://docs.open-metadata.org/connectors/bigquery](https://docs.open-metadata.org/connectors/bigquery) [37] BigQuery 使用数据: [https://docs.open-metadata.org/connectors/bigquery-usage](https://docs.open-metadata.org/connectors/bigquery-usage) [38] dbt: [https://docs.open-metadata.org/connectors/dbt](https://docs.open-metadata.org/connectors/dbt) [39] Superset: [https://docs.open-metadata.org/connectors/superset](https://docs.open-metadata.org/connectors/superset) [40] 传感器: [https://airflow.apache.org/docs/apache-airflow/stable/concepts/sensors.html](https://airflow.apache.org/docs/apache-airflow/stable/concepts/sensors.html) [41] Soda SQL: [https://github.com/sodadata/soda-sql](https://github.com/sodadata/soda-sql) [42] Great Expectations: [https://github.com/great-expectations/great_expectations](https://github.com/great-expectations/great_expectations) [43] 自定义测试: [https://docs.soda.io/soda-sql/tests.html#example-tests-using-custom-metrics](https://docs.soda.io/soda-sql/tests.html#example-tests-using-custom-metrics) [44] 编排扫描: [https://docs.soda.io/soda-sql/orchestrate_scans.html](https://docs.soda.io/soda-sql/orchestrate_scans.html)

0 人点赞