Datastore/BigTable ACID 和密钥更新通知
Datastore/BigTable ACID and key update notifications
我有 Kafka 主题,其中包含目录数据,命令如下:
- item_upsert
- partial_item_update
- delete_item
- delete_all
现在我需要使用这个主题,可能将 100k msgs/sec 流式传输到某些数据库,这将帮助我将原始命令流转换为项目状态流。所以只有来自数据库的当前项目状态。基本上DB都会用到lookup。
我的想法是:
数据存储中 - Insert/Update/Delete 个项目,
- 处理完特定消息后,我将向另一个流发送新消息,告诉下游消费者某个项目是 Inserted/Updated/Deleted。这些消费者随后将从数据存储中读取项目的当前状态,并将项目状态提取到另一个 Kafka 主题。
我担心的是 Datastore 的 ACID。 "ACID"怎么样?它甚至适合这样的用例吗?
我也在考虑使用更便宜的 BigTable,但对于这个用例来说这似乎不是正确的选择。
如果您有任何ideas/recommendations解决此问题的方法,我将很高兴。
首先关注的是消息率。数据存储无法维持每个实体组超过 1/秒的写入速率(每个实体都是实体组的一部分),请参阅 Limits。因此,如果您希望每秒更新一次以上 item/entity,则数据存储不适合。
要使用 Cloud Datastore 实现 ACID,您需要避免 Eventual Consistency. Which is possible. From Eventual Consistency when Reading Entity Values:
The eventual consistency on reading entity values can be avoided by
using a keys-only query, an ancestor query, or lookup by key (the
get() method). We will discuss these different types of queries in
more depth below.
我会放弃祖先查询的可能性,因为它需要所有相应的实体都在同一个实体组中,从而放大了上述写入限制的影响。另见 Updates to a single entity group。
棘手的部分是 upsert
操作,更具体地说,是创建新实体和 updating/deleting 现有实体之间的区别。
如果您不能总是 generate/determine 项目数据中的唯一项目标识符(或传递在前一阶段确定的标识符),那么这意味着您需要查询,这不能在事务内执行,其结果将受到最终一致性的约束。数据存储也不适合这种情况。
但是如果可以获得这样的唯一标识符,那么您可以将其用作实体键标识符,事情很简单:upsert
操作变成了通过该键 get
实体的简单事务尝试(强一致)和(在同一事务内):
- 如果
get
因代码不存在而失败,则使用该键创建一个新实体
- 如果
get
成功更新实体并将其保存回来
Bigtable 可以处理 100K 的 10 节点集群(我有 运行 测试多达 3,500 个节点,每秒处理 35M 更新)。 Bigtable 单行一致性强upserts
。 Bigtable 用户设计的模式可以将他们所有的交易数据放入一行。
Cloud Bigtable支持upserts
,不区分insert
和update
。还有一个按范围删除,理论上可以用于您的 delete_all
案例。
高交易率和低成本是使用 Cloud Bigtable 的正确理由。或者,您可以考虑使用适用于高吞吐量事务数据的 Cloud Spanner。
我有 Kafka 主题,其中包含目录数据,命令如下:
- item_upsert
- partial_item_update
- delete_item
- delete_all
现在我需要使用这个主题,可能将 100k msgs/sec 流式传输到某些数据库,这将帮助我将原始命令流转换为项目状态流。所以只有来自数据库的当前项目状态。基本上DB都会用到lookup。
我的想法是:
-
数据存储中
- Insert/Update/Delete 个项目,
- 处理完特定消息后,我将向另一个流发送新消息,告诉下游消费者某个项目是 Inserted/Updated/Deleted。这些消费者随后将从数据存储中读取项目的当前状态,并将项目状态提取到另一个 Kafka 主题。
我担心的是 Datastore 的 ACID。 "ACID"怎么样?它甚至适合这样的用例吗?
我也在考虑使用更便宜的 BigTable,但对于这个用例来说这似乎不是正确的选择。
如果您有任何ideas/recommendations解决此问题的方法,我将很高兴。
首先关注的是消息率。数据存储无法维持每个实体组超过 1/秒的写入速率(每个实体都是实体组的一部分),请参阅 Limits。因此,如果您希望每秒更新一次以上 item/entity,则数据存储不适合。
要使用 Cloud Datastore 实现 ACID,您需要避免 Eventual Consistency. Which is possible. From Eventual Consistency when Reading Entity Values:
The eventual consistency on reading entity values can be avoided by using a keys-only query, an ancestor query, or lookup by key (the get() method). We will discuss these different types of queries in more depth below.
我会放弃祖先查询的可能性,因为它需要所有相应的实体都在同一个实体组中,从而放大了上述写入限制的影响。另见 Updates to a single entity group。
棘手的部分是 upsert
操作,更具体地说,是创建新实体和 updating/deleting 现有实体之间的区别。
如果您不能总是 generate/determine 项目数据中的唯一项目标识符(或传递在前一阶段确定的标识符),那么这意味着您需要查询,这不能在事务内执行,其结果将受到最终一致性的约束。数据存储也不适合这种情况。
但是如果可以获得这样的唯一标识符,那么您可以将其用作实体键标识符,事情很简单:upsert
操作变成了通过该键 get
实体的简单事务尝试(强一致)和(在同一事务内):
- 如果
get
因代码不存在而失败,则使用该键创建一个新实体 - 如果
get
成功更新实体并将其保存回来
Bigtable 可以处理 100K 的 10 节点集群(我有 运行 测试多达 3,500 个节点,每秒处理 35M 更新)。 Bigtable 单行一致性强upserts
。 Bigtable 用户设计的模式可以将他们所有的交易数据放入一行。
Cloud Bigtable支持upserts
,不区分insert
和update
。还有一个按范围删除,理论上可以用于您的 delete_all
案例。
高交易率和低成本是使用 Cloud Bigtable 的正确理由。或者,您可以考虑使用适用于高吞吐量事务数据的 Cloud Spanner。