Google Cloud BigTable:更新列值

时间:2018-05-29 17:22:54

标签: google-cloud-dataflow apache-beam bigtable google-cloud-bigtable

我有一个示例的以下BigTable结构:

Table1 : column_family_1 : column_1 : value

value这里有一个数字,我们可以这么说。这是由数据流管理的,我想每次更新值。

此值可能是一个金额,我希望每次用户进行购买时更新它(以维持总花费到目前为止),所以我在购买事件监听器数据流中执行以下操作(每当遇到购买事件时):

  • 发出BigTable请求以获取id
  • 的值
  • 将新购买所花费的金额添加到BigTable搜索回复中的金额
  • 发出Put请求以更新值

虽然这种方法有一些网络延迟,但似乎有效。失败的情况是,当数据流有多个工作人员时,用户进行多次购买,并且事件发送给多个工作人员,例如:

  • 工人1获取事件1,获取金额并将花费的金额添加到其中
  • 工作人员2获取事件2,获取金额并将已花费的金额添加到其中
  • 两名工人发出Put次请求并被覆盖

为了防止这种情况发生,我正在努力提出一个只用纯文本add 10 to the spent amount value说的请求。这是我们可以在数据流中做些什么吗?

2 个答案:

答案 0 :(得分:4)

Bigtable具有Increment值的能力。您可以在protobuf documentation中查看更多详细信息。

Idempotency在理解Bigtable中的计数器方面起着重要作用。  在Bigtable中,Put s通常是幂等的,这意味着您可以多次运行它们并始终获得相同的结果(a=2将产生相同的结果,无论您运行多少次)。 Increment不是幂等的,因为多次运行会产生不同的结果(a++a++的结果与a++a++,{{不同1}})。

瞬态故障可能会也可能不会执行a++。客户端从来都不清楚Increment在这些瞬态错误期间是否成功。

由于这种幂等性,这个Increment功能在Dataflow中构建起来很复杂。 Dataflow有一个“捆绑”概念,它是一组充当工作单元的动作。这些捆绑包会针对瞬态故障进行重试(您可以阅读有关Dataflow瞬态故障重试here的更多信息)。 Dataflow将“捆绑”视为一个单元,因为Cloud Bigtable不支持多行事务,因此Cloud Bigtable必须将“捆绑”中的每个项目视为一个独特的事务。

鉴于“捆绑”的预期行为不匹配,Cloud Bigtable将不允许您通过数据流运行Increment

您所拥有的选项应该提供比我在此处提供的更多文档,但我可以提供一些高级别的选项:

  1. 始终对您找到的任何新事件使用Increment,并总结Reads上的值。您还可以通过创建删除所有当前值的“事务”来编写另一个定期清理行的作业,并使用总和写入新单元格

  2. 使用Cloud Functions来监听发布/订阅事件并执行Put。这是一个Cloud Bigtable example using Cloud Functions。您还可以执行Increment,执行添加并使用您在帖子中描述的算法执行Get(如果我选择此选项,我个人会选择CheckAndMutate来保持一致性选项)。

  3. 使用AbstractCloudBigtableTableDoFn编写自己的CheckAndMutate来执行DoFnIncrement,但要了解这可能会导致数据完整性问题。< / p>

  4. 如果系统足够大,选项#1是您最强大的选项,但会以系统复杂性为代价。如果您不想要这种复杂性,那么选项#2是您的下一个最佳选择(尽管我会选择CheckAndMutate)。如果您不关心数据完整性并且需要高吞吐量(例如“页数”或其他可能在一小部分时间内出错的遥测),那么选项#3将是您最好的选择。< / p>

答案 1 :(得分:2)

另一种解决方案可能如下:

  • 使一个仅附加表包含单个事件,以及一个聚合表,其中包含要聚合的相关键和值。
  • 使用AbstractCloudBigtableTableDoFn在仅附加表中执行Put插入。
  • 在同一数据流的连续阶段,在合理的短时间内(5秒?)内的窗口事件按聚合键分组。
  • 在该数据流的下一个阶段(或者此时甚至可以将其路由到另一个数据流),在仅附加表中对每个分组键执行范围扫描,聚合值并执行{ {1}}插入该聚合表。

那样:

  • 确保在Put之后触发窗口时事件处于Bigtable中,可以获得一致的聚合。
  • 在下一个触发窗口之后一个窗口完成的不太可能的情况下(使用旧的聚合视图),触发时间戳可用于区分最新版本的单元格。
  • 仅附加表也可以用于其他种类/级别的聚合,之后可以决定这样做。
  • 维护相对简单,因为它不需要任何定期清洁工作。