cassandra高分

时间:2012-03-12 17:51:49

标签: database database-design cassandra data-modeling

如果我只想查询:

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

我如何进行数据结构和查询。

对于1.我的结构类似于: {用户名:{Xp,OtherUserData}}

我是否只需要对所有用户进行2.查询,还是有更好的选择?

2 个答案:

答案 0 :(得分: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以便区分用户,但保持按分数排序的列。

答案 1 :(得分:1)

只使用一行进行分类可能非常危险,因为每一行只能在一个Cassandra实例上。因此,系统中的所有播放器都会在一台计算机上写入该一键 - 存在集群中节点过载的风险。这可能会导致所有集群失败,因为节点试图在尝试恢复期间承担被击落节点负载的奇怪连锁反应(我们在生产机器上发生这种情况,因为存在硬编码测试的错误key将接收所有针对每个人的单独行中的写入。)

解决方案是按照他们的分数来吸引用户:

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

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

使用列名作为复合来编写列: CompositeType(LongType,UTF8Type)

所以,例如,如果您使用UUID作为玩家ID并且将其作为分数,那么我们将拥有:

  • 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
  3. 没有前导零的

    将是

    1. 000004100085589:2ae91e9f-1512-4ef8-8441-9f48e21fb11b
    2. 000000500089845:f7bc41d8-c1c6-489c-bb2c-f86fccc7681c
    3. 这样,您不必阅读修改具有相同分数的人的矢量,json,复合或超级列,因为每个分数都是单独的列。您可以在列中放置您想要的任何信息,以便您可以在一次读取中获取所有内容(无需使用另一个读取获取播放器信息,我个人会使用包含我需要的所有内容的json或字节序列化对象)

      要阅读:您想要的行上的反向范围查询(最高的第一个)将起到作用。

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

      希望这是有帮助的