2012-03-12 111 views
1

如果我想有只为查询:卡桑德拉高分

1. Username, Xp, OtherUserData 
2. User with the N-th highest Xp 

我怎么会做的数据结构和查询。

对于1,我会类似的结构: {用户名:{XP中,OtherUserData}}

我只是要对所有用户提供2.做一个查询,或者是有一个更好的选择?

回答

3

我不能完全肯定你问,但这里有一个猜测(是XP用户的得分?):

存储用户数据,为每个用户创建一个行,键入他们的用户名(假设这是独特的,固定的),然后对每个项目的列:

username -> Xp  other ... 
      value value ... 

为了保持高得分表,使用单个行(可能在不同的列系列),与所有用户(或与上述一个某些阈值),列名称为分数,并指定一个数字(LongType)比较器,以便列按照分数排序:

highscores -> 1000  1001  99999999 ... 
       user123 user345 user789 ... 

然后,您可以通过查询此排序行中的最后或前N列来检索最高N个分数。如果它太大,你可以从这一行删除低分。

更新:正如您指出的那样,多个用户可能具有相同的分数。快速和肮脏的解决办法是使价值用户的列表:

highscores -> 1000  
       "user123, user567, user899" 

这是可以容忍的,如果你是不可能得到大量同分的用户,虽然尴尬,因为你需要阅读,更新并写入列表。

您可以使用超级列,但通常不建议这些列。

否则,您可能可以使用composite column keys,以便您可以区分用户,但保留按分数排序的列。

+0

是,XP =经验值 – Daniel 2012-03-14 12:35:00

+0

我怎么能处理2个用户与TE同样的比分? – Daniel 2012-03-14 12:38:11

+0

查看最新的答案... – DNA 2012-03-14 12:59:52

1

仅使用一行进行分类可能会非常危险,因为每行只能在Cassandra的一个实例上进行。因此,系统中的所有玩家都会在一台机器上写入该ONE密钥,从而有可能导致群集中的节点过载。这可能会导致所有群集失败,原因是尝试恢复时,尝试恢复正在关闭的节点负载的节点的怪异连锁反应(我们在我们的生产机器上发生过这种情况,因为存在硬编码测试键会收到所有写入所有人的单独行)。

一个解决办法是通过自己的分数来斗你的用户:

  • 0-> 1000 = bucketA
  • 1001 - > 5000 = bucketB
  • 5001 - > 15000 = bucketC 等。

我会建议让较低级别的桶变小。

写你与列名作为复合柱: 的CompositeType

因此,例如,如果你使用UUID作为玩家ID和多头的分数(LongType,UTF8Type)我们将有:

  • 500089845:f7bc41d8-c1c6-489c-bb2c-f86fccc7681c
  • 4100085589:2ae91e9f-1512-4ef8-8441-9f48e21fb11b

你可以做它与串联字符串,但你必须写所有的前导零,以便UTF8比较器,但所有的分数在正确的顺序。

  1. 000000500089845:f7bc41d8-c1c6-489c-bb2c-f86fccc7681c
  2. 000004100085589:2ae91e9f-1512-4ef8-8441-9f48e21fb11b

没有前导零将

  1. 000004100085589: 2ae91e9f-1512-4ef8-8441-9f48e21fb11b
  2. 000000500089845:f7bc41d8-c1c6-489c-bb2c-f86fccc7681c

这种方式你不必阅读修改矢量,json,复合或超级列的人有相同的分数,因为每个分数是一个单独的列。你可以在列中放置任何你想要的信息,这样你就可以在一次读取中获得所有信息(而不必通过另一次读取获取播放器信息,我个人会用一个json或一个字节序列化的对象来包含我需要的所有东西) 。

要阅读:你想要的行上的反向范围查询(最高优先)将做的伎俩。

只要您有足够的行触及所有节点,即可在整个令牌环上共享负载,您也可以通过更改存储桶的性质来改变系统的风格。

希望这是有益