当前位置: 首页 > 知识库问答 >
问题:

在卡桑德拉中建模多租户

蒋奇
2023-03-14

我有几个客户,每个客户都由一个“租户”代表

我想知道将这个概念建模的最佳方法是什么,我做了大量的研究,发现了这个课题:http://cassandra-user-incubator-apache-org.3065146.n2.nabble.com/Modeling-multi-tenanted-Cassandra-schema-td7591311.html

我知道有几种可能性

  1. 租户提供一个密钥空间
  2. 按租户划分的一个表(列族)
  3. 一个字段代表所有表中的租户

我选择解决方案3,但我不确定是否有最佳模式以获得最佳性能

这是我的配置文件模式

CREATE TABLE profiles (
  id timeuuid,
  tenant text,
  email text,
  datasources set<text>,
  info map<text, text>,
  friends set<timeuuid>,
  PRIMARY KEY(id, tenant)
);

CREATE INDEX ON profiles(datasources);
CREATE INDEX ON profiles(email);

我的PARTITION KEY是唯一性的“id”,而CLUSTERING KEY是“tenant”。我的需要是能够尽快执行这些查询

SELECT * FROM profiles WHERE id = x
SELECT * FROM profiles WHERE tenant = x
SELECT * FROM profiles WHERE email = x
SELECT * FROM profiles WHERE datasources CONTAINS x

查询是可以的,但我想知道是否最好将“租户”作为分区键而不是“id”,并使用“id”作为集群键

CREATE TABLE profiles (
  ...
  PRIMARY KEY(tenant, id)
);

在我的应用程序中,“租户”始终是必填字段,因此以这种方式进行相同的查询不会有问题(但它是更快还是更慢?

SELECT * FROM profiles WHERE tenant = y
SELECT * FROM profiles WHERE tenant = y AND id = x
SELECT * FROM profiles WHERE tenant = y AND email = x
SELECT * FROM profiles WHERE tenant = y AND datasources CONTAINS x

奖励优势:能够按创建日期对配置文件进行排序(按 ID 排序)

使用租户作为分区键如果我理解得不错的话,Cassandra将在同一行中物理存储同一租户的所有元素,并且可能能够在该行中存储多达20亿个数据,在这种情况下,如果我的一个客户超过该数字,会发生什么情况?我还了解到,我们可以使用组合键,例如,将当前日期(20150313)放在键的第二部分,以便在一行中只对租户当天的所有新配置文件进行分组

CREATE TABLE profiles (
  ...
  date text,
  PRIMARY KEY((tenant, date), id)
);

但是使用该解决方案,查询不可能查询所有数据(查询中没有日期)。

正如您在我的模式中所看到的,我对“电子邮件”和“数据源”字段使用二级索引。但我在这里读http://www.datastax.com/documentation/cql/3.1/cql/ddl/ddl_when_use_index_c.html在一个返回少量结果(在我的例子中是一个)的大表上使用二级索引是一种糟糕的做法。在我的模式中,“datasources”是一个集合,包含例如facebookId、twitterId等

如果你有任何想法,我真的很感兴趣:)!我对卡桑德拉很陌生,如果有我不明白的地方,请告诉我

谢谢,

多诺万

共有1个答案

段阳夏
2023-03-14

使用 Cassandra 进行数据复制不是问题,因此您必须从查询开始考虑数据建模过程。

所以,我在想这样的事情:

CREATE TABLE profiles (
   id timeuuid,
   tenant text,
   email text,
   datasources set<text>,
   info map<text, text>,
   friends set<timeuuid>,
   PRIMARY KEY((id, tenant))
);

假设租户在应用程序级别是已知的,此模式将为您提供以下查询快速运行:

SELECT * FROM profiles WHERE id = x and tenant = y


CREATE TABLE profiles_emails (
   id timeuuid,
   tenant text,
   email text,
   datasources set<text>,
   info map<text, text>,
   friends set<timeuuid>,
   PRIMARY KEY((email, tenant))

);

SELECT * FROM profiles WHERE email = x and tenant = y


CREATE TABLE profiles_tenants (
   id timeuuid,
   tenant text,
   email text,
   datasources set<text>,
   info map<text, text>,
   friends set<timeuuid>,
   PRIMARY KEY((tenant, id))
);

SELECT * FROM profiles WHERE tenant = x and id = y

CREATE TABLE tenants (
   id timeuuid,
   tenant text,
   email text,
   datasources set<text>,
   info map<text, text>,
   friends set<timeuuid>,
   PRIMARY KEY((tenant, date))
 );

 SELECT * FROM profiles WHERE tenant = x and date < y 

或者你可以看看 http://www.datastax.com/documentation/cql/3.0/cql/cql_using/paging_c.html

对于基于“数据源”的搜索,您可以使用不同的系统,如elasticsearch或solr。或者如果集合的值有限,那么您可以为每个集合维护一个单独的表。

Cassandra 的写入操作速度很快,数据重复不是问题,因此您可以批量写入所有这些表。

您还必须考虑一致性级别,它对 READ 性能有影响。真的取决于您的用例。

 类似资料:
  • 我目前在cassandra中有一个名为macrecord的表,类似于以下内容: 在这种情况下,我想不出其他解决方案,只有在macadd值重复的情况下删除整行,然后插入具有更新时间戳的新行。 是否有更好的解决方案在macadd值重复时更新时间戳,或者在我的原始表中只有macadd是主键的范围内查询时间戳值的替代方法。

  • 我对Cassandra相当陌生,在过去的一个月里读了很多书。 我正在研究一个小用例。 查询:基于在某个时间范围内播放的金额排名前 X 的玩家。 因此,在任何给定的时间范围内,我都希望汇总玩家的总游戏次数,并得出排名前X的玩家。 我遵循了创建UDF(使用C*-2.2.0版本)的方法,用于聚合AmountPlay by a Player。 下面是我为这个用例设计的时间序列数据模型。 请让我知道我的数据

  • 我使用的是spring数据cassandra,需要使用jpa映射一个字段,在cassandra中,该字段的类型为

  • 我们运行的cassandra集群有3个节点,复制因子为2。 我们的nodejs服务器是查询这个集群的唯一地方。 是否有其他任何地方的参数设置可能导致不一致的查询? cassandra v2.2.4 nodejs驱动程序v3.0.0 编辑-添加我正在做的事情的示例: 1)检查用户名是否被占用 2)创建用户

  • 我们一直在使用Spark RDD API(Spark 2.0)来处理在Cassandra.Note中建模的数据,这些数据在Cassandra中建模以实现高效的读写。 然而,现在还有SparkSQLAPI,Spark DataFrame API,它也是一种替代的数据访问方法-http://spark.apache.org/docs/latest/sql-programming-guide.html

  • 我用Spring Data Cassandra 2.2.1开发了一个新的应用程序,想在Cassandra 2.1.9服务器上运行它(旧的,我知道)。但是我们得到了错误 Spring数据卡桑德拉手册声称Spring数据2.2.1至少需要卡桑德拉2.1,所以这应该有效,但它没有。我们包含的唯一特定于卡桑德拉的依赖项是 我怎样才能让这个工作?