Beam / DataFlow :: ReadFromPubSub(id_label)::意外行为

时间:2019-03-16 07:35:13

标签: python-2.7 google-bigquery google-cloud-dataflow apache-beam google-cloud-pubsub

有人可以澄清ReafFromPubSub transformid_label的目的是什么吗?

我正在使用BigQuery接收器,据我了解,它的作用类似于BQ Streaming API的insertId Tabledata: insertAll

  

每行的唯一ID。 BigQuery使用此属性来尽最大努力检测重复的插入请求。有关更多信息,请参见数据一致性。

但是我没有看到这种预期的行为。

  • 我正在将消息发布到Pub / Sub,每个消息具有相同的属性message_id值(这是为了测试管道/ BQ重复数据删除行为)

  • 我的管道从酒吧读取如下 beam.io.gcp.pubsub.ReadFromPubSub(topic=TOPIC, subscription=None, id_label='message_id'

但仍在查询BQ,将插入所有消息。我希望,因为发布的每个消息都具有相同的message_id值,所以BQ应该已经推导了这些消息。

有人可以澄清一下吗? 预先感谢!

此外,我注意到DirectRunner在使用此属性时会不断抛出错误

  

NotImplementedError:DirectRunner:PubSub读取不支持id_label

我必须使用DataflowRunner ...这也是预期的吗?

干杯!

UPDATE 1 :移至DataflowRunner,并且管道在ReadFromPubSub()期间似乎遵循id_label参数。 但是,重复的消息确实会继续偶尔散发到管道中

  • 我的发布者应用程序每15秒以以下格式(the publisher app code is here)发布消息:

    cid = 141&message_id = 2&evt_time = {{DATE_TIME_AT_RUNTIME}}

注意,我也在消息的属性中传递了相同的message_id值(=“ 2”)(这是为了尝试,通过测试来推断行为)。

    我的管道(在Dataflow Runner上运行,Beam Python v2.11 SDK,pipeline code is here)将以下消息转储到BQ。如您所见,具有相同message_id的多条消息被读入管道并发送到接收器。当我停止/重新启动发布者应用程序时,通常会发生这种情况。
cid=141&message_id=2&evt_time=2019-03-17T09:31:15.792653Z
cid=141&message_id=2&evt_time=2019-03-17T09:30:00.767878Z
cid=141&message_id=2&evt_time=2019-03-17T09:28:30.747951Z
cid=141&message_id=2&evt_time=2019-03-17T09:22:30.668764Z
cid=141&message_id=2&evt_time=2019-03-17T09:21:00.646867Z
cid=141&message_id=2&evt_time=2019-03-17T09:19:45.630280Z
cid=141&message_id=2&evt_time=2019-03-17T09:12:05.466953Z
cid=141&message_id=2&evt_time=2019-03-17T09:10:42.956195Z
cid=141&message_id=2&evt_time=2019-03-17T09:01:42.816151Z

1 个答案:

答案 0 :(得分:1)

这些是不同的ID。如here所述,发布到某个主题的每条消息都有一个名为messageId的字段,该字段在该主题内是唯一的。发布/订阅保证at-least-once delivery,因此订阅可以重复(即消息具有相同的messageId)。数据流具有exactly-once processing语义,因为数据流在从订阅中读取时使用该字段对消息进行重复数据删除。这与接收器无关,接收器不需要是BigQuery。

使用id_label(或Java SDK中的.withIdAttribute()),我们可以根据不同的唯一字段(例如订单ID,客户ID等)强制将消息视为重复消息。 。输入源只会读取重复的消息一次,您不会看到它们增加管道中输入元素的数量。请记住,直接运行程序仅用于testing,在检查点,重复数据删除等方面不能提供相同的保证。例如,请参考this comment。这就是为什么您在管道中看到它们的最可能原因,同时也考虑了NotImplementedError消息,因此建议您转到Dataflow Runner。

另一方面,在best-effort的基础上使用insertId来避免在BigQuery中重试流插入时出现重复的行。使用BigQueryIO会创建under the hood,无法手动指定。在您的情况下,如果您的N条消息进入管道,并且N条被写入BigQuery,则它按预期运行。如果必须重试,则该行具有相同的insertId,因此被丢弃。