我有一个示例的以下BigTable结构:
Table1 : column_family_1 : column_1 : value
value
这里有一个数字,我们可以这么说。这是由数据流管理的,我想每次更新值。
此值可能是一个金额,我希望每次用户进行购买时更新它(以维持总花费到目前为止),所以我在购买事件监听器数据流中执行以下操作(每当遇到购买事件时):
Put
请求以更新值虽然这种方法有一些网络延迟,但似乎有效。失败的情况是,当数据流有多个工作人员时,用户进行多次购买,并且事件发送给多个工作人员,例如:
Put
次请求并被覆盖为了防止这种情况发生,我正在努力提出一个只用纯文本add 10 to the spent amount value
说的请求。这是我们可以在数据流中做些什么吗?
答案 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
。
您所拥有的选项应该提供比我在此处提供的更多文档,但我可以提供一些高级别的选项:
始终对您找到的任何新事件使用Increment
,并总结Reads上的值。您还可以通过创建删除所有当前值的“事务”来编写另一个定期清理行的作业,并使用总和写入新单元格
使用Cloud Functions来监听发布/订阅事件并执行Put
。这是一个Cloud Bigtable example using Cloud Functions。您还可以执行Increment
,执行添加并使用您在帖子中描述的算法执行Get
(如果我选择此选项,我个人会选择CheckAndMutate
来保持一致性选项)。
使用AbstractCloudBigtableTableDoFn
编写自己的CheckAndMutate
来执行DoFn
或Increment
,但要了解这可能会导致数据完整性问题。< / p>
如果系统足够大,选项#1是您最强大的选项,但会以系统复杂性为代价。如果您不想要这种复杂性,那么选项#2是您的下一个最佳选择(尽管我会选择CheckAndMutate
)。如果您不关心数据完整性并且需要高吞吐量(例如“页数”或其他可能在一小部分时间内出错的遥测),那么选项#3将是您最好的选择。< / p>
答案 1 :(得分:2)
另一种解决方案可能如下:
AbstractCloudBigtableTableDoFn
在仅附加表中执行Put
插入。那样:
Put
之后触发窗口时事件处于Bigtable中,可以获得一致的聚合。