并发场景——实时排行榜设计

实时排行榜是Redis ZSet数据结构最经典的落地应用,在面试中,不仅要回答出用Redis ZSet,更要主动抛出同分怎么排,几千万行数据怎么存这种进阶问题。(当然也是被吐槽面试造航母,工作拧螺丝的贡献者🙂)

核心原理:Redis ZSet

数据结构:ZSet底层是跳表+字典

复杂度

  • 插入/更新分数(ZADD):
  • 获取排名(ZRANK):
  • 获取前N名(ZREVRANGE):

核心命令

  • ZADD leaderboard <score> <user_id>:更新分数
  • ZINCRBY leaderboard <increment> <user_id>:增加分数(如杀敌+1)
  • ZREVRANGE leaderboard 0 9 WITHSOCRES:获取前十名(由高到低)
  • ZRANK/ZREVRANK:获取某人排名

当然,只答出用Redis ZSet来解决虽然已经是正确答案了,但我们面试终究是为了体现自己很懂这个领域的知识嘛,所以我们就要主动抛出进阶场景。

进阶场景一:同分情况,先到的排前面

这是面试最喜花挖的坑,Redis ZSet的默认规则是:分数不同看分数,分数相同看Member的字典序

  • 用户A(ID:100)得了100分
  • 用户B(ID:200)得了100分
  • Redis会默认把A排在B前面,因为100<200,但如果是uuid的话,排序就乱了
  • 因此在业务中通常要求先到达的同分分数排前面

解决方案:带时间戳的浮点数

我们将Score设计为一个浮点数,整数部分为原本的分数,小数部分为时间比,公式为:

  • RealScore为实际分数
  • CurrentTimestamp为当前时间戳
  • FutureTimestamp为一个足够大的固定时间,用来把时间比例压缩到0-1之间

所以分数一样时,数据来得越晚,时间戳越大,而(1-时间比)越小,排名就越后。

进阶场景二:海量数据的大Key问题

如果有1000万个玩家,或者直播间有几千万观众,全部塞进一个ZSet里,会导致:

  • 内存爆炸:单个Key过大,迁移、持久化困难
  • 性能下降:虽然是,但海量数据也会变慢
  • 过于冗余:没人会关心一定排名(如9999名以后)的人是谁

解决方案:截断策略

我们只维护活跃榜与Top N榜

  1. 用户得分时:先用ZADD加入进ZSet
  2. 定期裁剪:
    1. 每次写入后,判断ZCARD(总数)是否超过10,000
    2. 如果超过,执行ZREMRANGEBYRANK leaderboard 0 -10001(移除10000名以后的人)
  3. 对于裁剪后的人的处理
    1. 直接返回未上版或排名10000+
    2. 去数据库查,因为低排名不需要实时性

进阶场景三:全服排名 vs 好友排名

在游戏中(比如王者荣耀)我们可以看到全服排名和好友排名,要如何处理?

全服排名:直接查leaderboard(选择前面的方案)

好友排名:

  • 不能为每个用户都建立一个ZSet,浪费内存
  • 做法:
    • 先去数据库拿到该用户的所有好友ID List
    • 使用Redis的 ZMSCORE leaderboard ID1 ID2 ID3 ...(批量获取分数)
    • 在内存中排序这些数据,返回给前端
    • 注意:Redis 6.2+才支持ZMSCORE,老版本可以用pipeline批量ZSCORE

进阶场景四:深分页问题

如果前端请求查看50000名到50010名,使用ZREVRANGE leaderboard 50000 50010的话,Redis虽然是跳表,但也是链表,OFFSET越大,扫描越慢

解决方案:

1、限制页数:产品上直接限制,只能看100页

2、缓存分片:如果非要看,可以将榜单按分数拆分,或者把计算好的每页结果缓存起来。

相关推荐
打码人的日常分享21 小时前
智能制造数字化工厂解决方案
数据库·安全·web安全·云计算·制造
没差c21 小时前
springboot集成flyway
java·spring boot·后端
三水不滴21 小时前
Redis 过期删除与内存淘汰机制
数据库·经验分享·redis·笔记·后端·缓存
笨蛋不要掉眼泪21 小时前
Spring Boot集成LangChain4j:与大模型对话的极速入门
java·人工智能·后端·spring·langchain
-孤存-1 天前
MyBatis数据库配置与SQL操作全解析
数据库·mybatis
2301_822366351 天前
使用Scikit-learn构建你的第一个机器学习模型
jvm·数据库·python
万邦科技Lafite1 天前
一键获取京东商品评论信息,item_reviewAPI接口指南
java·服务器·数据库·开放api·淘宝开放平台·京东开放平台
自可乐1 天前
Milvus向量数据库/RAG基础设施学习教程
数据库·人工智能·python·milvus
indexsunny1 天前
互联网大厂Java面试实战:从Spring Boot到微服务架构的技术问答解析
java·spring boot·redis·微服务·kafka·jwt·flyway
sheji34161 天前
【开题答辩全过程】以 基于SpringBoot的疗养院管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端