【问题标题】:How to maintain data consistency across multiple tables in cassandra?如何在cassandra中保持跨多个表的数据一致性?
【发布时间】:2017-05-15 06:41:29
【问题描述】:

我无法弄清楚如何跨多个表维护属性更新以确保数据一致性。

例如,假设我在演员和粉丝之间有多对多的关系。一个粉丝可以支持很多演员,一个演员有很多粉丝。我制作了几张表格来支持我的查询

CREATE TABLE fans (
    fan_id uuid,
    fan_attr_1 int,
    fan_attr_2 int
    PRIMARY KEY ((fan_id))
)

CREATE TABLE actors (
    actor_id uuid,
    actor_attr_1 int,
    actor_attr_2 int
    PRIMARY KEY ((actor_id))
)

CREATE TABLE actors_by_fan (
    fan_id uuid,
    actor_id uuid,
    actor_attr_1 int,
    actor_attr_2 int
    PRIMARY KEY (fan_id, actor_id)
)

CREATE TABLE fans_by_actor (
    actor_id uuid,
    fan_id uuid,
    fan_attr_1 int,
    fan_attr_2 int
    PRIMARY KEY (actor_id, fan_id)
)

假设我是一个粉丝,我在我的设置页面上,我想将我的 fan_attr_1 更改为不同的值。

fans 表上,我可以很好地更新我的属性,因为应用程序知道我的fan_id 并且可以键入它。

但是,如果不先查询与粉丝关联的 actor_id,我就无法更改 fans_by_actor 上的 fan_attr_1

只要您想更新fansactors 的任何属性,就会出现此问题。

我尝试在网上寻找遇到类似问题的人,但我找不到他们。例如,在 Datastax 的数据建模课程中,他们使用具有多对多关系的演员和视频的示例,其中他们有表格 actors_by_videovideos_by_actor。与我咨询过的其他在线资源一样,该课程讨论了查询后的建模表,但没有深入研究如何维护数据完整性。在actors_by_video 表中,如果我想更改演员的属性会发生什么?不必遍历actors_by_video 的每一行来查找包含actor 的分区并更新属性吗?这听起来非常低效。另一种选择是事先查找视频 ID,但我在其他地方读到,在写入之前读取是 Cassandra 中的反模式。

从数据建模的角度或从 CQL 的角度来说,解决此问题的最佳方法是什么?

编辑: - 固定句子存根 - 增加了背景和先前的研究

【问题讨论】:

  • 您要进行哪些查询?您围绕查询建模数据,而不是围绕它们的关系(它不是关系数据库)。可能想查看academy.datastax.com/resources/ds220-data-modeling 了解有关 cassandra 数据建模的一些教程
  • 是的,我在问这里之前实际上参加了课程,但课程本身似乎并没有回答问题。在他们的 KillrVideo 示例中,他们同时使用了 videos_by_actoractors_by_videos,这是与上述类似的范例。但是,他们从未讨论过如果演员属性或视频属性发生变化应该如何维护这些表
  • 这真是一个好问题。所有关于这些 nosql 数据存储的数据建模教程似乎都忽略了如果您在不同的表中有重复数据时如何维护数据完整性的主题:cassandra.apache.org/doc/latest/cassandra/data_modeling/…

标签: cassandra data-modeling cql data-consistency


【解决方案1】:

数据建模

Cassandra 不是关系型数据库,在 DataModeling 上需要遵循某些基本规则,在高层次上,我们的数据模型需要遵循以下目标。

1) 在集群周围均匀分布数据

2) 最小化读取的分区数

此外,我们应该选择一个大表,而不是把它分成多个表并在表之间添加关系。在这种方法中,会出现重复记录。复制记录并不是一项成本更高的操作,因为它只需要多一点磁盘空间,而不是 CPU、内存、磁盘 IOP 或网络。

请注意,列键名和值有大小限制。最大列键(和行键)大小为 64KB。最大列值大小为 2 GB。但由于没有流式传输,并且在请求时会在堆内存中获取整个值,因此将大小限制为仅几 MB。

更多信息:

http://www.datastax.com/dev/blog/basic-rules-of-cassandra-data-modeling

http://www.ebaytechblog.com/2012/07/16/cassandra-data-modeling-best-practices-part-1/

http://www.ebaytechblog.com/2012/08/14/cassandra-data-modeling-best-practices-part-2/

https://docs.datastax.com/en/cql/3.1/cql/cql_reference/refLimits.html

CQL

可以使用BatchMaterialized Views 来维护跨表的一致性。从 3.0 版开始提供物化视图

请看

How to ensure data consistency in Cassandra on different tables?

我的偏好是更改数据模型并进行设计 相应地用于我们的查询,并尽可能将其作为一个大表。

希望对你有帮助!

【讨论】:

  • 我仍然没有看到光明,也许一个具体的例子会有所帮助。假设您正在对上述示例进行建模。您将如何构建表格以支持查询?
【解决方案2】:

物化视图可能是最好的选择:

CREATE MATERIALIZED VIEW actors_by_fan 
AS SELECT fan_id, actor_id, actor_attr_1, actor_attr_2
FROM fans 
PRIMARY KEY (fan_id, actor_id);

CREATE MATERIALIZED VIEW fans_by_actor
AS SELECT actor_id, fan_id, fan_attr_1, fan_attr_2
FROM actors 
PRIMARY KEY (actor_id, fan_id);

在 3.0 之前的版本中,创建二级索引并评估其性能是否可以接受。后来升级到 3.x 后,只删除二级索引,创建物化视图。

【讨论】:

  • 感谢有趣的方法。但是,我们使用不支持物化视图的旧版本 Cassandra (2.2.7):/ 我无法想象自己是唯一面临这个问题的人,我想知道其他 SWE 是如何解决这个问题的。二级索引是一种选择,但它不适合具有高基数的数据。
  • MV 现在显示为泄漏抽象; mail-archive.com/dev@cassandra.apache.org/msg11511.html使用前请检查
【解决方案3】:

解决此类问题的方法是手动更新所有更改的记录。

由于您不能使用物化视图,为了更新您的数据上的fan_attr_1,您需要:

  1. 通过发出UPDATE fan ... WHERE fan_id = xxx 更新fan 表。
  2. 通过发出SELECT actor_id ... WHERE fan_id = xxx,从actors_by_fan 中选择所有actor_id
  3. 通过发出UPDATE fans_by_actor ... WHERE actor_id IN (...) 更新fans_by_actor 表中的所有相应行,或者循环遍历actor_ids 并异步运行每个更新。

只要您在第 2 步中有少量的actor_id,比如少于 20 个,您就可以将所有查询分组并通过在单个 BATCH 中运行它们来保持表之间的强一致性。否则需要通过其他方式保证表之间的一致性。

这可能就像听起来一样低效,但我认为没有其他更智能的解决方案。顺便说一句,您正在发出一次读取(步骤 2)和多次写入(步骤 1 和步骤 3)。这不会是世界末日,尤其是如果您不经常更改属性(例如每 10 毫秒)。

【讨论】:

    猜你喜欢
    • 2014-03-11
    • 2016-03-17
    • 2019-12-12
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 2016-05-31
    • 2015-07-08
    • 1970-01-01
    相关资源
    最近更新 更多