如何在cassandra中保持多个表之间的数据一致性



我很难弄清楚如何在多个表之间维护属性更新以确保数据一致性。

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

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的角度来看,解决这个问题的最佳方法是什么?

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

数据建模

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

可以使用批处理视图或物化视图来维护跨表的一致性。物化视图可从版本3.0 获得

请参阅

如何确保Cassandra中不同表上的数据一致性?

我更喜欢更改数据模型并进行设计相应地用于我们的查询,如果可能的话,将其作为一个大表。

希望它能有所帮助!

物化视图可能是最佳选择:

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之后,只需删除二级索引并创建物化视图。

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

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

  1. 通过发出UPDATE fan ... WHERE fan_id = xxx来更新fan
  2. 通过发出SELECT actor_id ... WHERE fan_id = xxxactors_by_fan中选择所有actor_id
  3. 通过发出UPDATE fans_by_actor ... WHERE actor_id IN (...)更新fans_by_actor表中的所有对应行,或者在actor_id上循环并运行每个更新异步

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

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

相关内容

  • 没有找到相关文章

最新更新