是否可以构建一个数据模型,使得获取查询更容易,即使它可能会在群集中创建热点?
在阅读时,请记住我现在不与Solr合作,并且考虑到这些数据的访问频率我不认为使用spark-sql是合适的。我想把它保持为纯粹的卡桑德拉。
我们有事务,它们使用UUID作为分区键建模,以便数据在集群周围均匀分布。我们的一种访问模式要求UI获取给定用户和日期范围的所有记录,查询如下:
CREATE transactions_by_user_and_day (
user_ id int,
created_date timestamp,
created_date_time timestamp,
transaction_id uuid,
PRIMARY KEY ((user_id, created_date), created_date_time)
) WITH CLUSTERING ORDER BY (created_date_time DESC);
我构建的第一个模型使用user_id和created_date(创建事务的日期,始终设置为午夜)作为主键:
select * from transactions_by_user_and_day where user_id = ? and created_date in (?, ?, …) and created_date_time > ?;
此表似乎表现良好。使用created_date作为PK的一部分,允许用户更均匀地分布在群集周围以防止热点。但是,从访问角度来看,它使数据访问层做了我们想要的更多工作。最终必须创建一个包含所提供范围内所有日期的IN语句,而不是给出日期和大于运算符:
CREATE transactions_by_user_and_day (
user_id int,
created_date_time timestamp,
transaction_id uuid,
PRIMARY KEY ((user_global_id), created_date_time)
) WITH CLUSTERING ORDER BY (created_date_time DESC);
为了简化在数据访问层完成的工作,我考虑过如下建模数据:
{{1}}
使用上述模型,数据访问层可以为用户获取transaction_id,并在Cassandra中的特定日期范围内进行过滤。但是,这会导致群集中出现热点。具有长寿和/或高容量的用户将在该行中创建更多列。我们打算提供数据的TTL,以便60天以上的任何东西都会下降。此外,我已经分析了数据的大小,我们最高容量用户的60天数据量低于2 MB。算一算,如果我们假设所有40,000个用户(这个数字不会显着增长)均匀分布在3节点集群上,每个用户2 MB数据最终每个节点最多只有26 GB((13333.33 *) 2)/ 1024)。实际上,你不会最终有1/3的用户做这么多的音量而你必须真的不幸让Cassandra使用V-Nodes将所有这些用户放在一个节点上。从资源的角度来看,我认为26 GB不会产生或破坏任何东西。
感谢您的想法。
答案 0 :(得分:1)
日期模型1:您可以做的其他事情是更改数据访问层以单独查询每个ID,而不是使用IN子句。查看此页面以了解为什么会更好。
数据模型2:每个节点26GB的数据似乎不多,但2MB的提取似乎有点大。当然,如果这是一个异常值,那么我没有看到它的问题。您可以尝试设置cassandra-stress作业来测试模型。只要大多数分区小于2MB,就可以了。
另一个解决方案是将数据模型2与Bucketing一起使用。这会给你更多的写入开销,因为你必须维护一个桶查找表。如果我需要详细说明这种方法,请告诉我。