Cassandra:低基数分区

时间:2015-05-11 22:20:16

标签: cassandra cassandra-2.0 denormalization

假设我有一张桌子,就像这样:

CREATE TABLE Users (
  user UUID,
  seq INT,
  group TEXT,
  time BIGINT,
  PRIMARY KEY ((user), seq)
);

这遵循Cassandra所需的模式,在分区之间具有良好的分布(假设默认的Murmur3散列分区器)。

但是,我还需要(很少)按时间顺序执行范围查询。这似乎不可能在Cassandra。实际上我确实需要按组访问数据,因此(group, time)是可以接受的。既然似乎没有办法让二级索引有多个列,我想正确的事情就是反规范化,就像这样:

CREATE TABLE UsersByGroupTime (
  user UUID,
  seq INT,
  group TEXT,
  time BIGINT,
  PRIMARY KEY ((group), time)
) WITH CLUSTERING ORDER BY (time ASC);

除了group实际上是低基数,假设('A','B','C')以及用户之间的分布不均匀之外,这完全正常。由于该表上的查询很少,我不担心热节点,但我担心分布不均匀,甚至可能是单个节点获得所有节点。

这是一种常见的情况吗?有没有办法减轻这种情况,还是有替代解决方案?

1 个答案:

答案 0 :(得分:0)

一种帮助避免Cassandra时间序列模型热点的技术是利用时间桶。"基本上你要做的是确定"快乐的媒体"提供足够数据分布的时间精度水平,同时也是已知且半便于查询的。

出于本示例的目的,我将选择年份和月份(" yyyyMM")。 注意:我不知道年份和月份是否适用于您...它只是一个示例。确定时间段后,您可以将其添加为附加分区键,像这样:

CREATE TABLE UsersByGroupTime (
  user UUID,
  seq INT,
  group TEXT,
  time TIMEUUID,
  yearmonth BIGINT,
  PRIMARY KEY ((group, yearmonth), time)
) WITH CLUSTERING ORDER BY (time DESC);

插入一些行后,这样的查询将起作用:

aploetz@cqlsh:stackoverflow2> SELECT group, yearmonth, dateof(time), time, seq, user 
FROM usersbygrouptime WHERE group='B' AND yearmonth=201505;

 group | yearmonth | dateof(time)             | time                                 | seq | user
-------+-----------+--------------------------+--------------------------------------+-----+--------------------------------------
     B |    201505 | 2015-05-16 10:04:10-0500 | ceda56f0-fbdc-11e4-bd43-21b264d4c94d |   1 | d57ba8a4-db24-440c-a983-b1dd6b0d2e27
     B |    201505 | 2015-05-16 10:04:09-0500 | ce1cac40-fbdc-11e4-bd43-21b264d4c94d |   1 | 66d07cbb-a2ff-4d56-8fa1-14dfaf684474
     B |    201505 | 2015-05-16 10:04:08-0500 | cd525760-fbdc-11e4-bd43-21b264d4c94d |   1 | 07b589ac-4d5f-401e-a34f-e3479e269e01
     B |    201505 | 2015-05-16 10:04:06-0500 | cc76c470-fbdc-11e4-bd43-21b264d4c94d |   1 | 984f85b5-ea58-4cf8-b512-43abacb227c9

(4 rows)

现在可能会或可能不会帮助您查询,因此您需要花一些时间来确保选择合适的时间段。但是,这确实有助于环中的数据分布,您可以使用token函数看到:

aploetz@cqlsh:stackoverflow2> SELECT group, yearmonth, token(group,yearmonth)
FROM usersbygrouptime ;

 group | yearmonth | token(group, yearmonth)
-------+-----------+-------------------------
     A |    201503 |    -3784784210711042553
     A |    201504 |     -610775546464185720
     B |    201505 |     6232834565276653514
     B |    201505 |     6232834565276653514
     B |    201505 |     6232834565276653514
     B |    201505 |     6232834565276653514
     A |    201505 |     8281745497436252453
     A |    201505 |     8281745497436252453
     A |    201505 |     8281745497436252453
     A |    201505 |     8281745497436252453
     A |    201505 |     8281745497436252453
     A |    201505 |     8281745497436252453

(12 rows)

注意如何为每个组/年月对生成不同的标记,即使它们中的一些具有相同的组(" A")。