场景题:排行榜怎么设计?

刷到此贴的友友春招/暑期必上岸!!!

鼠鼠在秋招的过程中多次被问到场景题,中大厂的考察频率相当之高,一般会放在最后一个问题用来拖时间,也遇到过上来就问你怎么设计一个系统(面试官以此来决定后面对你的态度)。所以鼠鼠准备开这个场景题栏目,分享在秋招过程中遇到的场景题以及如何进行回答,感兴趣和感觉有帮助的友友点个关注和赞吧,你们的点赞和关注是鼠鼠持续更新下去的最大动力!!!

话不多说开启今天的主题,排行榜设计吧!!!

排行榜是很常见的一个功能,在社交软件、游戏等各种场景中都有应用,积分、点赞、礼物、战绩排名等各类排行榜功能,这些排行本质都是基于计数进行排序的。不同的场景会有细微的设计差异,这里只讲通用的排行榜系统该如何设计,遇到具体的场景再做细微的调整即可,就算在面试过程中只能答出本文所设计的通用排行榜,也足够了,毕竟对于应届生也只会考察到这个程度,面试是尽可能多的回答问题,很难追求所有问题都能回答出来……

大家可能看过一些八股文,会回答直接使用zset进行试试排行即可。

鼠鼠也曾在面试中这样回答过:将每个用户的得分作为zset中元素的score,将用户ID作为元素的value。使用zset提供的排序功能,可以按照分数从高到低排序。

当时面试官说如果分数相同,按照默认的排序规则会按照value值排序,他希望按照时间顺序排序,也就是分数相同的情况下先上榜的排在前面。

当时把鼠鼠给难住了,面完后才找到一个可行的方案:

为了实现分数相同按照时间顺序排序,可以将分数score设置为一个浮点数,其中整数部分为得分,小数部分为时间戳

即:score = 分数 + 1 - 时间戳/1e13

此时在分数相同的情况下,时间早的时间戳小,除以一个很大的数后得到的数字就小,被1减去以后得到的差就会大,也就实现了

分数相同的情况下先上榜的排在前面。

但面试官后面希望我聊一些系统设计的思路,当时鼠鼠完全没有系统设计的思路,不管后面复盘后也总结出了一套方法论,在这里分享给大家。

(1)明晰项目诉求:在这里就是设计出一个根据积分或点赞等数据进行排序。同时关注请求量,是否需要做高并发/高可用的扩展设计;此外对实时性是否也要要求,追求强一致性还是最终一致性

(2)确定业务逻辑:新用户上榜后排行榜要产生变化;用户积分发生变化后调整排名

(3)架构设计:存储(MySQL/Redis)+服务(是否需要拆分为多个服务)

大体上排行榜由两部分组成,排序结构和信息汇总结构。也就是我们在排行榜上看到的根据点赞数排出前一百,而信息汇总则是我们点击某一个用户头像可以看到其具体的用户信息。 系统设计初期,前端同步调用排行榜系统,对于并发量不大的情况,可以直接使用MySQL作为存储,直接操作数据库io即可,这里数据库的极限在5000/s。也可以先把全量数据从数据库里取出来后在内存中进行排序(前提是数据量不大的情况下)

但随着并发量和用户量上升,这种强依赖的同步调用会增加接口延迟。 这时可以增加中间层,也就是应对接口性能提不上去的三板斧之一(缓存,消息队列,分库分表)。如使用Rocket MQ或Kafka等消息队列(MQ)。流量大时可对排行榜系统起到削峰作用,还可批量插入数据库减少IO次数,提高插入效率。不过,使用MQ后要做好幂等处理(八股提问,MQ的消息幂等有哪些方式可以实现)。 当流量和并发量持续上升,数据库读写锁竞争加剧,可采用主从分离等方式均摊读压力,当然也可以直接考虑使用Redis作为排行榜。利用Redis的sortset类型排序(这里需要掌握zset,相关的八股文也要熟悉,可能会被问到),如排行评论数可使用ZINCRBY命令更新,查询用ZREVRANGE命令获取前N名排名和分数。 架构上可以由Redis作为消费者,它订阅MQ消息,消费时做幂等判断,用Lua脚本保证操作原子性。(这段话可以作为经典话术使用)

总结:

针对排行榜,简单的就直接可以使用Redis排序,但如果需要保证时间戳小的在前面就需要做一点小处理。

面对设计一个通用的排行榜系统,考察系统设计能力,这里就可以从我前面列举的方法论进行展开,多多关注我的文章,积累经验,相信友友们一定会越来越游刃有余。

PS:

其实在整个分析过程中大家可以发现,场景题其实就会把我们背的那些八股和技术运用起来,所以在学习场景题的时候就可以把八股文进行问题,有点像单词背不住就去读阅读文章,在读文章的时候记住八股文,在上面的分析过程中我也有几处进行了随机的八股提问。排行榜这个过程系统设计过程中有用到MQ,那友友们是不是可以顺带复习一下MQ的相关八股呢?

(1)如何保证MQ的消息幂等性?

(2)MQ的推模式和拉模式是什么?

(3)如何保证MQ消息不丢?

……

以上都是鼠鼠在面试中只要遇到Redis就一定会被问到的,不一定是全部问到,但至少都是三选一了…

好了如果大家有什么问题的话欢迎来评论区交流。包括但不限于文章创作改正意见,后续分享内容(面经,知识输出,经验分享等等),都看到这了,点个免费的关注和赞不过分吧

#场景题##八股文##面试##暑期实习##春招#
全部评论
时间戳处理很妙
5 回复 分享
发布于 03-27 20:46 湖北
1e13 这个是怎么确定的
1 回复 分享
发布于 03-31 13:13 江西
1 回复 分享
发布于 03-27 22:34 北京
m
点赞 回复 分享
发布于 04-30 12:54 四川
m
点赞 回复 分享
发布于 04-21 09:56 四川
催更催更催更
点赞 回复 分享
发布于 04-15 15:21 陕西
点赞 回复 分享
发布于 04-04 16:05 福建
优秀
点赞 回复 分享
发布于 04-03 13:02 广东
排行榜用 mq 没太看明白,可以解释一下吗
点赞 回复 分享
发布于 04-01 16:55 广东
点赞 回复 分享
发布于 04-01 16:17 上海
mark
点赞 回复 分享
发布于 04-01 06:19 上海
点赞 回复 分享
发布于 03-31 12:56 浙江
mark住Redis部分
点赞 回复 分享
发布于 03-31 09:18 湖北

相关推荐

09-16 19:41
门头沟学院 Java
依旧只写记得的部分一面:1.自我介绍+介绍个人博客2.看我个人博客,让我讲讲我写的博客的东西(有关线程池源码的,参考性并不是很大)2.5.在讲博客内容时穿插多线程八股3.看我多线程这块好像挺好的,手撕奖励一道多线程打印,一个打印A,一个打印B(还好上次回去恶补了一下)4.问实习相关,主要是自己做了啥事情,整个系统大概啥样,回答思路是首先大致介绍系统作用,然后聚焦个人做的模块,再补充上下游把全链路讲清楚大概这么多,一共45-50min,出来等了5min告知通过准备第二轮二面:1.看我项目用了限流的东西问了一下我对限流算法有无了解,回答了令牌桶和时间窗口2.初现端倪,开始问我TCP有无限流概念的体现(主播简历一点408计网没写),回答流量控制和拥塞控制3.接2,给了一个例子,比如通过TCP连接下载数据的时候的场景,让我画TCP数据传输速率时间图(v-t图)。直接给我干懵逼了,他说你们应该学过吧,我说我完全没听过,他说没事,你学过的知识里应该有体现(体现在哪),于是开始画图。这题我主要的考虑是作为发送方来发数据的速率,因为流量控制和拥塞控制实际上都是控制发送方的窗口大小,其中拥塞控制是发送方根据网络拥堵程度控制自己的窗口大小。所以主播在这里考虑拥塞避免的一些算法(慢开始、拥塞避免、快重传、快恢复),通过窗口变化来推算传输速率的变化。所以首先画了一个拥塞窗口随时间变化的图,然后根据这个图画出最终他要的v-t图。他当时没说对不对,下来之后我用claude给我模拟了一下,思路基本没啥问题,最后的v-t图实际上跟窗口变化是基本差不多的。4.继续问计网,让我讲讲TCP三次握手和四次挥手,主播已经不记得那些状态具体叫啥了,索性说那我继续画图吧,然后就直接开画,画的中间穿插一些细节问题,比如第二次挥手跟第三次挥手之间可能是谁给谁传数据(服务端给客户端传)之类的细节。5.画完开始问一些我觉得自己擅长的,我说线程池,然后开始吟唱一些普通线程池八股6.追问你看过一些Web容器的源码比如tomcat吗?回答没看过,说没事那你觉得像这种Web服务的容器用传统线程池合适吗?回答思路是不太合适,我是从用户响应这块考虑的,假设用传统线程池,那么请求只来了一部分,就到达核心线程数,只有等任务队列满之后才会继续创临时线程来处理,这样如果请求多一点的话,请求的平均响应时间可能就会慢,我的想法就是优先创建线程,实在没线程可创了再放进队列里可能会好一些。下来查发现tomcat也确实是这样设计。7.然后继续问我看过啥源码吗,我依然回答线程池。。。大哥看我这么喜欢线程池奖励了一道设计题,让我设计一个工业可用的线程池,我的大概思路就是1.线程池集中管理、2.线程池配置热更新(分成本地更新和远程更新,本地可以考虑WatchService,远程比如放配置中心Nacos这种,Nacos的SDK里有ConfigService可以注册监听器监听配置发布)、3.线程池监控、4.线程池告警8.然后说是给我一个拔高的问题,问我线程池中死锁如何产生的,这个一时没想出来,依然从死锁的四个必要条件开始推,1.互斥、2.请求保持、3.不可剥夺、4.循环等待,推断出应该是由于出现循环等待导致四个条件同时满足(死锁只有在四个条件同时成立时可能出现,注意是可能),但是推了一会依然没推出来,让下来再想想。9.剩下就问了一个Spring有哪些拓展点,BeanPostProcessor、InitializingBean、还有Aware系列比如AppilicationContextAware这种,当时只记得这三个了。大概就这些,貌似也30-40min左右,哥们看手机显示您今天的面试已结束,还以为凉透了,刚准备去抽奖然后hr喊我名字说我通过了,前脚刚迈出来后脚就过了属于是,有点懵逼,然后抽奖走人,抽了个水杯正好拿来泡茶。总结就是真的蛮看运气的,周末两天复习实际上他问我的东西一点没看,上周刚被拷打过JVM于是恶补了一下,结果两面都基本在问线程池和408,所以感觉还是平常心看待吧,面试官想问啥确实不是面试者能左右的。。。主播以面一次赚一次的态度来的,降低预期,反而没这么紧张了,反正还是那句话,找工作就是找屎,别让一坨屎影响生活吧,虽然该找还得找。。。而且线下面的好处就是流程快和好沟通,一言不合直接画图给面试官看感觉确实比线上用手比划爽多了。发出来让大火了解一下线下面大概是个啥强度,同时希望后续顺利一些吧。。
查看14道真题和解析
点赞 评论 收藏
分享
评论
78
320
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务