基于 redis 实现排名榜功能

更新日期: 2018-10-12 阅读次数: 14452 分类: Redis

MySQL 做排名功能很痛苦,因为我想不到简单的方法直接获取到某个用户,或是 Item 的排名,除非遍历。

而 Redis Sorted Set 恰好提供了便捷的方式。

如何更新分数

Sorted sets' scores can be updated at any time. Just calling ZADD against an element already included in the sorted set will update its score (and position) with O(log(N)) time complexity.

为排行榜插入数据

zadd 'teams_rank' 100 大象马拉松队

对应的 Laravel 代码

use Illuminate\Support\Facades\Redis;

Redis::zadd('teams_rank', $score, $team_name);

取出排名

zrank 'teams_rank' 大象马拉松队

默认是正序

  • zrange 默认取出来是从小到大排列。
  • zrevrange 才是倒序

分页的坑

与 MySQL 不同的是,redis zrange 的第二个参数是最后一个数据的下标。

例如,0 ~ 1 是两条记录,而不是取出一条记录。

举例,我要获取前5名的团队。

$offset = $request->get('offset', 0);
$limit = $request->get('limit', 5);

$teams = Redis::zrange(
	‘teams_rank’,
	$offset, 
	$offset + $limit - 1
);

实际就是

zrange 'teams_rank' 0 4

key 的格式问题

我想将尽可能多的数据整合到 key 中,例如

  • team name
  • team id
  • team score
  • team members

这样做的好处是,一次性 zrange 取出之后,可以直接解析返回给客户端。

但是,也会带来问题。即,如果 score 一直在变,那么更新操作就无法覆盖之前的数据。 之后再想增加新功能就非常难兼容之前的排行榜数据。

所以,最佳的方案是用 ID 即可,查出排行榜之后再用 ID 从 MySQL 中查出对应的详情。

问题

如何方便的获取排用用户的其他关联信息。

参考

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式