Cassandra- UserProfileie 的数据建模

Cassandra- Data modelling for UserProfilie

我有一个用户模型,具有如下属性:-

class User(Model):
    user_id = columns.Integer(primary_key=True)
    username = columns.Text()
    email = columns.Text()
    fname = columns.Text()
    lname = columns.Text()
    age = columns.Text()
    state = columns.Text()
    city = columns.Text()
    country = columns.Text()
    gender = columns.Text()
    phone = columns.Text()
    school_name = columns.Text()
    created_at = columns.Text()
    race = columns.boolean()

这是我的普通 RDBMS 模型。我的查询如下:-

1) Get all users with city = 'something'

2) Get a user with email = 'something' 

3) Get a user with username = 'something' 

4) Get all users with phones IN ('something' )

5) Get all users with state = 'something' 

6) Get all users with age > something

7) Get all users with gender = 'something' 

8) Get all users with race = 'something' 

9) Get count(*),school_name users Group By schoolname

10) Get all users with created_date > 'something' LIMIT 1000

11) Get all users with username IN ('something') AND age IN ('something') AND phone IN ('something') AND state IN ('something') AND so on  LIMIT 1000

我可以在 RDBMS 中使用简单的 Select 查询得到上述查询结果,但问题出在 Cassandra 上。

因为,要在 Cassandra 中获取上述查询的结果,建议每个查询使用不同的模型,这将加快读取速度。在这个时代,磁盘比以前便宜得多。话虽这么说,但我明白在一个问题上投入更多磁盘并不总是那么容易。我看到的更大问题是调整应用程序的 DAO 层以保持 10 个不同的表同步。 (此外,我的内在直觉不相信有 10 个模型用于不同的查询。:P)

有人可以向我解释 Cassandra 中的正确模型以获得这些查询的结果吗?

PS:上面模型的动作可以是Read/Write/Update/Delete。 查询 11 是最重要的查询。

考虑到可以更新特定用户的信息,最重要的是使这些查询在大量数据上真正快速。

可能最简单的方法是将 Datastax Enterprise 与搜索 (Solr) 或分析 (Spark) 选项一起使用。您可以从 www.datastax.com 免费下载它用于测试目的。只要您的可用于查询的数据的 SLA 超过 1 秒,lucene 索引应该能够处理这些不同的搜索选项。

更大的问题是您为什么要在这里使用 Cassandra?大量数据是什么意思?通常,当您的应用程序具有低延迟读写需求、复制到许多服务器和许多数据中心的能力以及零停机时间时,Cassandra 最适合使用。这在数据集市/仓库或分析数据库中通常不需要,根据查询类型和您在 "Large amounts of data" 上执行它的需要似乎指向了这一点。您通常不希望每个 Cassandra 节点放置超过 1 - 3T 的数据,尽管那里有一些异常值...

您面临着真正的 Cassandra 限制:如果您确定要使用 Cassandra,则需要遵循 "Cassandra rules"。其中有

  • 去规范化
  • 明智地选择索引

那么让我们开始吧。每个用户都应该有唯一的 ID、用户名、电子邮件和 phone。这意味着这些列不适合索引 (read here why),因此反规范化是正确的方法。

根据您的查询,您将得到 user_by_username、user_by_email 和 user_by_phones。您可能认为每次重复数据在更新和磁盘使用方面会很繁重:因此您可以通过创建每个仅包含用户 ID 作为值的折衷方案。例如:

 user_email     | user_id 
--------------+-------------------
 some@thing.com | 123-456-7aa |    
 girl@hello.org | efg-123-ghi | 

在 KS 中的另一个 table 中,您需要一个 table,它可以通过 id 检索有关用户的所有信息。这将解决 update problem,如果您需要更新电子邮件地址或 phone,您只能更新一对 table 而不是 N。阴暗面是您必须执行两次查询以获取您的数据。

我们继续。

stategenderrace 很适合编入索引,原因如下:

  1. 低基数
  2. 许多行将包含这些值

通过索引,您将解决一些其他查询。最难的部分是像

这样的查询
select * from users where age > xyz

Cassandra 不允许这种查询,因为您需要在集群部分执行 "!equals" 操作。为此,您需要通过某种通用键 "organize" 用户:例如状态或 "state-group" —— 这意味着要了解特定年龄的所有用户,您必须查询每个分区。

注意:我不是在提供解决方案,这也不是我的目标——我想做的是提供一种方法来解决 Cassandra 的这个问题。

HTH,
卡罗