Redis Sorted Set 实现高并发排行榜的核心是利用其有序性、O(log N) 复杂度和原子操作:ZADD 原子更新分数,ZREVRANGE 实时分页查榜,ZREVRANK 结合 ZRANGE 精准定位用户排名及周边名次,配合周期性 key 归档与 ZREM/ZREMRANGEBYSCORE 清理保障内存可控。

用 Redis 的 Sorted Set 实现高并发排行榜,核心在于利用其天然的有序性、O(log N) 插入/更新复杂度和原子操作能力,完全避开数据库锁和频繁读写压力。
用 ZADD 原子更新分数,避免竞争
用户积分或得分变化时,直接调用 ZADD key score member。Redis 会自动插入新成员或更新已有成员分数,整个过程原子执行,无需额外加锁。例如用户 A 当前得分 1200,新行为带来 +50 分,只需:
ZADD rank:2024 1250 "uid:1001"- 若 uid:1001 已存在,分数自动覆盖;不存在则新增
- Java 中用 Lettuce 或 Jedis 调用
zAdd("rank:2024", 1250, "uid:1001")即可
分页查榜用 ZRANGE 或 ZREVRANGE,支持实时排名
排行榜通常按降序展示(分数高者靠前),用 ZREVRANGE key start stop WITHSCORES 获取指定范围的成员及分数。例如取 Top 100:
ZREVRANGE rank:2024 0 99 WITHSCORES- 返回结果天然按分数从高到低排列,下标即“名次”(注意:下标从 0 开始,第 1 名对应索引 0)
- Java 中解析响应时,每两个元素为一组(member + score),可直接封装为 RankItem 对象
精准获取某用户排名和附近名次,用 ZREVRANK 和 ZRANGE
用户想知道自己排第几,或查看自己上下 5 名——不能全量拉榜。推荐组合操作:
立即学习“Java免费学习笔记(深入)”;
- 先用
ZREVRANK key member获取该用户逆序排名(即从高到低的索引,Top1 返回 0) - 再用
ZREVRANGE key (rank-5) (rank+5) WITHSCORES拉取周边数据(注意边界检查,避免负数或越界) - Java 中建议封装成
getRankAround(String userId, int offset)方法,内部完成两次命令调用
定期归档与内存控制,避免 key 无限膨胀
长期运行的排行榜需考虑数据生命周期。不要依赖过期时间(Sorted Set 不支持成员级过期),而是主动管理:
- 按周期建 key,如
rank:2024Q3、rank:daily:20240820,便于清理 - 用
ZREM key member清理无效用户(如注销账号) - 用
ZREMRANGEBYSCORE key -inf (threshold)删除低分长尾(如分数低于 10 的用户) - 结合 Redis 内存策略(如 maxmemory + allkeys-lru),防止 OOM
不复杂但容易忽略:ZSET 的 score 是 double 类型,精度问题可能导致相同分数排序不稳定;如需严格一致,可在 score 后拼接唯一 ID(如 score + "_" + uid),再转为数值存储。


















