在将数据stream式传输到BigQuery时,在使用BigQuery Java库制作https://cloud.google.com/bigquery/docs/reference/rest/v2/tabledata/insertAll请求时,我们所面临的数据不一致。
有些批处理会失败,出现错误代码: backendError ,而有些请求会超时 堆栈跟踪 : https : //gist.github.com/anonymous/18aea1c72f8d22d2ea1792bb2ffd6139
对于失败的批次,我们观察到3种不同的与摄取数据有关的行为:
我们的问题是:
您在Gist中提供的错误是java.net.SocketTimeoutException : Read timed out ,当套接字操作在本地: Read timed out由Java HttpClient抛出。 它不是由BigQuery服务直接抛出(尽pipe可能是由于某些服务器端问题而突然终止连接)。
backendError是不同的 – 这将表示(通常)临时服务器故障或远程发生的其他一些错误情况,在保持连接打开的情况下,BigQuery服务能够发出信号。
这两个错误都可能发生在logging摄入之前,之中或之后,这就是为什么有时您不会看到logging,部分logging或所有logging被写入的原因。 BigQuery 不是事务性的 ,所以部分插入是由于错误而发生的。
所以要回答你的问题:
除了查询本应写入的数据并检查其存在之外,没有简单的方法来区分这三种情况。 由于stream式插入是批量完成的,因此在退出批处理后重新进行退出和重试操作要简单得多,可能会覆盖现有数据。 这是提供insertId字段的一个原因 – 为了避免重复,并确保重试插入时的数据一致性 。
从上面继续,你应该以同样的方式处理SocketTimeoutException和backendError ,它总是重试失败的批处理,并使用insertId来避免重复。
同样扩展到1,甚至在写入数据之后,仍然可能发生任何超时或系统问题,特别是在SocketTimeoutException的情况下。