

在这篇文章中,我将对这种特定的数据处理模式进行深入研究,并探讨其数据管道结构和如何处理这些数据。
Apache Beam
Apache Beam是Apache的最新项目之一,是一个表达高效数据处理管道的综合编程模型。它是一个开源的、统一的模型,用于定义批处理和流式数据的并行处理管道。Apache Beam编程模型简化了大规模数据处理的机制。使用Apache Beam SDK中的一个,你可以建立一个定义管道的程序。
安装
本地
pip install apache-beam
谷歌云平台
pip install apache-beam[gcp]
亚马逊网络服务器
pip install apache-beam[aws]
什么是数据管道
它通过改变输入来封装信息处理任务。
一个Beam程序通常从创建一个Pipeline 对象开始。
在Beam SDKs中,每个管道由一个显式的Pipeline 类型的对象表示。每个Pipeline 对象是一个独立的实体,它封装了管道操作的数据和应用于该数据的转换。
要创建一个管道,需要声明一个Pipeline 对象,并传递给它一些配置选项。
// Start by defining the options for the pipeline.
PipelineOptions options = PipelineOptionsFactory.create();
// Then create the pipeline.
Pipeline p = Pipeline.create(options);
Apache Beam的特点
Apache Beam包括四个基本功能。
- 管线
- P-Collection
- P-Transform
- 运行器
一个Pipeline ,负责读取、处理和保存数据。这整个周期是一个流水线,从输入开始,一直到输出的整个循环。虽然,每个Beam程序都能生成一个Pipeline。
Beam的第二个特点是Runner 。它决定了这个管道将在哪里运行。
Beam的第三个特点是P-Collection ,它也相当于Spark中的RDD或DataFrames。该管道通过从数据源读取数据来创建一个PCollection ,之后,随着PTransform的应用,更多的PCollections不断发展。
每一个P-transform 在PCollection ,都会产生一个新的PCollection ,使其成为不可改变的。一旦构建完成,你将无法配置PCollection中的单个项目。PCollection 中的转换将导致一个新的PCollection 。PCollection 中的特征可以是任何类型的,但都必须是同类的。然而,为了保持散布式处理,Beam将每个元素编码为一个字节字符串,这样Beam就可以将项目传递给分布式工作者。
Beam SDK包也作为一个编码机制,用于支持自定义的编码的类型。此外,PCollection不支持颗粒化操作。由于这个原因,我们不能在PCollection中的一些特定项目上应用转换。我们使用所有的转换来应用于整个PCollection ,而不是某些方面。
PCollection中的时间戳
通常情况下,当项目被读取或添加时,源通常会给每个新元素分配一个时间戳。如果PCollection ,持有有边界的数据,我们可以强调每个特征都将被设置为相同的时间戳。你可以明确指定时间戳,或者Beam会提供自己的时间戳。在任何一种情况下,如果源不为我们做,我们可以手动分配时间戳给元素。
Beam的第四个功能是P-Transform 。它把一个样本PCollection 作为数据源,并产生一个相同的带有时间戳的PCollection。它们在进行窗口化、分配水印等操作时是平行操作的。
Beam的管道结构
在本节中,我将实现Beam的流水线结构。第一步从 "给管道分配一个名称 "开始,这是必须要做的一行代码。
pipeline1 = beam.Pipeline()
第二步是通过读取任何文件、流或数据库来`创建`初始PCollection 。
dept_count = (
pipeline1
|beam.io.ReadFromText(‘/content/input_data.txt’)
)
根据我们的用例,第三步是`应用`P-Transforms 。我们可以在这个管道中使用几个转换。一个管道操作者将应用每个转换。
dept_count = (
pipeline1
|beam.io.ReadFromText(‘/content/input_data.txt’)
|beam.Map(lambda line: line.split(‘,’))
|beam.Filter(lambda line: line[3] == ‘Backend’)
|beam.Map(lambda line: (line[1], 1))
|beam.CombinePerKey(sum)
)
要请求一个转换操作,你需要把它实现到输入PCollection 。对于每个转换,都存在一个非专有的应用方法。然而,我们可以用`.apply`或` |`管道操作符来使用apply操作。
在所有的转换之后,第四步是将最终的PCollection 写到一个外部源。它可以是一个文件,数据库,或流。
dept_count = (
pipeline1
|beam.io.ReadFromText(‘/content/input_data.txt’)
|beam.Map(lambda line: line.split(‘,’))
|beam.Filter(lambda line: line[3] == ‘Backend’)
|beam.Map(lambda line: (line[1], 1))
|beam.CombinePerKey(sum)
|beam.io.WriteToText(‘/content/output_data.txt’)
)
最后一步是运行管道。
pipeline1.run()
管线分支操作
大多数流水线只是代表了一个具有一对一映射的线性操作流。在第一个PCollection之后,一个过滤操作产生一个新的PCollection。在该PCollection上,一个映射转换在队列中创建额外的PCollection,直到它被写入一个文件。
然而,对于大多数的用例来说,我们的管道可以明显地复杂化和分支化。这种类型的流水线在Beam中被称为分支流水线,我们可以使用同一个PCollection作为多个转换的输入。


Beam中流数据管道的结构
Beam的核心思想是提供综合大数据处理管道。正如其官方文档中所述,其和谐的性质通过一个单一的API建立了批处理和流式管道。
当我们创建一个Pipeline ,我们还可以设置一些与之相关的配置选项,如管道运行器,它将执行我们的管道,以及所选运行器所需的任何运行器特定配置。
我们可以考虑通过硬编码来分配管道的配置偏好。不过,通常最好还是让它们从命令行中读取,然后传递给Pipeline 对象。出于这个原因,如果我们能够建立一个管道,从命令行中获取运行器信息、那些输入输出文件路径信息,那么我们的问题就解决了,可以说我们将获得一个通用的管道。
import apache_beam as beam
import argparse
from apache_beam.options.pipeline_options import
PipelineOptions,StandardOptions
parser = argparse.ArgumentParser()
parser.add_argument(‘ — input’, dest=’input’,
required=True,help=’/content/data.txt/’)parser.add_argument(‘ —
output’,dest=’input’,required=True, help=’/content/output.txt/’)
path_args, pipeline_args = parser.parse_known_args()
input_arguments = path_args.input
output_arguments = path_args.output
options = PipelineOptions(pipeline_args)
pipeline_with_options = beam.Pipeline(options = options)
dept_count = (pipeline_with_options
|beam.io.ReadFromText(input_arguments)
|beam.Map(lambda line: line.split(‘,’))
|beam.Filter(lambda line: line[3] == ‘AI’)
|beam.Map(lambda line: (line[1], 1))
|beam.io.WriteToText(output_arguments)
)
pipeline_with_options.run()
参考文献