在Bigtable中建模正向和反向查询问题



假设我们有以下三个实体:

Organization
- id
Role
- id
Member
- id

可以将角色授予组织内的成员,从而赋予该成员对该组织的某些访问控制权限我希望能够回答以下两个问题

  1. 列出在给定组织中具有给定角色的所有成员的ID(例如,给定角色ID和组织ID,请给我成员列表(
  2. 列出成员在给定组织内被授予的所有角色ID(例如,给定成员ID和组织ID,给我角色列表(

我正在努力寻找如何在Bigtable中对此进行建模的建议(最好是用一行原子突变(。。。我也对其他技术建议持开放态度(我试图在公司给我的限制范围内进行设计(。


如果我们使用Bigtable行关键字org#{orgID}#role#{roleID}#member#{memberID}对上述关系进行建模,我可以很容易地回答第一个问题。然而,我无法轻易回答第二个问题。如果我复制数据并存储另一个行密钥org#{orgID}#member#{memberID}#role#{roleID},那么我可以很容易地回答第二个问题,但现在我有两行要管理,并且不能保证这两行之间的原子更新,因此可能会导致一致性问题。

社区里有人遇到过类似的问题吗?如果是,你是如何解决的?

Cloud Bigtable本机不支持二级索引,这就是您只需要一行并能够高效运行这两个查询而不需要完整的表扫描的原因。您已经确定的替代方法是通过一个确保最终一致性的过程写入两行。根据系统的基本需求,这可能足以满足您的需求。

根据您的限制(云提供商、数据规模、原子性、多区域复制等(,您可能会更好地使用标准关系数据库(如Postgres、MySQL(或Google cloud Spanner。

使用Spanner实现这一目标的可能方法:

  • 有一个表示成员的表<->角色关系。将RoleID作为行的主索引,然后为MemberID添加辅助索引,您就可以对其中任何一个运行查询。

  • 走传统的关系数据库路线,即拥有Member、Role和MemberRole联接表。使用Spanner,您应该通过事务进行原子更新。在进行查询时,可能会遇到跨多个拆分的读取问题,但您必须进行一些真实的测试,看看您的性能会是什么样子。

披露:

  • 我负责Cloud Bigtable的产品管理
  • 我是JanusGraph项目的联合创始人

通读你的问题陈述,听起来你想使用关系数据库或图形数据库。每一个都有自己的优点/缺点。

关系DBMS方法

正如Dan在回答中提到的,您可以通过Google Cloud SQL或Google Cloud Spanner使用托管MySQL或PostgreSQL,这取决于您对规模、复制、一致性、与现有代码/框架的兼容性等的需求。

图形数据库方法

或者,您可以使用图形数据库,它可以帮助您轻松地对这些信息进行建模并高效地查询。

例如,您可以使用Bigtable和Elasticsearch在GKE上部署Janusgraph,并使用Gremlin语言查询数据,这是许多图形数据库支持的标准图形遍历/查询语言。

请注意,JanusGraph+Bigtable继承了Bigtable的事务性(正如您所指出的,它是行级原子(。由于JanusGraph将每个顶点存储在Bigtable中的单独一行中,因此只有单个顶点更新是原子更新。如果您希望通过JanusGraph进行事务更新,则可能需要使用不同的存储后端,例如

  • BerkeleyDB(本地非分布式存储后端(
  • FoundationDB(JanusGraph社区最近的贡献(

您可以考虑许多其他图形数据库,其中一些还支持Gremlin或其他图形查询语言。例如,如果您愿意,可以在GCP上部署Neo4j,它支持Gremlin和Cypher。

最新更新