看完这篇《系统设计题目的回答要领》,下次换你拷打面试官
文章主体来自@程序员程序员。该同学目前已经入职美团银行卡支付业务。后续也会在牛客更新自己的工作经验和面经。感兴趣的同学可以关注一下他。
一句话铭记在心:
这种题一定要学会反问面试官,索取更多的信息。
系统设计题想要考察什么?
系统设计题不是让你设计一个完美的系统出来,面试官也不可能考虑的面面俱到,因此你不要有太大的心里压力。考察这种题,主要还是考察一下三方面:
- 沟通表达能力:面试官不可能一句话描述清楚这个系统,我们需要跟面试官交流去完善细节。比如他想让我们主要设计哪些功能、系统的流量是多少、系统的用户量大概是多少。在这个阶段就把面试官当场产品经理即可,正常的面试他不会嫌弃你问的多,理想的过程就是在他一点点提示中你把系统设计的比较完备。
在面试的时候,不要一个人闷着头想,最后吐出来一个自以为完美的架构。这种大多数在面试官看来就是憋了半天之后拉了一泡大的。
所以要一遍表达自己的思路,一遍不断的完善。要让面试官了解你的一整个思路历程,不要让面试官尴尬的等你。
- 知识广度和深度:因为设计的业务场景非常多,所以对知识广度有很大的要求,比如设计一个红包雨系统、直播系统、弹幕系统。如果你之前没有相关的技术积累的话很难无中生有相关的概念,因此这部分需要我们着重积累。无论是中间件的积累,还是技术架构的积累都是很有必要的。
在这里给大家推荐三个比较万金油的中间件:
1.京东HotKey:这个中间件的作用是检测Redis中的HotKey。当检测到Hotkey后,这中间件可以直接把对应kv推送到线上服务中。这样下次请求就不需要访问redis了,而是直接从自己的JVM中获取。
2.美团BCP:这是一个一致性校验工具。场景很常见,比如我们需要校验两个数据库的数据是否一致。例如我们可能会有一条数据链路是先同步MySQL,再写es。那如何确保这条数据一定存在于MySQL和es中呢?就要使用这种一致性校验工具了。
3.databus:数据库变更捕捉工具。他会伪装成为数据库的一个slave节点,以此来拉去主库的binlog日志。可以根据binlog日志来往下游数据库中同步数据。
- 技术和业务的取舍:我们不可能按照技术最优的路线去设计,这时候要求我们向业务进行一定的妥协,比如我们需要为了高并发舍弃数据强一致、为了性能舍弃安全性,你只需要在这部分表现出你的业务思考即可。
技术在大多数情况下是为了业务服务的。所以不存在最优的技术,只有和业务高度匹配的技术。我举一个例子:比如哔哩哔哩的漫展卖票
在这个业务下,票超售了能咋?那玩意又不是一个人一个座位那种。漫展场馆内多塞几个人无所谓。所以这个业务场景有必要使用分布式事务吗?
分布式事务会大幅度的拖垮线上服务的性能,在这个场景下都不如使用实时核对消费+最大努力通知+逆向数据补偿。
我们回答的方向是什么?
系统设计题一般是设计一个C端产品,因此最重要的有三点:
第一是要完成面试官要求的核心功能
第二是系统要保证高并发下的访问速度
第三是合理设置存储方案。
我们的设计就是往三高上靠即可:高性能、高可靠、高可用。
我总结的这套思考方式将回答总结成3+1。3代表按照接入层、逻辑层、存储层的顺序递进思考;1代表需要完成的核心业务功能。
我将通用的这部分划分为以下几个层级。
1.接入层:负责流量的分发,如果面试官提到了百万QPS,不用想,我们肯定要在这里跟他吹一下你所了解的负载均衡工具,比如nginx、lvs、f5等。这和海量数据题利用了相同的思路就是分治。
2.逻辑层:在这里我们要完成核心业务功能。需要考虑引入什么中间件、什么缓存架构等。这一部分负责处理拆分后的流量。常见的思路有MQ异步解耦、本地-Redis-数据库多级缓存、CDN加速等。
3.数据存储层:我们需要考虑百万级别QPS的存储问题,这里一定是分布式的数据库,可以考虑分库分表、对于对象存储可以考虑元信息和内容信息的分离、冷热数据分离、备份等。
4.核心业务功能:给出设计方案并进行设计方案的对比
比如设计红包雨这个功能核心功能就是红包拆分,我们通过积累知道有一些俩种方式。
优缺点分析:二倍均值法实现简单,空间复杂度低,但是用户间抢到的金额不会有太大差距,因此给用户的惊喜较少。线段分割法实现复杂,但是金额差距大,娱乐性更强。
举个例子:设计一个百万级TPS的红包系统
1.接入层(网络负载层):搭建多个数据中心,并通过负载均衡工具比如nginx、lvs、f5(处理量分别是万级、十万级、百万级)对流量进行分散,不同数据中心只承载一部分流量。如果需要用到redis(这种级别的服务几乎强依赖于redis),拆分后的流量按照单机redis能处理8wtps的能力组建redis集群。
2.逻辑层:将红包拆分,并使用redis的list进行保存(key为红包id,list是拆分的金额),抢红包就是使用lua脚本pop这个list,并将结果存到用户维度的队列(key为uid+红包id,红包金额)。定时任务定时拉取用户队列进行批量入库操作,并发送mq通知结果。
3.存储层:mysql集群按照uid维度进行分库,存储用户已经抢到的红包列表。近期数据存MySQL,历史数据迁移至HBase,结合时间分表(如按月分表)控制单表规模
4.核心业务功能:
比如设计红包雨这个功能核心功能就是红包拆分,我们通过积累知道有一些俩种方式。
- 二倍均值法:剩余红包金额为M,剩余人数为N,每次抢到的金额=随机区间(0,M/N*2)。可以通过证明每个人抢到的金额期望上是相等的。是公平的算法。
- 线段分割法:将红包金额看作有一定长度的线段,N个用户抢红包就是确定N-1个分割点,用户对应的区间长度就是抢到的金额。
优缺点分析:二倍均值法实现简单,空间复杂度低,但是用户间抢到的金额不会有太大差距,因此给用户的惊喜较少。线段分割法实现复杂,但是金额差距大,娱乐性更强。
知识储备
在系统设计中,核心功能这一点,一定需要你有相关领域的积累,就像我问你短链接怎么生成、红包拆分算法怎么设计、朋友圈feed流如何实现的话,你在没有思考过的情况下很难直接说出来,因此这也是我们主要需要积累的东西。推荐的学习方式就是了解各大互联网公司的核心业务,比如
美团、滴滴、饿了么:派单
抖音、B站、快手:视频推送、弹幕功能
小红书、大众点评:文章推送
京东、淘宝、拼多多:电商秒杀
微信、QQ:朋友圈、群聊、红包、消息推送
你会发现,业务场景基本被涵盖在内了。你对这些核心功能有一个大概的了解之后,剩下的部分基本就是通用啦!平时我们可以针对性的看一看相关文章。
因此平时多看看各大公司的微信公众号,多看看他们披露出来的企业级别的架构。我一般常看的公众号有:
哔哩哔哩:
得物:
京东技术:
最后:
本文章来自我的学习笔记《小牛八股》。目前正在完善中,估计今年八九月份会写完。提前放出来一些文章引引流。
关注我,带你了解更多代码之外的生存之道。欢迎订阅我的专栏(目前免费),后续也会持续更新。如果这篇文章帮到了你的话,就送我朵花花吧。
#牛客激励计划##Java##牛客创作赏金赛#我们的生活不止有代码