直接流式传输到 BigQuery 与通过 Google Pub/Sub + Dataflow 流式传输的优缺点

Posted

技术标签:

【中文标题】直接流式传输到 BigQuery 与通过 Google Pub/Sub + Dataflow 流式传输的优缺点【英文标题】:Pros/cons of streaming into BigQuery directly vs through Google Pub/Sub + Dataflow 【发布时间】:2018-06-21 03:37:33 【问题描述】:

我们在 Google Kubernetes Engine 上托管了一个 NodeJS API,我们希望开始将事件记录到 BigQuery 中。

我可以看到 3 种不同的方法:

    使用 API 中的 Node BigQuery SDK 将每个事件直接插入 BigQuery(如“流式插入示例”下所述:https://cloud.google.com/bigquery/streaming-data-into-bigquery 或此处:https://github.com/googleapis/nodejs-bigquery/blob/7d7ead644e1b9fe8428462958dbc9625fe6c99c8/samples/tables.js#L367) 将每个事件发布到 Cloud Pub/Sub 主题,然后编写 Cloud Dataflow 管道以将其流式传输到 BigQuery(似乎仅在 Java 或 Python 中),例如此处 https://blog.doit-intl.com/replacing-mixpanel-with-bigquery-dataflow-and-kubernetes-b5f844710674 或此处 https://github.com/bomboradata/pubsub-to-bigquery 通过 API 将每个事件发布到 Pub/Sub 主题,但使用自定义工作进程代替 Dataflow,该进程一方面订阅 Pub/Sub 主题,另一方面将流式传输到 BQ。像这儿 : https://github.com/GoogleCloudPlatform/kubernetes-bigquery-python/blob/master/pubsub/pubsub-pipe-image/pubsub-to-bigquery.py 或在这里:https://github.com/mchon89/Google_PubSub_BigQuery/blob/master/pubsub_to_bigquery.py

对于这个特定的用例,我们不需要进行任何转换,只需将事件直接发送到正确的格式。但是我们以后可能会有其他用例,我们需要将表从我们的主数据存储 (mysql) 同步到 BQ 以进行分析,所以也许直接从 Dataflow 开始是值得的?

几个问题:

选项 1(将单个事件直接发送到 BQ)似乎是最简单的,如果您没有任何转换要做。是否和它一样快速和可靠 发布到 Pub/Sub 主题?我主要关心延迟 和错误/重复处理 (https://cloud.google.com/bigquery/troubleshooting-errors#streaming)。 也许这最好在一个单独的过程中完成? 对于选项 2,是否有任何数据流“预设”不需要您编写自定义代码,而您只需从 Pub/Sub 读取 + 可靠地发送到 BQ 而不进行任何转换(可能只是重复数据删除/错误处理) 让一个简单的自定义工作程序(选项 3)从 Pub/Sub 读取然后流入 BQ 并执行所有错误处理/重试等是否有任何缺点?

【问题讨论】:

如果没有某种生产者/消费者模式,即使用队列异步处理事件,选项 1 将无法扩展。您也将无法正确处理错误,即后退和重试。使用:App -> PubSub -> Dataflow (streaming) -> BigQuery。这是 Google 推荐的模式,也是最具容错性和可扩展性的模式。您还将获得连接到管道等的 Stackdriver 日志记录。 【参考方案1】:

我看了看这个,感觉答案有些欠缺。以下是我可以告诉您每种方法的优缺点:

    编写自定义程序(通过 Node BQ API 或自定义工作进程)在保证一次性保证方面存在一些陷阱。具体来说,如果您编写自己的工作进程,则需要执行额外的工作来检查点进度,并确保在运行时错误或工作进程死亡的情况下不会删除或重复任何元素。

    如果您的要求发生变化(例如,执行 BQ 流式插入变得过于昂贵),Dataflow 的 Java SDK 无缝支持任一选项:流式插入,或者在 BQ 中执行多个加载作业而不是更便宜流式插入;它还可以处理多个数据源。

    Dataflow 提供自动自动缩放,以防您的数据量增加。

考虑到这一点,我想说:

如果您的用例相对简单,并且您可以接受在工作程序重新启动时丢弃非常罕见的数据点,那么自定义编写的 Node / Python 应用程序应该可以为您解决问题。

如果您的用例仅涉及将 PubSub 流式传输到 BQ,但您必须确保没有数据丢失,请查看 Template provided by Andrew,它正是这样做的。

如果您的用例可能比这更复杂,您可以考虑编写自己的管道(并使用Template code as inspiration!)。

【讨论】:

【参考方案2】:

另一种选择是使用日志接收器导出日志。您可以直接在 Stackdriver Logging UI 中为您的日志指定 BigQuery(或其他目标)。由于您的 Node API 在 Kubernetes 中运行,您只需将消息记录到 stdout,它们就会自动写入 Stackdriver。

参考:https://cloud.google.com/logging/docs/export/configure_export_v2

【讨论】:

这是一个有趣的想法。我仍然想知道成本与其他解决方案相比如何,但这确实是需要考虑的事情。 这可能是最简单的开箱即用解决方案。这样做的主要成本是支付 Stackdriver Logging(存储)和创建接收器的任何额外成本(我没有看到任何定价信息)。我最初的感觉是,这比维护对 BigQuery 进行流式写入的流式 Dataflow 作业要便宜。 Stackdriver Logging 有一个基本层,其中包含免费日志记录。 Stackdriver 定价:cloud.google.com/stackdriver/pricing.【参考方案3】:

对于选项 2,是的,有一个称为 Google 提供的模板的预设,它有助于将数据从 PubSub 移动到 BigQuery,而无需编写任何代码。

您可以在Cloud Dataflow documentation 中了解有关如何使用此 Google 提供的模板和其他模板的更多信息。

【讨论】:

以上是关于直接流式传输到 BigQuery 与通过 Google Pub/Sub + Dataflow 流式传输的优缺点的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery - 通过 java 流式传输非常慢

将数据流式传输到BigQuery

将 JSON 流式传输到 Bigquery

使用 Java 将 JSON 流式传输到 BigQuery

Google BigQuery - 将数据流式传输到 BigQuery

使用 Express 将 BigQuery 流式传输到前端