当前位置:首页 > 文章列表 > 数据库 > Redis > Redis ZSET 排行榜完整工作流:加分、TOP榜、我的排名和周榜归档

Redis ZSET 排行榜完整工作流:加分、TOP榜、我的排名和周榜归档

来源:17golang原创 2026-06-15 17:12:14 0浏览 收藏

很多业务一开始做排行榜时,需求看起来很简单:用户加分后,把前 100 名展示出来,再给当前用户看一下“我的排名”。但真正写到线上,很快会遇到几个细节:分数怎么累加、TOP 榜怎么分页、用户自己的排名怎么查、同分怎么排、周榜结束后怎么归档。

这篇文章按完整工作流来拆 Redis ZSET 排行榜。我们不只看一条命令,而是从 Key 设计、写入、查询、分页、同分规则到周期榜单收尾,整理成一套可以直接落地的路线。

目录
  • 目标和边界:先把排行榜类型定清楚
  • 先说结论:ZSET 负责排名,业务负责规则
  • 全流程总览:从加分到分页展示
  • 阶段 1:设计排行榜 Key 和 member
  • 阶段 2:写入分数和读取 TOP 榜
  • 阶段 3:查询我的排名和分页数据
  • 阶段 4:处理同分、周榜归档和过期清理
  • 我的推荐流程
  • 容易踩坑
  • 速查表

目标和边界:先把排行榜类型定清楚

先把边界定清楚。本文讨论的是“分数越高排名越靠前”的排行榜,比如积分榜、活动榜、答题榜、贡献榜。数据量可以从几千到几百万,读多写也不少,需要快速拿到 TOP 列表和某个用户的名次。

不在本文范围里的场景有两类:第一类是复杂多维排序,例如分数、等级、地区、会员等级一起影响排名;第二类是强审计积分系统,例如每一分都要追溯流水。这些仍然可以用 ZSET 做展示层,但需要额外的业务表保存明细。

先说结论:ZSET 负责排名,业务负责规则

Redis ZSET 最适合承担排行榜的“排序视图”:member 放用户标识,score 放用于排名的数值。加分用 ZINCRBY,TOP 榜用 ZREVRANGE,我的名次用 ZREVRANK,我的分数用 ZSCORE

但是有一点要提前记住:ZSET 只负责按 score 排序。同分时到底按时间、用户编号,还是并列名次,要由业务提前定规则。规则定不清,后面页面展示和用户反馈都会变得很难解释。

全流程总览:从加分到分页展示

下面这张图是最常见的排行榜主流程:用户行为产生分数,写入 ZSET 后,页面可以同时拿 TOP 榜、我的排名和分页数据。

Redis ZSET 排行榜从加分到 TOP 榜、我的排名和分页展示的完整流程

阶段 目标 关键动作 检查点
阶段 1 定 Key 和成员 按活动、周期、榜单类型拆 Key 不同榜单不会混在一起
阶段 2 写入和读取 用 ZINCRBY 加分,用 ZREVRANGE 取榜 TOP 列表顺序正确
阶段 3 查个人位置 用 ZREVRANK 和 ZSCORE 查排名与分数 我的排名从 1 开始展示
阶段 4 周期收尾 归档、设置过期、清理旧榜 历史榜可查,内存可控

阶段 1:设计排行榜 Key 和 member

目标:让每个榜单都有明确边界。一个推荐的 Key 结构是:

rank:{biz}:{period}:{id}

示例:
rank:activity:week:2026-W25
rank:course:day:2026-06-15
rank:game:season:S12

biz 表示业务类型,period 表示日榜、周榜、赛季榜,id 表示具体周期。这样做的好处是查询简单,归档也简单。周榜结束后,只要处理这一周的 Key,不会影响日榜或总榜。

member 建议放稳定的用户 ID,例如 user:10086。如果你的页面需要昵称、头像、等级,不要把这些资料塞进 ZSET。排行榜只保存排名视图,用户资料从缓存或数据库批量补齐。

阶段 2:写入分数和读取 TOP 榜

目标:用户产生积分变化后,能快速反映到榜单里。最直接的写法是用 ZINCRBY 累加分数。

ZINCRBY rank:activity:week:2026-W25 10 user:10086
ZINCRBY rank:activity:week:2026-W25 5 user:10087

读取前 10 名时,用倒序读取,因为我们要分数高的排在前面:

ZREVRANGE rank:activity:week:2026-W25 0 9 WITHSCORES

检查点有两个:第一,分数必须是业务确认后的结果,不要把未支付、未审核、可撤销的分数直接写入正式榜;第二,页面展示最好把 member 批量转成用户资料,避免循环查数据库。

阶段 3:查询我的排名和分页数据

目标:用户打开页面时,既能看到榜单,也能知道自己在哪。我的排名可以这样查:

ZREVRANK rank:activity:week:2026-W25 user:10086
ZSCORE rank:activity:week:2026-W25 user:10086

ZREVRANK 返回的是从 0 开始的下标,展示给用户时要加 1。如果返回空值,说明这个用户还没上榜,可以展示“暂未上榜”或“完成一次任务后参与排名”。

分页本质上还是范围查询。比如每页 20 条,第 3 页可以换算成起止位置:

page = 3
size = 20
start = (page - 1) * size
stop = start + size - 1

ZREVRANGE rank:activity:week:2026-W25 40 59 WITHSCORES

这里的检查点是:分页不要一次性把全榜拉回应用层再截取。ZSET 已经提供了范围读取,应用层只负责计算下标和补齐用户资料。

阶段 4:处理同分、周榜归档和过期清理

排行榜上线后,最容易被忽略的是同分规则和周期榜收尾。下面这张图把这两个动作放到同一条工作流里:先确定同分排序,再查询排名,周榜结束后归档并设置过期时间。

Redis ZSET 排行榜同分处理、排名查询、周榜归档和过期清理流程

同分规则怎么定

ZSET 的 score 相同时,还会按 member 的字典顺序参与排序。这个规则是确定的,但不一定符合你的业务。例如活动榜希望“先达到该分数的人排前面”,那就不能只把用户 ID 当 member 然后直接展示。

常见做法有两种:

  • 并列展示:同分用户展示同一名次,页面文案说明“同分并列”。这种做法简单,但分页和奖励边界要提前定义。
  • 组合分数:把主分数和时间序号组合成一个可排序分数,例如主分数越高越靠前,同分时更早完成的人更靠前。要注意数值范围,避免超过安全整数精度。

如果业务对奖励边界很敏感,我更推荐把积分流水和最终发奖名单落到数据库,再用 ZSET 做实时展示。这样既有实时榜,也有可审计的最终结果。

周榜如何归档

周榜结束时,不建议立刻删除旧 Key。可以先把前 N 名写入历史榜单表,或者复制一份结果到只读缓存,再给旧 Key 设置过期时间:

EXPIRE rank:activity:week:2026-W25 604800

这样用户在活动结束后一段时间内仍能查看结果,后台也有时间完成发奖、申诉和数据核对。等窗口期结束,Redis 会自动清理旧榜,内存压力也可控。

我的推荐流程

如果从零实现一个 Redis 排行榜,我会按下面顺序推进:

  1. 先写清楚榜单类型:日榜、周榜、总榜,还是活动榜。
  2. 确定 Key 结构,保证不同活动和周期互不影响。
  3. 确定 member 只放稳定用户 ID,用户资料走批量补全。
  4. ZINCRBY 写分,用 ZREVRANGE 读 TOP 榜。
  5. ZREVRANKZSCORE 做“我的排名”。
  6. 提前确认同分和奖励边界,不要等用户反馈后再改。
  7. 周期结束后归档结果,再给旧榜设置过期时间。

容易踩坑

  • 只设计 TOP 榜,不设计我的排名:页面会多一次全榜扫描,数据量大时很慢。
  • 把昵称头像放进 member:用户改名后榜单数据会混乱,补资料也麻烦。
  • 同分规则不明确:奖励边界最容易产生争议,必须提前写进需求。
  • 周期 Key 不带日期:日榜、周榜、历史榜会互相覆盖。
  • 旧榜永不过期:活动多了以后,Redis 内存会被历史数据慢慢吃掉。

速查表

需求 Redis 命令 注意点
用户加分 ZINCRBY 只写确认后的分数
读取 TOP 榜 ZREVRANGE WITHSCORES 下标从 0 开始
查询我的名次 ZREVRANK 展示时加 1
查询我的分数 ZSCORE 空值代表未上榜
周期榜收尾 EXPIRE 先归档,再设置过期

总结

Redis ZSET 做排行榜的核心并不复杂:score 排序,member 标识用户,范围查询拿榜单,排名查询找个人位置。真正决定系统是否好用的,是 Key 设计、同分规则、分页策略和周期收尾。

把这几件事提前设计好,排行榜就不是几条零散命令,而是一条完整工作流:加分进入 ZSET,页面读取 TOP 榜和我的排名,周期结束后归档并清理旧 Key。这样既能支撑实时展示,也能给后续运营和发奖留出清楚的边界。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
PHP 旧 MD5 密码如何平滑迁移到 password_hash:兼容登录与自动升级完整流程PHP 旧 MD5 密码如何平滑迁移到 password_hash:兼容登录与自动升级完整流程
上一篇
PHP 旧 MD5 密码如何平滑迁移到 password_hash:兼容登录与自动升级完整流程
Java CompletableFuture 多接口聚合完整流程:并行调用、超时兜底和结果合并
下一篇
Java CompletableFuture 多接口聚合完整流程:并行调用、超时兜底和结果合并
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • MiMo Code - 小米大模型团队开源的新一代 AI 编程助手
    MiMo Code
    MiMo Code 是小米大模型团队开源的新一代 AI 编程助手,面向开发者提供代码理解、生成与辅助开发能力,适合作为 AI 编程工具收藏和体验。
    67次使用
  • TRAE Work - 字节跳动推出的 AI 原生工作台
    TRAE Work
    TRAE AI IDE | 国内首款 AI 原生集成开发环境,深度集成 Doubao-1.5-pro 与 DeepSeek 模型,支持中文自然语言一键生成完整代码框架,实时预览前端效果并智能修复 BUG。首创 Builder 模式实现需求到代码的自动化开发,兼容 Windows/macOS 系统,官网下载即用。
    94次使用
  • MeloLab - 一站式 AI 音乐生成与编辑平台
    MeloLab
    MeloLab 是一款 AI 音乐生成工具,可根据文本创意生成歌曲、人声、混音、分轨和背景音乐,适合创作者快速制作音乐素材。
    75次使用
  • ChatExcel酷表:告别Excel难题,北大团队AI助手助您轻松处理数据
    ChatExcel酷表
    ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
    8728次使用
  • Any绘本:开源免费AI绘本创作工具深度解析
    Any绘本
    探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
    9143次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码