Skip to content

P15 Redis 如何实现上亿用户实时积分排行榜 ​

面试题:上亿用户,积分实时变化,要求实时展示 TOP 排行,怎么实现?

推荐方案:Redis ZSet(有序集合) ​

text
key:rank:score
member:userId
score:积分

更新积分(原子累加):

bash
ZINCRBY rank:score 100 10001

查某用户排名(从 0 开始,+1 是第几名):

bash
ZREVRANK rank:score 10001

查 Top N:

bash
ZREVRANGE rank:score 0 99 WITHSCORES   # 前 100 名

查指定排名区间的用户:ZREVRANGE rank:score 100 199。

为什么用 ZSet ​

  • 跳表 + 哈希表实现:更新 O(logN)、查询排名 O(logN);
  • 所有操作在 Redis 内存中完成,实时性极好;
  • 天然支持"按分数排序",正序倒序都行。

大规模优化点 ​

1. 分桶(分段排名) ​

一亿用户放一个 ZSet,key 过大、内存集中。方案:

text
按积分段分桶:rank:0-100、rank:100-1000 ...
  • 更新时直接落入对应桶;
  • 查总排名:先算高于自己积分段的用户总数(各桶 SCARD 累加),再算本桶内名次;
  • 取 Top N:从最高分段桶往下取,拼够 N 个。

2. 分数设计 ​

积分是整数时,排名按积分即可。需要先到先得等规则时,可以用"积分×权重 + 时间戳"合成 score,或维护二级排序。

3. 一致性 ​

  • 积分变化高并发:用 Lua 脚本原子执行"加分 + 更新排行榜",避免重复累加;
  • 排行榜与业务库数据最终一致:异步同步,允许短暂延迟;
  • 榜单缓存:Top N 结果缓存几秒,避免每次查询都扫 ZSet。

4. 数据持久化 ​

  • 开启 RDB/AOF 防止重启丢榜;
  • 榜单数据可以定期快照到 DB,供活动结算使用。

加分点 ​

  • 对比方案:DB 每次 order by limit 查询,百万级数据就扛不住了,ZSet 才是实时榜单标配;
  • 活动型榜单按活动维度建 key,活动结束删除;
  • 查询"我的排名 + 前后 10 名"用 ZRANK/ZREVRANGE 组合。

一句话总结 ​

积分排行榜用 Redis ZSet(member=用户、score=积分),ZINCRBY 更新、ZREVRANGE 取 TopN、ZREVRANK 查排名;超大规模按积分段分桶 + 桶内名次累加实现。

基于 VitePress 重建