凉了呀,面试官叫我设计一个排行榜。 (上)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Tair(兼容Redis),内存型 2GB
简介: 凉了呀,面试官叫我设计一个排行榜。 (上)

这是why哥的第89篇原创文章

前两天,有一个读者给我发了一张图片。

我问:发什么肾么事了?

于是有了这样的对话:


微信图片_20220427220623.png


他发的图,就是微信运动步数排行榜的截图:


image.png


其实扯了这么多,这就是个常见的面试场景题:如何设计一个排行榜?

这个题吧,其实就是考你面试准备范围的广度,见过就会答,没见过...就难说了。

当然,如果你在实际业务中做过排行榜,那么这题正中下怀,你也不要笑出声来,场景题面试官是会给你思考时间的。


image.png


所以你不要张口就来,你只需要眉头稍稍一皱,给面试官说:这题我想想啊。

然后稍微组织一下语言,说出来就行。

这次的文章,就带着大家分析一下“排行榜”这个场景题,到底应该怎么做。


基于数据库


这个题,如果是真的之前没有遇见过,可能最容易进入大家视野的就是平时接触的最多的数据库了。

因为一想到“排行榜”,就想到了 order by。

一想了 order by,就想到了数据库。

一想到了数据库...

兄弟,你路就走窄了。

虽然我曾经就基于 MySQL 做过排行榜,因为当时是为了一个比赛临时搭建的服务,根本就没有引入 Redis。我评估了一下搭建 Redis 的时间和用 MySQL 直接开发的时间。

于是选择了 MySQL。

而让我选择 MySQL 的根本原因还是我已经知道进入决赛的队伍只有 10 支,也就是说我的排行榜表里面从始至终也只有 10 条数据。

选手提交代码之后,系统实时算分,然后更新排行榜表。

然后接口返回给前端页面下面这些数据,而下面这些数据都在一个表里面:

  • 队伍按照历史最高分数排名
  • 队伍名称
  • 历史最高分数
  • 最近一次提交得分
  • 最近一次提交时间

前端每隔一分钟调用我的接口,相同分数,名次相同,所以我在接口里面用一条比较复杂的 sql 去查询数据库,上面的这些字段就都有了。

你看,排行榜确实是可以用 MySQL 来做的。

不一定非得上 Redis,记住一句话:脱离业务场景的方案设计,都是耍流氓。


image.png


但是这玩意和“万物皆对象”一样,别对着面试官说,这一定不是面试官想要听到的答案。

或者说,这只是想要听到的一部分回答。

这个回答能用的原因是我给了一个具体的场景,用户量非常的小,怎么玩都可以。

甚至我们不借助 MySQL 的排序,把数据查出来,在内存里面排序都可以。

但是如果,这是一个游戏排行榜,随着游戏玩家的增加,达到千万用户级别的话,这个方案肯定是不行了。

当然,也许你会给我扯什么查询慢就加索引,数据量大就分库分表的方案。

怎么说呢,上面这句话是没有错的。

但是一旦数据量大起来了,这个方案其实就不是一个特别好的方案。

这问题,得从根上治理。


基于 Redis


这个场景其实就是在考察你对于 Redis 的 sorted set 数据结构的掌握。

sorted set,见名知意,就是有序集合的意思。


image.png

前面的 sport:ranking:20210227 是 Redis 中的 key。

value 是一个集合,且可以看出这个集合是有序的。集合中的每一个 member 都有一个 score,然后按照这个 score 进行降序排序。

需要注意的是,图片中的 score/member 不是我随便写的,官网上就是这样定义的:

https://redis.io/commands/zadd#sorted-sets-101

在 Redis 中它大概是长这样的:


image.png


而且官网上说的是: score / member pairs。

所以我画图的时候,score 在前,member 在后。这可不是随便画的,虽然谁前谁后好像也不影响什么玩意。

另一个需要注意的点是,虽然我的示意图中没有体现出来,但是在有序集合中,元素即 member 是不可以重复的,但是 score 是可以重复的。

这个很好理解,就比如 20210227 这一天的微信步数,我可以走 6666 步,你也可以走 6666 步,这个是不冲突:


image.png


但是,问题就随之而来了:当 member 的 score 一样的时候,member 是怎么排序的呢?

看一下来自官网的答案:

image.png


当多个元素具有相同的分数时,它们按照 lexicographically 进行排序。

哎呀,lexicographically 这个单词不认识。

不慌,你知道的 why哥还兼职教英文:


image.png


当分数一样的时候,按照字典序排序,所以上面的示意图 jay 在 why 之前。

接下来,看一下有序集合的操作函数,一共有 32 个:


微信图片_20220427220912.png


我这里就不一个个的做 API 教学了,官网上已经写的很清楚了,如果对于不熟悉的命令,可以去官网上查看,都是有示例代码的。

https://redis.io/commands/zadd#sorted-sets-101

比如这个 ZADD 方法:


image.png


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
SQL 消息中间件 搜索推荐
面试让人画正十七边形?面试官你长点心好不好?
面试让人画正十七边形?面试官你长点心好不好?
|
算法 搜索推荐 程序员
一文学会算法复杂度分析,面试再也不用愁了。
一文学会算法复杂度分析,面试再也不用愁了。
|
消息中间件 存储 算法
字节跳动这份面试题,你能打几分
字节跳动这份面试题,你能打几分
543 0
字节跳动这份面试题,你能打几分
|
域名解析 缓存 前端开发
2018春招前端面试: 闯关记(精排精校) | 掘金技术征文
年末研发组解散失业, 选择回去学车了,也顺利拿到了驾照,最近回归大深圳,开始踏上漫漫的找工作之路。
266 0
|
XML JSON 网络协议
上月成功拿到字节跳动offer,全靠我啃烂了这份最新面试题
前言 不论是校招还是社招都避免不了各种面试、笔试,如何去准备这些东西就显得格外重要。不论是笔试还是面试都是有章可循的,我这个“有章可循”说的意思只是说应对技术面试是可以提前准备,所谓不打无准备的仗就是这个道理,以下为大家,描述了从面试准备到最后的拿到offer提供了非常详细的目录,建议可以从头看是看几遍,如果基础不错的话也可以挑自己需要的章节查看。
上月成功拿到字节跳动offer,全靠我啃烂了这份最新面试题
|
存储 NoSQL 数据可视化
凉了呀,面试官叫我设计一个排行榜。 (中)
凉了呀,面试官叫我设计一个排行榜。 (中)
488 0
凉了呀,面试官叫我设计一个排行榜。 (中)
|
NoSQL 算法 数据挖掘
凉了呀,面试官叫我设计一个排行榜。 (下)
凉了呀,面试官叫我设计一个排行榜。 (下)
374 0
凉了呀,面试官叫我设计一个排行榜。 (下)
再学一道算法题:奥运排行榜
再学一道算法题:奥运排行榜
职场风云系列:那些有名的职场问题分析思路,一次讲给你听
无论是即将迈入社会接受社会毒打的大学生,还是已经在职场多年的职场老司机,实际都需要了解一些职场常用的做事套路以及问题分析的方法论。只有这样在遇到一些实际问题的时候,我们才能根据已有的做事套路以及法法论来进行应对,不至于让自己陷入手忙脚乱的困境之中。
职场风云系列:那些有名的职场问题分析思路,一次讲给你听