系统设计题回答步骤
Step1 问清楚系统的功能性需求和非功能性需求
功能性需求:
- 用户是谁,会如何使用该系统
- 系统的作用是什么,有哪些功能,可以拆分成哪些服务?
- 系统的输入和输出是什么?
非功能性需求:
- QPS大概是多少?每秒处理多少请求?
- 会处理多少数据?
- 读写比率大概是多少?
Step2 系统进行抽象设计
通过所有组件来描绘一个高层级设计–系统设计架构图
比如说大概有哪几个部分
- 画出主要的组件和连接
- 证明想法
Step3 每一个核心的组件进行分析
具体如何实现,包括技术选型与算法逻辑,使用什么设计模式
Step4 需要优化的点
确认和存储瓶颈以及一些限制,举例来说就是一以下扩展性议题:
- 可扩展性
- 负载均衡:当前系统部署在一台机器上够吗?是否需要部署在多台机器上进行负载均衡?
- 水平扩展
- 缓存
- 数据库:数据库处理速度是否能够支撑业务需求?是否需要给指定字段加索引?是否需要读写分离?是否需要缓存?数据量大到是否需要分库分表
- 是否存在安全隐患
- 是否需要分布式文件系统?
- 高性能:是否需要读写分离、缓存、负载均衡、异步操作等
- 高可用:CAP理论,通过集群来提高系统整体稳定性,超时和重试机制、应对接口级故障:降级、熔断、限流、排队
- 服务稳定性:
- 高扩展性:如何进行系统拆分,数据存储与服务层面进行系统拆分
知识储备
性能相关的指标
- 响应时间:用户发出请求到用户收到系统处理结果所需要的时间。正常在200ms以内,如果响应时间变长,可以通过arthas工具进行分析哪一步出现了延迟
- 并发数:并发数可以理解为系统能够同时供多少人访问使用,也就是系统能够同时处理的请求数量。(QPS、TPS)
- 吞吐量:吞吐量指的是系统单位时间内系统处理的请求数量。QPS/TPS = 并发数/平均响应时间
常用组件的性能相关指标
- Nginx:一般情况下,系统的性能瓶颈不会是Nginx,单机可以达到30w+
- Redis:Redis官方性能测试,单机QPS可以达到8w+
- mysql:单机qps大概4000左右
- tomcat:单机大概2w左右
- kafka 单机能够满足每秒100K以上的数据传输请求,TB级别数据也能达到常数时间的访问程度。
- hbase单表的平均写入QPS大概在5000-7000左右,hbase是写性能好于读性能的,如果存在大量读的操作,也是需要使用缓存。
- 单机flink可以处理数据大概是35万/条,是storm的3-5倍
可扩展性提升
- 垂直扩展:更好的CPU\DISKS\RAM 限制:可能没有那么多的物理资源
- 负载均衡:通过load balancer将服务集群黑盒化
- 共享存储,比如用redis共享session
- 使用缓存,redis,sqlcache等
- 主从模式,主写从读
常见面试题
在facebook规模下,设计一下照片计数系统
题目理解:对每一个photo有一个counter计数器
- 使用denormalize方法,和photo,这样每次遇到一个photo时候,不用去数据库里面like。考察的就是数据库的存放方法,使用cache存储照片和数量的映射关系
- 也要保持一致性
实现前5分钟、1小时、24小时内分享最多的post请求
算法角度:实现LFU的数据结构
系统设计角度分析:
会有以下问题:
- 如果QPS比较高,比如1m。这个数据结构因为要加锁才能处理,所以会比较慢
- 分享数据本身是分布式的,而不是中心化的,也就是说,比如有1000台web服务器,那么这1000台web服务器的最先获得哪个帖子被分享的数据的,但是这些数据又都分布在这1000台web服务器中,如果用一个中心化的节点来做这个数据结构的服务,那么很显然这个中心节点会成为瓶颈
- 比如这个系统用在twitter这样的服务中,根据长尾理论,有80%或者更多的帖子连20%都拍不到,而通常来说,从产品的角度,我们可以只需要知道top20最多是top100的数据就可以了。
- 题目要求5分钟,1小时,24小时,存在较大优化空间
- 真是产品的实时性和准确性没有那么高,需要查询最近5分钟的topk,结果得出的事最近5分钟02的topk没有问题
- 查询topk的次数远低于count+1和count-1
优化策略:
- 分布式统计:distributed 每隔5-10秒向中心节点汇报数据
哪些帖子被分享了多少次这些数据,首先在web_server中进行一次缓存,也就是说如果web server的一个进程接收到一个分享请求之后,会把这个数据先汇报给web server熵跑着的agent进程,这个agent进行在机器刚启动的时候,就会一直运行着,他接受web server上跑着的若干个web进行发过来的count+1请求。这个agent整理好这些数据之后,每隔5-10秒汇报给中心节点。这样子通过5-10s数据延迟解决了中心节点访问频率过高的问题。这个设计思路在业界非常实用 - 分段统计:level
如果我们要去算最近5分钟的数据,我就按照1秒钟为一个bucket的单位,收集最近300个buckets里面的数据,如果是最近1小时数据,那么就按照1分钟为单位,收集最近60分钟数据。这样的好处是,比如统计最近1小时数据,可以随着时间推移,每次增加当前分钟的所有数据的统计,然后扔掉1小时里最早1分钟的所有数据,这样就不用真的+1/-1了,而是整体+X/-X。 - 数据抽样:
topk的post,一定被分享了很多次,所以可以进行抽样记录。 - 缓存cache,永远看cache中数据
面试中遇到的系统设计题
- 1G内存的机器,8g的文件,如何从总选出数量最多的100个
- 如何提高服务的稳定性
- 设计一个rpc服务时候需要考虑什么?