BigQuery 数据提取中出现流错误导致不一致

BigQuery 数据提取中出现流错误导致不一致

在将数据传输到 BigQuery 时,我们在制作时遇到了一些数据提取不一致的问题https://cloud.google.com/bigquery/docs/reference/rest/v2/tabledata/insertAll使用 BigQuery Java 库的请求。

某些批次失败并显示错误代码:后端错误,而有些请求暂停异常堆栈跟踪:https://gist.github.com/anonymous/18aea1c72f8d22d2ea1792bb2ffd6139

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

  1. 该批次中的所有记录均无法提取到 BigQuery 中
  2. 只有部分记录无法提取到 BigQuery 中
  3. 尽管抛出了错误,但所有记录都成功被提取到 BigQuery 中

我们的问题是:

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

答案1

您在 Gist 中提供的错误是java.net.SocketTimeoutException: Read timed outHttpClient,当套接字操作在本地超时时,Java 会抛出该异常。它不是由 BigQuery 服务直接抛出的(尽管可能由于某些服务器端问题导致连接突然终止而间接导致)。

AbackendError有所不同 - 这将指示(通常)服务器暂时出现故障或远程发生其他错误情况,BigQuery 服务能够在保持连接打开的同时发出信号。

这两种错误都有可能发生在记录提取之前、之中或之后,这就是为什么您有时会看到没有记录、部分记录或所有记录都被写入。BigQuery非交易性,因此由于错误而发生部分插入。

因此,回答你的问题:

  1. 除了查询应该写入的数据并检查其是否存在之外,没有简单的方法可以区分这三种情况。由于流式插入是分批进行的,因此更简单的方法是退避并在失败的批次上重试,这可能会覆盖任何现有数据。这是insertId提供字段 - 以避免重复和确保数据一致性重试插入时。

  2. 从上面继续,您应该以相同的方式处理SocketTimeoutException和的所有情况backendError,即始终重试失败的批次并使用insertId以避免重复。

  3. 另外扩展一下1.,即使数据已经写入,任何超时或系统问题仍然可能发生,特别是在的情况下SocketTimeoutException

相关内容