如果我只想查询:
1. Username, Xp, OtherUserData
2. User with the N-th highest Xp
我如何进行数据结构和查询。
对于1.我的结构类似于: {用户名:{Xp,OtherUserData}}
我是否只需要对所有用户进行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将接收所有针对每个人的单独行中的写入。)
解决方案是按照他们的分数来吸引用户:
我建议让较低级别的存储桶变小。
使用列名作为复合来编写列: CompositeType(LongType,UTF8Type)
所以,例如,如果您使用UUID作为玩家ID并且将其作为分数,那么我们将拥有:
你可以使用连接字符串来完成它,但你必须写出所有前导零,这样UTF8比较器才会按正确的顺序排列所有分数。
将是
这样,您不必阅读修改具有相同分数的人的矢量,json,复合或超级列,因为每个分数都是单独的列。您可以在列中放置您想要的任何信息,以便您可以在一次读取中获取所有内容(无需使用另一个读取获取播放器信息,我个人会使用包含我需要的所有内容的json或字节序列化对象)
要阅读:您想要的行上的反向范围查询(最高的第一个)将起到作用。
只要您有足够的行来触摸所有节点,您就可以通过更改存储桶的性质来改变系统的风格,从而在令牌环上共享负载。
希望这是有帮助的