我在apache beam [python]中有一个正在工作的流传输管道,该管道从pub / sub提取数据,对数据流进行丰富处理并将其传递给big-query。
对于流媒体窗口,我想确保消息不会重复(因为pub / sub至少保证一次传递)。
因此,我认为我只会使用与Beam不同的方法,但是一旦使用它,我的管道就会中断(无法继续进行,任何本地打印内容也不可见)。
这是我的管道代码:
with beam.Pipeline(options=options) as p:
message = (p | "ReadFromPubSub" >> beam.io.ReadFromPubSub(topic=known_args.topic).
with_output_types(bytes))
bq_data = (message | "Decode" >> beam.FlatMap(lambda x: [x.decode('utf-8')])
| "Deduplication" >> beam.Distinct()
| "JSONLoad" >> beam.ParDo(ReadAsJSON())
| "Windowing" >> beam.WindowInto(window.FixedWindows(10, 0))
| "KeepRelevantData" >> beam.ParDo(KeepRelevantData())
| "PreProcessing" >> beam.ParDo(PreProcessing())
| "SendLimitedKeys" >> beam.ParDo(SendLimitedKeys(), schema=schema)
)
if not known_args.local:
bq_data | "WriteToBigQuery" >> beam.io.WriteToBigQuery(table=known_args.bq_table, schema=schema)
else:
bq_data | "Display" >> beam.ParDo(Display())
您会在重复数据删除标签中看到,我正在调用beam.Distinct方法。
问题:
重复数据删除应该在哪里进行?
这甚至是正确/理智的方法吗?
我还能如何删除流缓冲区数据的重复项?
是否甚至需要重复数据删除,还是我只是在浪费时间?
任何解决方案或建议将不胜感激。谢谢。
答案 0 :(得分:2)
您可能会发现Exactly-once processing上的此博客很有帮助。首先,Dataflow已经基于发布/订阅记录ID执行重复数据删除。但是,如博客所述:“但是,在某些情况下,这还不够。用户的发布过程可能会重试发布。”
因此,如果将消息发布到Pub / Sub的系统可能多次发布同一条消息,则您可能希望添加自己的确定性记录ID。然后,Cloud Dataflow将检测到这些。这是我建议的方法,而不是尝试在自己的管道中进行重复数据删除。
您可以通过使用PubSubIO.Read上的withIdAttribute来执行此操作。 Example。
关于为什么我认为“相异”会导致卡住的一些解释。 Distinct尝试对窗口中的数据进行重复数据删除。我相信您正在尝试对全局窗口进行重复数据删除,因此您的管道必须缓冲并比较所有元素,并且由于这是无界的PCollection。它将尝试永久缓冲。
我认为,如果您先执行窗口化,并且具有确定性的事件时间戳(看起来不像您正在使用withTimestampAttribute),则此方法将正常工作。然后,Distinct将仅应用于窗口内的元素(并且具有相同时间戳的相同元素将放置在同一窗口中)。您可能想看看这是否适用于原型,但我建议尽可能添加唯一的记录ID,并允许Dataflow根据记录ID处理重复,以实现最佳性能。