首页/数据/数据库速查/排行榜场景(分页、并列与周期榜)
Redis 命令96 条

排行榜场景(分页、并列与周期榜)

ZSet 是排行榜的标准实现:ZINCRBY 计分、ZREVRANGE 取 TopN、ZREVRANK 取我的名次;周期榜用独立键 + 定时合并。

数据库速查数据更新于 2026-10-13

排行榜场景是什么

排行榜的标准实现是有序集合:ZINCRBY 累加分数做打点,ZREVRANGE 取 TopN,ZREVRANK 查某个成员的名次,ZSCORE 读当前分数。日榜、周榜、月榜各自建键,再用 ZUNIONSTORE 或定时任务合并汇总。名次从 0 开始,同分时按成员字典序排列,需要稳定顺序就得用复合分数。

基本信息

核心命令ZINCRBY / ZREVRANGE / ZREVRANK / ZSCORE / ZUNIONSTORE
排名约定0 为第一名;同分按成员字典序
分页ZREVRANGE start stop 或 ZRANGE 加 REV
并列控制用复合分数(分数加时间戳小数位)固定顺序
成本单条读写与查询名次均为 O(logN)

典型使用场景

  • 日榜周榜月榜:各自建键,定时任务滚动合并
  • 实时积分榜:ZINCRBY 打点后立刻刷新 TopN
  • 我的排名:ZREVRANK 加 ZSCORE 组合展示
  • 奖励结算:按排名取前 N 名并核对分数,避免漏发
  • 多场次汇总:ZUNIONSTORE 把多个榜单按分数合并
  • 去重计分:同一成员只保留一个分数,天然避免重复上榜

完整流程

完整流程
ZINCRBY rank:daily 1 user:88              # 打点,返回累加后的分数
ZINCRBY rank:daily 10 user:99             # 加不同权重
ZREVRANGE rank:daily 0 9 WITHSCORES       # 取 Top10 带分数
ZREVRANK rank:daily user:88               # 我的名次,0 基
ZSCORE rank:daily user:88                 # 我的分数
ZCARD rank:daily                          # 参与人数
ZREMRANGEBYRANK rank:daily 1000 -1        # 只保留前 1000 名,控制内存
ZUNIONSTORE rank:week 7 rank:day:1 rank:day:2 AGGREGATE SUM   # 周榜合并
EXPIRE rank:day:1 604800                  # 明细榜保留一周便于复盘

命令对照

命令作用注意点
ZINCRBY累加成员分数分数可用浮点,累计过多会有精度误差
ZREVRANGE取 TopN 或分页全量取 0 -1 在大榜单上开销大
ZREVRANK查成员名次成员不存在返回 nil
ZSCORE读当前分数与 ZREVRANK 一起用可做排名卡片
ZUNIONSTORE多榜合并需要指定聚合方式,默认求和
面向 UI 的「我的排名」在大榜单上也是 O(logN),可以放心用;但 TopN 与周围名次一起展示时需要两次查询,注意合并结果。
周期榜要规划过期与清理:日榜可保留一周便于复盘,周榜合并完成后即可清理明细键,否则历史榜单会持续占用内存。

易错点

  • 榜单键只增不减且不设过期,历史榜单不断堆积撑大内存
  • 同分成员顺序不稳定,展示时名次看起来「乱跳」,需要复合分数固定顺序
  • 用浮点分数累加,长时间运行后出现精度误差导致名次错位
  • 奖励结算按名次取前 N 名但未加锁,结算期间榜单仍在变动造成漏发或重发
  • 合并周榜时聚合方式选错(默认求和),把平均分场景算成了总分

数据来源与参考

  • Redis 官方文档: ZRANGE
  • Redis 官方文档: ZINCRBY

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌