Redis ZSET 排行榜完整工作流:加分、TOP榜、我的排名和周榜归档
很多业务一开始做排行榜时,需求看起来很简单:用户加分后,把前 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 榜、我的排名和分页数据。

| 阶段 | 目标 | 关键动作 | 检查点 |
|---|---|---|---|
| 阶段 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:处理同分、周榜归档和过期清理
排行榜上线后,最容易被忽略的是同分规则和周期榜收尾。下面这张图把这两个动作放到同一条工作流里:先确定同分排序,再查询排名,周榜结束后归档并设置过期时间。

同分规则怎么定
ZSET 的 score 相同时,还会按 member 的字典顺序参与排序。这个规则是确定的,但不一定符合你的业务。例如活动榜希望“先达到该分数的人排前面”,那就不能只把用户 ID 当 member 然后直接展示。
常见做法有两种:
- 并列展示:同分用户展示同一名次,页面文案说明“同分并列”。这种做法简单,但分页和奖励边界要提前定义。
- 组合分数:把主分数和时间序号组合成一个可排序分数,例如主分数越高越靠前,同分时更早完成的人更靠前。要注意数值范围,避免超过安全整数精度。
如果业务对奖励边界很敏感,我更推荐把积分流水和最终发奖名单落到数据库,再用 ZSET 做实时展示。这样既有实时榜,也有可审计的最终结果。
周榜如何归档
周榜结束时,不建议立刻删除旧 Key。可以先把前 N 名写入历史榜单表,或者复制一份结果到只读缓存,再给旧 Key 设置过期时间:
EXPIRE rank:activity:week:2026-W25 604800
这样用户在活动结束后一段时间内仍能查看结果,后台也有时间完成发奖、申诉和数据核对。等窗口期结束,Redis 会自动清理旧榜,内存压力也可控。
我的推荐流程
如果从零实现一个 Redis 排行榜,我会按下面顺序推进:
- 先写清楚榜单类型:日榜、周榜、总榜,还是活动榜。
- 确定 Key 结构,保证不同活动和周期互不影响。
- 确定 member 只放稳定用户 ID,用户资料走批量补全。
- 用
ZINCRBY写分,用ZREVRANGE读 TOP 榜。 - 用
ZREVRANK和ZSCORE做“我的排名”。 - 提前确认同分和奖励边界,不要等用户反馈后再改。
- 周期结束后归档结果,再给旧榜设置过期时间。
容易踩坑
- 只设计 TOP 榜,不设计我的排名:页面会多一次全榜扫描,数据量大时很慢。
- 把昵称头像放进 member:用户改名后榜单数据会混乱,补资料也麻烦。
- 同分规则不明确:奖励边界最容易产生争议,必须提前写进需求。
- 周期 Key 不带日期:日榜、周榜、历史榜会互相覆盖。
- 旧榜永不过期:活动多了以后,Redis 内存会被历史数据慢慢吃掉。
速查表
| 需求 | Redis 命令 | 注意点 |
|---|---|---|
| 用户加分 | ZINCRBY | 只写确认后的分数 |
| 读取 TOP 榜 | ZREVRANGE WITHSCORES | 下标从 0 开始 |
| 查询我的名次 | ZREVRANK | 展示时加 1 |
| 查询我的分数 | ZSCORE | 空值代表未上榜 |
| 周期榜收尾 | EXPIRE | 先归档,再设置过期 |
总结
Redis ZSET 做排行榜的核心并不复杂:score 排序,member 标识用户,范围查询拿榜单,排名查询找个人位置。真正决定系统是否好用的,是 Key 设计、同分规则、分页策略和周期收尾。
把这几件事提前设计好,排行榜就不是几条零散命令,而是一条完整工作流:加分进入 ZSET,页面读取 TOP 榜和我的排名,周期结束后归档并清理旧 Key。这样既能支撑实时展示,也能给后续运营和发奖留出清楚的边界。
PHP 旧 MD5 密码如何平滑迁移到 password_hash:兼容登录与自动升级完整流程
- 上一篇
- PHP 旧 MD5 密码如何平滑迁移到 password_hash:兼容登录与自动升级完整流程
- 下一篇
- Java CompletableFuture 多接口聚合完整流程:并行调用、超时兜底和结果合并
-
- 数据库 · Redis | 2小时前 | Redis · Streams · 消费者组 · Pending · XACK · 消息堆积 消费者组 XACK XPENDING XAUTOCLAIM Redis Streams
- Redis Streams 消费者组消息堆积怎么办:从 XPENDING 到 XACK 一步步排查
- 385浏览 收藏
-
- 数据库 · Redis | 2天前 | Redis · 数据库 · HyperLogLog · UV统计 · redis hyperloglog UV统计 PFADD PFCOUNT 去重计数
- Redis HyperLogLog 统计 UV 实战:PFADD、PFCOUNT 和误差边界怎么用
- 180浏览 收藏
-
- 数据库 · Redis | 2天前 | Redis · 消息队列 · Stream · 消费组 · redis 消息队列 Redis Stream 消费组 XREADGROUP XACK XPENDING XAUTOCLAIM
- Redis Stream 消息队列实战:消费组、ACK 和失败重投怎么配
- 187浏览 收藏
-
- 数据库 · Redis | 2星期前 |
- RedisLua脚本实现复杂正则匹配方法
- 438浏览 收藏
-
- 数据库 · Redis | 2星期前 |
- Redis客户端缓冲区优化技巧
- 146浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- MiMo Code
- MiMo Code 是小米大模型团队开源的新一代 AI 编程助手,面向开发者提供代码理解、生成与辅助开发能力,适合作为 AI 编程工具收藏和体验。
- 67次使用
-
- TRAE Work
- TRAE AI IDE | 国内首款 AI 原生集成开发环境,深度集成 Doubao-1.5-pro 与 DeepSeek 模型,支持中文自然语言一键生成完整代码框架,实时预览前端效果并智能修复 BUG。首创 Builder 模式实现需求到代码的自动化开发,兼容 Windows/macOS 系统,官网下载即用。
- 94次使用
-
- MeloLab
- MeloLab 是一款 AI 音乐生成工具,可根据文本创意生成歌曲、人声、混音、分轨和背景音乐,适合创作者快速制作音乐素材。
- 75次使用
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 8728次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 9143次使用
-
- 分享Redis高可用架构设计实践
- 2023-01-24 286浏览
-
- Go与Redis实现分布式互斥锁和红锁
- 2022-12-22 117浏览
-
- Redis的各项功能解决了哪些问题?
- 2023-02-18 185浏览
-
- Go+Redis实现延迟队列实操
- 2023-02-23 426浏览
-
- 分享 echo-framework 项目基础框架
- 2023-01-11 134浏览

