BigQuery数据在stream式传输错误中的不一致性

在将数据stream式传输到BigQuery时,在使用BigQuery Java库制作https://cloud.google.com/bigquery/docs/reference/rest/v2/tabledata/insertAll请求时,我们所面临的数据不一致。

有些批处理会失败,出现错误代码: backendError ,而有些请求会超时 堆栈跟踪 : https : //gist.github.com/anonymous/18aea1c72f8d22d2ea1792bb2ffd6139

对于失败的批次,我们观察到3种不同的与摄取数据有关的行为:

  1. 该批次中的所有logging都无法被摄入到BigQuery中
  2. 只有部分logging无法被摄取到BigQuery中
  3. 尽pipe出现了错误,但所有logging都成功获取到BigQuery中

我们的问题是:

  1. 我们如何区分这三种情况呢?
  2. 对于情况2,我们如何处理部分摄取的数据,即哪批logging应该重试?
  3. 对于案例3,如果所有logging都被成功摄取,为什么会抛出错误? 提前致谢…

您在Gist中提供的错误是java.net.SocketTimeoutException : Read timed out ,当套接字操作在本地: Read timed out由Java HttpClient抛出。 它不是由BigQuery服务直接抛出(尽pipe可能是由于某些服务器端问题而突然终止连接)。

backendError是不同的 – 这将表示(通常)临时服务器故障或远程发生的其他一些错误情况,在保持连接打开的情况下,BigQuery服务能够发出信号。

这两个错误都可能发生在logging摄入之前,之中或之后,这就是为什么有时您不会看到logging,部分logging或所有logging被写入的原因。 BigQuery 不是事务性的 ,所以部分插入是由于错误而发生的。

所以要回答你的问题:

  1. 除了查询本应写入的数据并检查其存在之外,没有简单的方法来区分这三种情况。 由于stream式插入是批量完成的,因此在退出批处理后重新进行退出和重试操作要简单得多,可能会覆盖现有数据。 这是提供insertId字段的一个原因 – 为了避免重复,并确保重试插入时的数据一致性 。

  2. 从上面继续,你应该以同样的方式处理SocketTimeoutExceptionbackendError ,它总是重试失败的批处理,并使用insertId来避免重复。

  3. 同样扩展到1,甚至在写入数据之后,仍然可能发生任何超时或系统问题,特别是在SocketTimeoutException的情况下。