题目:Redis的zset实现排行榜,实现分数相同按照时间顺序排序,怎么做?
难度:high
评分:⭐⭐⭐⭐☆☆(3/5)
zset的排序规则只支持分数排序,如果要实现相同分数按照时间排序有两种思路,一个是在分数的后面跟上时间戳,作为分数的补充内容一起进行排序,另外就是在 zset 的 value 中保存时间,读取相同分数的内容后,在业务端进行二次排序,都能实现同分数后按照其他规则排序
优点:
两种思路都提到- 分数拼接方案抓到
不足:
❌ 遗漏分数拼接具体实现(如 score * 1e13 + timestamp)- ❌ 遗漏时间戳精度选择(毫秒 vs 微秒)- ❌ 遗漏同毫秒内排序边界情况- ❌ 遗漏业务端二次排序在分页场景的代价- ❌ 遗漏排行榜扩展(Top N、我的排名、实时推送)
核心考点:考察 Zset 排行榜的工程化实现能力,理解分数拼接技巧。
知识点拆解:
关键命令:
面试官您好,Zset 排行榜分数相同按时间排序有两种方案。
方案一是分数拼接:分数 = 业务分数 × 1e13 + 时间戳(毫秒)。例如分数 100,时间戳 1690000000000,拼接后是 10016900000000000。Zset 原生支持,查询高效。缺点是时间戳精度限制,毫秒内无法区分。
方案二是业务端二次排序:Zset 存 score + member,member 中包含时间戳,读取后在业务端排序。灵活,支持任意排序规则。缺点是分页场景困难(需加载全部数据)、性能差。
我推荐方案一,分数拼接。时间戳用毫秒够用,同毫秒概率极低,不影响业务。
排行榜常见扩展:Top N 用 ZREVRANGE 0 N-1,我的排名用 ZREVRANK O(log n),分数变化用 Pub/Sub 或 Redis Stream 推送,分维度(实时/小时/日/周榜)用多个 Zset。
生产实践:Top 1000 排行榜,分数拼接毫秒时间戳,ZADD 更新分数,Pub/Sub 推送变化,客户端订阅实时更新。分维度排行榜用多个 Zset,每个 Zset 独立过期时间。