Google cloud platform 如何在使用Google数据流处理数据时报告无效数据?
我正在查看和,以了解如何在使用Google的处理数据时报告无效数据 除了实际的In-/output之外,我还想生成第二个输出文件,其中包含被视为无效的记录(例如数据丢失、数据格式错误、值过高)。我想对这些记录进行故障排除,并单独处理它们Google cloud platform 如何在使用Google数据流处理数据时报告无效数据?,google-cloud-platform,google-cloud-dataflow,Google Cloud Platform,Google Cloud Dataflow,我正在查看和,以了解如何在使用Google的处理数据时报告无效数据 除了实际的In-/output之外,我还想生成第二个输出文件,其中包含被视为无效的记录(例如数据丢失、数据格式错误、值过高)。我想对这些记录进行故障排除,并单独处理它们 输入:gs://…/Input.csv 输出:gs://…/Output.csv 无效记录列表:gs://…/invalid.csv 如何将这些无效记录重定向到单独的输出?您可以使用从单个转换返回多个PCollection。比如说, TupleTag<
- 输入:gs://…/Input.csv
- 输出:gs://…/Output.csv
- 无效记录列表:gs://…/invalid.csv
TupleTag<String> mainOutput = new TupleTag<>("main");
TupleTag<String> missingData = new TupleTag<>("missing");
TupleTag<String> badValues = new TupleTag<>("bad");
Pipeline p = Pipeline.create(options);
PCollectionTuple all = p
.apply(TextIO.Read.named("ReadMyFile").from(options.getInput()))
.apply(new SomeTransformation());
all.get(mainOutput)
.apply(TextIO.Write.named("WriteMyFile").to(options.getOutput()));
all.get(missingData)
.apply(TextIO.Write.named("WriteMissingData").to(...));
...
TupleTag main输出=新的TupleTag(“main”);
TupleTag missingData=新TupleTag(“缺失”);
TupleTag badValues=新的TupleTag(“坏”);
Pipeline p=Pipeline.create(选项);
PCollectionTuple all=p
.apply(TextIO.Read.named(“ReadMyFile”).from(options.getInput())
.apply(新的SomeTransformation());
all.get(主输出)
.apply(TextIO.Write.named(“WriteMyFile”).to(options.getOutput());
all.get(丢失数据)
.apply(TextIO.Write.named(“WriteMissingData”).to(…);
...
PCollectionTuple可以直接从现有的PCollections中构建,也可以从带有侧输出的ParDo操作中发出,例如
PCollectionTuple partitioned = input.apply(ParDo
.of(new DoFn<String, String>() {
public void processElement(ProcessContext c) {
if (checkOK(c.element()) {
// Shows up in partitioned.get(mainOutput).
c.output(...);
} else if (hasMissingData(c.element())) {
// Shows up in partitioned.get(missingData).
c.sideOutput(missingData, c.element());
} else {
// Shows up in partitioned.get(badValues).
c.sideOutput(badValues, c.element());
}
}
})
.withOutputTags(mainOutput, TupleTagList.of(missingData).and(badValues)));
PCollectionTuple partitioned=input.apply(ParDo
。of(新DoFn(){
公共void processElement(ProcessContext c){
如果(选中OK(c.元素()){
//显示在partitioned.get(mainOutput)中。
c、 产出(……);
}else if(hasMissingData(c.element())){
//显示在partitioned.get(missingData)中。
c、 sideOutput(missingData,c.element());
}否则{
//显示在partitioned.get(badValues)中。
c、 sideOutput(badValues,c.element());
}
}
})
.withOutputTags(main输出,TupleTagList.of(missingData.)和(badValues));
请注意,一般情况下,各种边输出不需要具有相同的类型,并且数据可以多次发送到任意数量的边输出(而不是我们这里的严格分区)
然后,您的SomeTransformation类可以如下所示
class SomeTransformation extends PTransform<PCollection<String>,
PCollectionTuple> {
public PCollectionTuple apply(PCollection<String> input) {
// Filter into good and bad data.
PCollectionTuple partitioned = ...
// Process the good data.
PCollection<String> processed =
partitioned.get(mainOutput)
.apply(...)
.apply(...)
...;
// Repackage everything into a new output tuple.
return PCollectionTuple.of(mainOutput, processed)
.and(missingData, partitioned.get(missingData))
.and(badValues, partitioned.get(badValues));
}
}
类SomeTransformation扩展了PTransform{
公共PCollectionTuple应用(PCollection输入){
//过滤好的和坏的数据。
PCollectionTuple分区=。。。
//处理好数据。
PCollection已处理=
partitioned.get(main输出)
.apply(…)
.apply(…)
...;
//将所有内容重新打包到新的输出元组中。
返回PCollectionTuple.of(主输出,已处理)
.和(丢失数据,分区.get(丢失数据))
.和(badValues,partitioned.get(badValues));
}
}
Robert关于使用SideOutput的建议很好,但请注意,只有当您的ParDos识别出坏数据时,这才有效。目前还没有一种方法可以识别在初始解码过程中命中的坏记录(在Coder.decode中命中错误)。我们计划很快解决这一问题
class SomeTransformation extends PTransform<PCollection<String>,
PCollectionTuple> {
public PCollectionTuple apply(PCollection<String> input) {
// Filter into good and bad data.
PCollectionTuple partitioned = ...
// Process the good data.
PCollection<String> processed =
partitioned.get(mainOutput)
.apply(...)
.apply(...)
...;
// Repackage everything into a new output tuple.
return PCollectionTuple.of(mainOutput, processed)
.and(missingData, partitioned.get(missingData))
.and(badValues, partitioned.get(badValues));
}
}