【问题标题】:Modeling MultiTenant in Cassandra在 Cassandra 中建模多租户
【发布时间】:2015-05-15 08:36:50
【问题描述】:

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

我想知道将这个概念建模的最佳方法是什么。我做了很多研究,发现了这个话题: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

查询没问题,但我想知道将“租户”作为 PARTITION KEY 而不是“id”并使用“id”作为 CLUSTERING KEY 是否会更好

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

额外优势:能够按创建日期(ORDER BY id)对配置文件进行排序

如果我理解良好,使用租户作为 PARTITION KEY,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 在返回少量结果的大表上使用二级索引(在我的情况下是一个)是一种不好的做法。在我的模式中,“数据源”是一个包含例如 facebookId、twitterId 等的集合

如果您有任何想法,我真的很感兴趣 :) !我是 Cassandra 的新手,如果有不懂的地方请告诉我

谢谢,

多诺万

【问题讨论】:

  • 我正在考虑类似于选项 1 的东西,但每个租户都有一个应用程序列表,每个应用程序都有自己的密钥空间。你选择了哪个选项?您对这个选择满意吗?
  • 我发现第一个选项的吸引力在于能够控制每个应用的复制。

标签: cassandra data-modeling


【解决方案1】:

使用 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 性能。真的取决于你的用例。

【讨论】:

    猜你喜欢
    • 2012-08-11
    • 2019-09-07
    • 2019-05-18
    • 2015-04-22
    • 2011-03-29
    • 1970-01-01
    • 2017-05-15
    • 2011-08-16
    • 2017-03-21
    相关资源
    最近更新 更多