在BigQuery接收器中仅执行一次处理的情况下,改组是什么意思?

时间:2018-09-26 14:52:16

标签: google-bigquery apache-beam dataflow

我正在阅读关于article的一些数据流源和接收器实施的一次精确处理,而我在理解BigQuery接收器上的示例时遇到了麻烦。 摘自文章

  

生成随机UUID是一种不确定的操作,因此在插入BigQuery之前,我们必须添加 reshuffle 。完成此操作后,Cloud Dataflow进行的任何重试将始终使用改组后的相同UUID。重复插入BigQuery的尝试将始终具有相同的插入ID,因此BigQuery可以对其进行过滤

// Apply a unique identifier to each record
c
 .apply(new DoFn<> {
  @ProcessElement
  public void processElement(ProcessContext context) {
   String uniqueId = UUID.randomUUID().toString();
   context.output(KV.of(ThreadLocalRandom.current().nextInt(0, 50),
                                     new RecordWithId(context.element(), uniqueId)));
 }
})
// Reshuffle the data so that the applied identifiers are stable and will not change.
.apply(Reshuffle.of<Integer, RecordWithId>of())
// Stream records into BigQuery with unique ids for deduplication.
.apply(ParDo.of(new DoFn<..> {
   @ProcessElement
   public void processElement(ProcessContext context) {
     insertIntoBigQuery(context.element().record(), context.element.id());
   }
 });

改组是什么意思,它如何防止在后续重试中为同一插入生成不同的UUID?

2 个答案:

答案 0 :(得分:4)

重新排列以不同的方式对数据进行分组。但是,这里是因为它的副作用:检查点和重复数据删除。

不进行重新组合,如果同一任务生成UUID并将数据插入BigQuery,则存在工作线程重新启动的风险,新工作线程将生成新的UUID并将不同的行发送到BigQuery,从而导致重复的行。

重排操作将UUID生成和BigQuery插入分为两个步骤,并在它们之间插入检查点和重复数据删除。

  1. 首先,生成UUID并将其发送到改组。如果重新启动了UUID生成工作器,则可以,因为重新组合将对行进行重复数据删除,从而消除了失败/重新启动的工作器中的数据。
  2. 生成的UUID由随机操作检查点。
  3. BigQuery插入工作程序使用带有检查点的UUID,因此即使重新启动它-也会向BigQuery发送完全相同的数据。
  4. BigQuery使用这些UUID对数据进行重复数据删除,因此在BigQuery中消除了来自重新启动的插入工作程序的重复数据。

答案 1 :(得分:2)

我认为这篇文章很好地解释了为什么“改组”有助于从“至少一次”过渡到“恰好一次”:

  

具体来说,窗口可能会尝试使用元素e0,e1,e2触发,但是工作程序在提交窗口处理之前崩溃(但没有在发送这些元素作为副作用之前崩溃)。当工作程序重新启动时,该窗口将再次触发,但是现在出现了一个较晚的元素e3。由于此元素是在提交窗口之前显示的,因此不会算作最新数据,因此将使用元素e0,e1,e2,e3再次调用DoFn。然后将它们发送到副作用操作。幂等在这里无济于事,因为每次都发送不同的逻辑记录集。

     

还有其他方法可以引入非确定性。解决此风险的标准方法是依靠Cloud Dataflow当前保证 DoFn输出的一个版本只能使其经过混洗边界这一事实。

您还可以查看Reshuffle的文档:

这里有关于不推荐使用此类的说明,因此以后BigQueryIO的实现可能会有所不同。