明确需求
1.排行榜的得分是如何计算的?
2.排行榜的时效性希望是多长?是否需要实时?
3.排行榜涉及到的用户数量是多少?日活、月活用户是多少?评估扫表数量以及QPS
4.是否希望找出指定玩家排名?
方案选择
数据量不大 + 只需要前N名的排行榜 -》 基于关系型数据库的方案
前提:数据小于百万行
例如, 每个月的排行榜可以被表示为一个包含用户ID和分数列的数据库表。当用户赢得比赛时,为用户更新积分。为了确定用户在排行榜上的排名,我们将按分数降序对表进行排序。
插入或更新
INSERT INTO leaderboard (user_id, score) VALUES ('mary1934', 1);
UPDATE leaderboard SET score = score + 1 WHERE user_id = 'mary1934';
为了获取用户的排名,我们将对排行榜表按照分数排序:
SELECT (@rownum := @rownum + 1) AS rank, user_id, score
FROM leaderboard
ORDER BY score DESC;
百万级数据 + 需要找出执行用户的排名 -》基于Redis的zset的方案
插入
Double newScore = jedis.zincrby("nameOfSet", 5, "targetElement");
查看前3名的用户
Set<String> topNNames = jedis.zrevrange("nameOfSet", 0, 2);
查看分数是 1-10 的用户
Set<String> namesInScoreArea = jeids.zrangeByScore("nameOfSet", 1, 10);
查看指定用户的排名
Long rank = jedis.zrank("nameOfSet", "userName");
附录:
Redis的有序集合(sorted set或zset)提供了一系列丰富的API来操作集合中的元素,每个元素都是带有一个浮点数分数的字符串。以下是zset在Redis中提供的全部API列表,这些命令用以增删查改元素,获取集合信息,以及执行范围和聚合操作。
增加或更新元素:
ZADD: 添加一个或多个成员,或更新已存在成员的分数。
移除元素:
ZREM: 移除一个或多个成员。
ZREMRANGEBYRANK: 移除给定排名范围内的所有成员。
ZREMRANGEBYSCORE: 移除给定分数范围内的所有成员。
获取元素:
ZRANGE: 通过索引区间返回有序集合成指定区间内的成员。
ZREVRANGE: 同ZRANGE,但返回结果是按分数从高到底的顺序。
ZRANGEBYSCORE: 返回有序集合中给定的分数区间的成员列表。
ZREVRANGEBYSCORE: 同ZRANGEBYSCORE,但顺序相反。
ZSCORE: 获取集合中成员的分数值。
ZRANK: 返回有序集合中指定成员的排名(从低到高)。
ZREVRANK: 返回有序集合中指定成员的排名(从高到低)。
ZCOUNT: 计算在有序集合中指定的分数区间内成员数量。
修改元素:
ZINCRBY: 为有序集合中指定成员的分数加上增量。
聚合操作:
ZINTERSTORE: 计算给定的一个或多个有序集的交集,并将结果存储到一个新的有序集合。
ZUNIONSTORE: 计算给定的一个或多个有序集的并集,并将结果存储到一个新的有序集合。
范围查询:
ZLEXCOUNT: 在有序集合中计算指定字典区间内成员数量。
ZRANGEBYLEX: 通过字典区间返回有序集合的成员。
ZREMRANGEBYLEX: 移除有序集合中给定的字典区间的所有成员。
获取集合大小:
ZCARD: 获取有序集合的成员数。
ZSCAN: 迭代有序集合中的元素(包括元素成员和元素分值)。
高级应用:
ZPOPMAX: 移除并返回有序集合中的最高分数成员。
ZPOPMIN: 移除并返回有序集合中的最低分数成员。
BZPOPMAX: 阻塞版本的ZPOPMAX。
BZPOPMIN: 阻塞版本的ZPOPMIN。