跳到正文
RadarAI· Databricks:Blog(RSS)·· 3 小时前AI 评分24

Eclipse Aerospace 用 Databricks PySpark 自定义数据源简化飞行数据接入

AI 导读

Eclipse Aerospace 借助 Databricks PySpark 自定义数据源,将近 20 年、超 3TB 的专有飞行数据直接接入 Spark 分析,省去 AWS Lambda 中转解码环节。

正文 · AI 翻译

Databricks:Blog·2026-11-13 03:20· 1 小时前AI 评分48

Eclipse Aerospace 借助 Databricks 简化飞行数据接入

AI 导读

Eclipse Aerospace 借助 Databricks 的 PySpark 自定义数据源,将近 20 年、超 3TB 的专有飞行数据直接接入 Spark 分析,省去 AWS Lambda 中转解码环节。

正文 · 原文

随着航空航天、制造业、生命科学等数据密集型行业的企业推进运营现代化,它们正将更多传感器、遥测和科学数据引入数据平台。但这些数据中有很大一部分难以大规模使用,因为它们以主流分析引擎无法直接读取的专用或专有格式存储。这带来了一个现实的行业挑战:团队必须在构建缓慢、内存密集的自定义转换,维护专用连接器,或在数据可分析之前增加额外的解码阶段之间做出选择。

PySpark 自定义数据源提供了一条更简单的路径。它让团队能够使用 Python 将专用格式引入 Spark,而无需从零构建单独的连接器。对于轻型公务机制造商和运营商 Eclipse Aerospace 而言,与 Databricks 合作提供了一种方式,让服务中心和工程师能够更便捷地访问近二十年的专有飞行数据,而无需增加昂贵的常开基础设施。Databricks 提供了无服务器数据平台和 Spark 集成,而 Eclipse Aerospace 贡献了其现有的飞行数据解码器和航空航天专业知识。

Eclipse Aerospace 与 Databricks 共同开发了一条从飞行数据到分析的更直接路径,减少了此前多阶段流程的延迟、重复和运营开销,同时保留了 Databricks Serverless 的灵活性。

Eclipse Aerospace 的数据接入挑战

Eclipse Aerospace 依赖 Databricks 存储近 20 年的飞行数据,总量超过 3TB。它利用来自超过一百万飞行小时的数据为服务中心和工程师提供支持,这些数据从多个来源获取并验证,包括:近实时卫星遥测;完整飞行历史的大批量上传;以及外部数据源。其所有遥测数据都以需要自定义解码器的专有文件格式存储,这些解码器已用多种语言开发,包括 Rust 和 Scala。

在 Databricks Runtime 15.4 LTS 中提供 Pyspark 自定义数据源之前,Eclipse Aerospace 团队有三种可行方案来解码其专有文件类型并将其加载到 Databricks 中:

  1. 将文件作为二进制类型加载,并使用 Python 用户定义函数(UDF)进行拆分
  2. 在专用计算资源上使用 Scala 自定义解码器
  3. 在加载到 Databricks 之前将文件解码为中间文件类型

对于简单的自定义文件类型,UDF 是一种自然的选择。它们以性能换取可读性。然而,当消息格式为可变长度时,UDF 存在长消息导致内存耗尽的实际风险,因此无法使用。现有的 Scala 解码器可用于实现原生 Data Source v1/v2,但在 Databricks 中使用它需要专用计算资源。用户期望能够快速上传和查看数据,这需要保持该计算资源始终开启,其成本高于其他无服务器选项。这使得团队只剩下最后一个选项:通过 AWS Lambda 上基于 Rust 的解码器,将文件解码为中间文件格式,在本例中为 Avro。

该方案成本低,但它:

  • 引入了多跳摄取模式带来的延迟
  • 在 Lambda 解码器与消费 Avro 输出的下游 Spark 作业之间重复了 schema 逻辑
  • 牺牲了团队的管道可观测性;Spark UI 和作业指标只能看到从 Avro 落地区开始的世界,因此调试缓慢或失败摄取的工程师不得不去平台完全不同的部分查找 Lambda 日志
  • 意味着需要为存储原始二进制文件及其 Avro 副本付费

为什么 Databricks 和 PySpark 自定义数据源很重要

Databricks 已经是 Eclipse Aerospace 存储和处理飞行数据的平台。决定性优势在于 Spark 原生执行、PySpark 自定义数据源和 Databricks Serverless 的结合。Databricks Serverless 自动分配和管理按需计算,因此 Eclipse Aerospace 无需预置或保持专用基础设施运行。PySpark 自定义数据源使得无需构建 JVM 连接器即可包装现有的 Rust 解码器。由于解码现在在 Spark 内运行,同一平台提供了 Spark UI、作业指标和下游 Delta 工作流,而不是将关键摄取步骤交给单独的 Lambda 管道。

大多数数据工程依赖常见的数据格式,但一些最有价值的数据仍隐藏在 PySpark 无法直接访问的格式中,例如用于科学数据的 HDF5 和用于航空航天数据的 ARINC 429 等行业标准。Databricks Serverless 为团队提供了一种灵活的方式来大规模解锁这些数据,而基于 Rust 的实现可以提供超越纯 Python 方法的性能。

PySpark 自定义数据源允许你用纯 Python 定义可读写的文件格式,像任何其他数据源一样使用。其主要优势是简单性,让用户可以用纯 Python 定义读写函数,并定义并行化等重要特性。Eclipse Aerospace 团队更进一步:通过构建基于 Rust 的 Python 包,它实现了类似基于 PyArrow 的纯 Python 数据源基准性能的两倍。与不使用 Arrow 的原生 Python 实现相比,它提供了近 20 倍的性能。

以下示例代码仓库演示了针对 ARINC 429 的自定义数据源。随附代码包含本文范围之外的设计决策,以及你可以自行运行的基准测试。

这如何通过 PySpark 自定义数据源变得可解决

Apache Spark 4.0 发布了 Python 数据源 API(在 Databricks 文档中称为 PySpark 自定义数据源),允许你为批处理或流数据注册自定义格式,例如:

该 API 在 Apache Spark 4.0 中引入并在 Databricks 上可用,从 Databricks Runtime 15.4 LTS 起正式可用,并且也在 Serverless 环境 2 及更高版本上受支持。由于该 API 用 Python 实现,它不需要单独的 JVM 连接器或 JAR。

该 API 是创建原生数据源的简化接口,用户实现几个类并通过以下方式注册它们:

这些解码器有两种形式:原生 Python 和 Apache Arrow 格式,后者是性能高得多的选择。Apache Arrow 是一种“用于平面和嵌套数据的语言无关列式内存格式”,使其成为不同语言共享数据对象之间的理想接口。该 API 利用这一点,允许用户直接返回 pyarrow.RecordBatch 对象,Spark 会以批次方式消费它们,而不是每行物化一个 InternalRow。

这引出了一个问题:能否让 Python 作为控制层,由 Rust 承担解码的重任,同时全程保持 Apache Arrow 格式?

解决方案架构概览

其背后的架构是一个单一的逻辑连接器,其解码路径几乎完全由编译代码构成,而 Python 层足够薄,对 Eclipse Aerospace 现有的 Rust SDK 改动极小。这个薄 Python 层使用 PyO3/Maturin 构建为独立包,导入管道后就像任何其他数据源一样使用。为确保最佳性能和关注点分离,团队遵循了几条架构原则。

image1.png

解码器不知道 Spark 的存在。核心 Rust crate 不依赖 PyO3、Arrow 或 Spark,只接收字节并返回结构化记录。这使得 Eclipse Aerospace 能够基本原封不动地移植现有的解码逻辑,因为 SDK 无需为此重写,只需包装。

Arrow 是唯一跨越外部函数接口(FFI)边界的东西,而且它跨越边界时不发生复制。Rust 胶水层使用 arrow-rs 构建一个 Arrow RecordBatch,然后通过 Arrow C Data Interface 将其作为 pyarrow.RecordBatch 交给 Python。在此过程中没有序列化步骤,因为不会重新编码字节,也不会构建逐行的 Python 对象。Rust 分配的缓冲区就是 Python 读取的缓冲区。

PySpark 层有意保持轻量。它解析选项、决定如何分区(在参考示例中每个输入一个 InputPartition),并定义 schema。在 PySpark 自定义数据源中,DataSource、DataSourceReader 及其流式等价物都必须可序列化,这样 Spark 才能 pickle 读取器实例并将其发送到 worker。通过让 PySpark 层保持轻量,Spark pickle 并发送到 worker 的 DataSourceReader 实例只持有纯 Python 状态(文件路径、表示批次大小的整数)。由 PyO3 支持的 Rust 对象在 read() 内部构造,此时读取器已经到达 worker。它本身永远不会成为被 pickle 的内容的一部分。

原生代码以 Python wheel 形式发布,使用 Maturin 构建。在 Databricks 上,该 wheel 是一个构建产物,作为普通 Python 依赖附加到作业或笔记本环境。由于实现是编译的,版本和架构兼容性需要谨慎处理,不过正如示例仓库所示,适当的 CI/CD 流程可以管理这一点。

连接器如何在 Databricks 中运行

在 Databricks Serverless 上,运行时路径很直接:

  1. 一个专有遥测文件落到云存储中。
  2. Databricks Spark 读取调用为该自定义格式注册的 PySpark 自定义数据源。
  3. 在 Databricks 上运行的 Spark 创建一个包含输入路径和读取选项的可序列化读取器,然后在 worker 上调度输入分区。
  4. 每个 worker 在 read() 内构建 Rust 解码器,并将文件字节传递给编译后的解码器。
  5. Rust 通过 Arrow C Data Interface 返回 Arrow RecordBatch,避免了序列化和逐行的 Python 对象。
  6. 运行在 Databricks 上的 Spark 消费这些批次,并将解码后的数据写入 Delta 等下游表。
  7. 解码错误、坏记录、Spark UI 阶段和作业指标在 Databricks 工作流中仍然可见。

这是与之前设计的关键区别:原始文件作为 Spark 读取的一部分被解码,而不是先复制到中间的 Avro 着陆区。

这对 Eclipse Aerospace 产生了什么影响

image2.png

通过用单次 Spark 原生读取取代多阶段的 Lambda 和 Avro 工作流,Eclipse Aerospace 更快地提供飞行数据,同时减少了基础设施、存储和运维开销。新的 Arrow 原生 PySpark 自定义数据源连接器还将解码引入 Spark,提高了对管道性能的可见性,并允许在一个地方管理 schema 和数据质量逻辑。

实现自定义数据源显著简化了 Eclipse Aerospace 的基础设施,其效果体现在四个不同的方面:延迟、成本、可观测性和工程时间。

延迟。 将多跳管道(上传、Lambda、解码、写入 Avro、读取 Avro、加载到 Delta)合并为单次 Spark 原生读取,消除了多个网络跳转以及文件在队列中等待下一阶段拾取的多个环节。新连接器可以在文件上传后一分钟内处理记录(包括启动时间),并且由于并行性,通常可以在两分钟内并行处理大型、数 GB 的批次。

成本。 移除 Lambda 跳转和 Avro 中间层,消除了 Eclipse Aerospace 必须运行、监控和付费的一整层基础设施。他们不再需要为每次飞行存储两份副本(原始二进制文件及其 Avro 转换),在近二十年的保留飞行历史中,这是一笔可观的重复存储量。这意味着大多数文件仍保留在 AWS 的 Glacier 存储中,如果将来需要原始数据,可以轻松重复解码。

可观测性。 由于解码步骤现在发生在 Spark 内部,它会像作业的任何其他阶段一样出现在 Spark UI 和标准作业指标中。Eclipse Aerospace 使用自定义的 "badRecordsPath"(模仿 CSV/JSON 加载器)来捕获格式错误的数据,并维护广泛的数据质量管道,直接从解码器捕获统计信息。

工程时间。 Schema 逻辑过去被定义两次:一次在生成 Avro 的 Lambda 解码器中,另一次在消费它的下游 Spark 作业中。对消息格式的任何更改都意味着要在两个不同的代码库中更新两处,并且存在两个定义逐渐偏离的风险。使用单个带版本控制的连接器,schema 只需定义一次,紧挨着解码逻辑本身。这也意味着相同的架构模式——一个薄 Python DataSource 包装 Rust 解码器——现在可以复用于 Eclipse Aerospace 支持的其他专有格式,而不是必须为每种格式重新发明。

Eclipse Aerospace 的经验表明,如何将专用数据格式引入 Databricks,而无需围绕它们构建单独的摄取平台。通过将解码器保留在 Rust 中、使用 Python 作为集成层,并通过 Apache Arrow 传递记录,自定义数据源可直接在 Spark 中读取原始文件,并保持与 Databricks Serverless 灵活性的兼容。

对于处理专有或行业特定格式的团队来说,可复用的模式很简单。工程师可以将领域特定的解码逻辑保持在靠近源格式的位置,通过 PySpark 自定义数据源将其暴露出来,并让 Spark 处理分区、执行、可观测性和下游处理。

想要开始使用?请查看以下内容:

常见问题

什么是 PySpark 自定义数据源?

PySpark 自定义数据源是用 Python 实现的用户定义 Spark 数据源。它让团队能够作为标准 Spark 工作流的一部分读取专用文件格式,而无需构建单独的 JVM 连接器。

Arrow 原生 PySpark 自定义数据源连接器解决了什么数据摄取问题?

Arrow 原生 PySpark 自定义数据源连接器将专有飞行遥测数据摄取到 Databricks 中,而无需依赖多阶段管道、专用的常开计算资源或原始文件的重复 Avro 副本。

什么是 Databricks Serverless?

Databricks Serverless 是一种完全托管的计算服务,让您无需在云账户中预置或管理任何基础设施即可运行工作负载。Databricks 会为您自动分配、扩展和优化计算资源。

Databricks Serverless 如何连接到 Arrow 原生 PySpark 自定义数据源连接器?

该连接器使用 PySpark 自定义数据源在无服务器计算上的 Spark 内运行文件读取逻辑。Python 处理控制流,而 Rust 和 Apache Arrow 处理高性能解码和数据传输。这使得专有文件可以直接读取,而无需专用的常开计算资源或中间 Avro 管道。PySpark 自定义数据源在 Databricks Runtime 15.4 LTS 及更高版本,或无服务器环境版本 2 中可用。

来源:Databricks:Blog · databricks.com

来源:RadarAI · aihot.news