Cassandra表定义/分区/建模
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cassandra表定义/分区/建模相关的知识,希望对你有一定的参考价值。
尝试为我们的场景定义正确的架构/表:我们有几百个电子商务站点,每个站点都有独特的siteId
。
每个站点都有自己的最终用户,每月最多可达1000万个唯一身份用户。每个用户都有独特的userId
。
每个最终用户都与网站进行交互:查看产品,将产品添加到购物车并购买产品(我们称之为用户事件)。我想存储过去30天的活动(如果可能,则存储180天)。
需要考虑的事项:
- 网站规模不同!我们有一些拥有1000万终端用户的“重型”网站,但我们也有“轻型”网站,拥有数百/数千名用户。
- 事件没有唯一的ID。
- 用户可以一次拥有多个事件,例如,他们可以查看包含多个产品的页面(但我们可以在没有此限制的情况下生活,以简化)。
- 粗略估计:100个客户x 10M EndUsers x 100交互= 100,000,000,000行(每月)
- 写入实时(当事件到达服务器时)。阅读量少得多(1%的事件)。
- 事件具有更多元数据,不同事件(view / purchase / ..)具有不同的元数据。
- 使用Keyspace在站点之间分离,并管理每个站点与一个表中的所有客户的表。
- 如何在这里定义密钥?
+--------+---------+------------+-----------+-----------+-----------+ | siteId | userId | timestamp | eventType | productId | other ... | +--------+---------+------------+-----------+-----------+-----------+ | 1 | Value 2 | 1501234567 | view | abc | | | 1 | cols | 1501234568 | purchase | abc | | +--------+---------+------------+-----------+-----------+-----------+
我的查询是:获取特定用户的所有事件(及其元数据)。正如我上面所假设的,大约有100个事件。
编辑2:我想这不清楚,但用户的唯一性是每个网站,如果他们在不同的网站上,两个不同的用户可能具有相同的ID
如果要查询userid,则userid应该是复合主键的第一部分(这是分区键)。使用复合主键创建可以查询以返回排序结果的列。我会建议以下架构:
CREATE TABLE user_events (
userid long,
timestamp timestamp,
event_type text,
site_id long,
product_id long,
PRIMARY KEY (userid, site_id, timestamp, product_id));
这应该像查询一样
SELECT * FROM user_events WHERE user_id = 123 and site_id = 456;
非常高效。通过将时间戳添加到PK,您还可以轻松限制查询以获得最高(最新)1000(无论您需要)事件,而不会因为具有很长历史的高活跃用户(或机器人)而导致性能问题。
要记住一件事:我建议将user_id或user_id,site_id组合作为分区键(主键的第一部分)。这样可以防止你的行变得太大。
所以替代设计看起来像这样:
CREATE TABLE user_events (
userid long,
timestamp timestamp,
event_type text,
site_id long,
product_id long,
PRIMARY KEY ( (userid, site_id), timestamp, product_id));
这种方法的“缺点”是您始终必须提供用户和站点ID。但我想这是你必须做的事情,对吧?
指出一件事。分区键(也称为行id)标识一行。一行将保留在特定节点上。出于这个原因,最好让行或多或少具有相同的大小。具有几千或几十列的行不是真正的问题。如果您有一些包含数百万列的行和其他只有10-20列的行,您将会遇到问题。这将导致集群失衡。此外,它使行缓存效率降低。在您的示例中,我建议避免将site_id作为分区键(行键)。
这对你有意义吗?也许这篇文章的优秀答案会给你一些更多的内容:difference between partition-key, composite-key and clustering-key。此外,仔细看看datastax documentation的这一部分提供了更多细节。
希望有所帮助。
我的查询是:获取特定用户的所有事件(及其元数据)。正如我上面所假设的,大约有100个事件。
所以,你想要给定用户的所有事件。由于每个用户在站点上都有唯一的ID,因此您可以使用userid
和site_id
作为主键并使用timestamp
作为聚类键来构建表。这是表结构:
CREATE TABLE user_events_by_time (
userid bigint,
timestamp timestamp,
event_type text,
product_id bigint,
site_id bigint,
PRIMARY KEY ((site_id,userid), timestamp)
) WITH CLUSTERING ORDER BY (timestamp DESC) ;
现在,您可以使用以下查询在给定时间内查询所有用户的事件:
SELECT * from user_events_by_time WHERE site_id= <site_id> and userid = <user_id> and timestamp > <from_time> and timestamp < <to_time>;
希望这能解决你的问题。
以上是关于Cassandra表定义/分区/建模的主要内容,如果未能解决你的问题,请参考以下文章