什么是PCollection?
PCollection 代表一个分布式的数据集,你的Beam流水线在上面操作。该数据集可以是有界的,即它来自一个固定的来源,如文件,或无界的,即它来自一个通过订阅或其他机制不断更新的来源。你的管道通常通过从外部数据源读取数据来创建一个初始PCollection ,但你也可以在你的驱动程序中创建一个PCollection 形式的内存数据。从那里,PCollection,是你的管道中每个步骤的输入和输出。
什么是ParDo?
ParDo是一个用于并行处理的通用转换。它相当灵活,允许你执行日常数据处理任务。与MapElements转换不同的是,它为一个集合的每个输入元素产生一个确切的输出,ParDo给了我们很大的灵活性,因此我们可以为一个集合中的每个输入元素返回0或更多的输出。
例子
ParDo通过转换产生一个集合,其中只有计数大于100的词才会出现。频率较小的词将被丢弃。
public static void main(String args[]) {
PipelineOptions options = PipelineOptionsFactory.create();
Pipeline pipeline = Pipeline.create(options);
pipeline
.apply(TextIO.read().from("./words.txt"))
.apply(new CountWords())
.apply(ParDo.of(new DoFn<KV<String, Long>, KV<String, Long>>() {
@ProcessElement
public void processElement(@Element KV<String, Long> input, OutputReceiver<KV<String, Long>> outputReceiver) {
if(input.getValue() > 100) {
outputReceiver.output(input);
}
}
}))
.apply(MapElements.into(TypeDescriptor.of(String.class)).via(kv -> String.format("%s: %d", kv.getKey(), kv.getValue())))
.apply(TextIO.write().to("output"))
;
// run the pipeline and wait until the whole pipeline is finished
pipeline.run().waitUntilFinish();
}
我们添加了一个ParDo转换来丢弃计数<=100的词。为了应用ParDo,我们需要以DoFn的形式提供用户代码。DoFn应该指定输入元素的类型和输出元素的类型。在这种情况下,输入和输出都有相同的类型。
我们的用户代码将被放在一个用@ProcessElement注释的函数中。一个用@ProcessElement注释的函数将为输入集合中的每个元素执行。为了定义输入元素是什么,我们用@Element来注解参数。要发射一个输出,我们还需要指定一个OutputReceiver。如果我们不打算返回任何值,例如我们只打算把元素写到数据库中,我们可以放弃它。这不是@ProcessElement注释的函数的唯一签名。稍后,我们将看到如何产生多个PCollections作为输出,以及如何接受侧面输入(除当前正在处理的元素外的额外输入)。
结论
- 调用任何用户指定的函数
- 它的处理方法被逐一应用于数据集的每个元素
- 如果分配了不同的资源,数据集的元素可以被并行处理
- 被处理的元素保持其原始的时间戳和窗口
- 没有全局易变的状态--不可能在执行的函数之间共享一些易变的状态。事实上,它们被序列化,并以这样的方式发送到工作者那里。因此,即使它们引用了一些全局变量(作为集合),工作者将只收到这些变量的副本,而不是变量本身
- ParDo转换是 容错的,也就是说,如果它崩溃了,它会被重新运行。