首页/数据/数据库速查/排行榜运营细节(同分、分页、周期榜)
Redis 运维与场景124 条

排行榜运营细节(同分、分页、周期榜)

ZSet 做排行榜的实战要点:同分顺序由 member 字典序决定、分页用 ZREVRANGE 区间、周期榜按 key 生成或用 ZUNIONSTORE 合并。

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

排行榜运营细节

用有序集合做排行榜,难点不在写入,而在运营细节:同分时谁排前面、翻页怎么取、周榜月榜怎么生成。分数相同的情况下顺序由成员名决定,因此想要「先到先得」必须把时间信息编进分数;周期榜可以用按天分键再合并的方式生成。

基本信息

写入ZADD 键 分数 成员,分数相同会覆盖旧分数
取榜单ZREVRANGE 键 起始 结束 WITHSCORES,从高到低
查名次ZREVRANK 键 成员,复杂度与集合规模对数相关
合并榜单ZUNIONSTORE 支持多键相加并指定权重与聚合方式
名次起点排名从 0 开始,展示时通常加一

典型使用场景

  • 日榜与周榜:按日期分键写入,周期结束时合并成一个榜单键
  • 积分排行:分数即积分,同分时需要稳定的展示顺序
  • 活动榜单:活动结束前只展示前若干名,避免全量拉取
  • 个人名次查询:用户查看自己在第几名,用查名次命令即可
  • 榜单快照:定期把结果落到数据库,用于历史回看与对账

常用操作

常用操作
ZADD lb:day 100 u1 100 u2 90 u3
ZREVRANGE lb:day 0 2 WITHSCORES      # 取前三名
ZREVRANK lb:day u3                   # 查某人名次(0 起)
ZSCORE lb:day u1                     # 查某人分数
ZREVRANGE lb:day 50 60 WITHSCORES    # 取第 51 到 61 名(分页)
# 周榜 = 两天的日榜相加(权重都为 1)
ZUNIONSTORE lb:week 2 lb:1012 lb:1013 WEIGHTS 1 1 AGGREGATE SUM
EXPIRE lb:week 604800                # 周期榜设置过期,避免长期堆积
# 同分先到先得:把时间编进分数(分数整体左移,末尾接反向时间)
# 例如 score = 业务分 * 10000000000 + (最大时间戳 - 完成时间戳)

操作与注意点

操作用途注意事项
从高到低取范围取榜单前若干名用错命令会得到升序结果
查名次个人名次展示排名从零开始,展示要加一
合并榜单生成周期榜权重与聚合方式要写清楚
分页取段榜单翻页不要全量拉取,按区间取
设过期清理临时榜单周期榜不设过期会长期占内存
同分顺序由成员名决定:需要对用户友好时,把「更早完成」编码成更大的分数尾巴,排序才是稳定的。
用浮点数直接编时间戳会丢精度:分数放大成整数运算,才能保证排序不出现错乱。

易错点

  • 用升序命令做从高到低展示:顺序完全相反,榜单显示错误
  • 分数用浮点直接拼时间戳:精度丢失导致排序错乱,同分顺序随机
  • 全量拉取千万级榜单:内存与网络压力大,应改为按区间分页
  • 周期榜不设过期也不合并:临时键长期堆积,内存缓慢上涨

数据来源与参考

  • Redis 官方文档: ZRANK
  • Redis 官方文档: ZUNIONSTORE

相关工具

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