首页 理论教育 程序员面试笔试:系统设计问题回答技巧

程序员面试笔试:系统设计问题回答技巧

时间:2023-11-23 理论教育 版权反馈
【摘要】:在面试时,求职者偶尔也会遇到一些系统设计问题,而这些题目往往只是测试求职者的知识面,或者测试求职者对系统架构知识的了解,一般不会涉及具体的编码工作。在正式介绍基础知识之前,首先罗列几个常见的与系统设计相关的面试笔试题。4)设计一个系统,要求写速度尽可能快,并说明设计原理。但其扩展性和容错性差、维护成本高,尤其是数据量和用户量暴增之后,系统不能通过简单地增加机器解决该问题。

程序员面试笔试:系统设计问题回答技巧

在面试时,求职者偶尔也会遇到一些系统设计问题,而这些题目往往只是测试求职者的知识面,或者测试求职者对系统架构知识的了解,一般不会涉及具体的编码工作。虽然如此,对于此类问题,很多人还是感觉难以应对。

如何应对此类题目呢?在正式介绍基础知识之前,首先罗列几个常见的与系统设计相关的面试笔试题。

1)设计一个域名系统(Domain Name System,DNS)的Cache结构,要求能够满足每秒5000次以上的查询,满足IP数据的快速插入,查询的速度要快(题目还给出了一系列的数据,例如,站点数总共为5000万,IP地址有1000万,等等)。

2)有N台机器,M个文件,文件可以以任意方式存放到任意机器上,文件可任意分割成若干块。假设这N台机器的宕机率小于1/3,要求在宕机时可以从其他未宕机的机器中完整地导出这M个文件,求最好的存放与分割策略。

3)假设有30台服务器,每台服务器中都存有上百亿条数据(有可能重复),如何根据某关键字,从中找出重复出现次数最多的前100条数据?要求使用Hadoop来实现。

4)设计一个系统,要求写速度尽可能快,并说明设计原理。

5)设计一个高并发系统,说明架构和关键技术要点。

6)假设有一个25T的log(query->queryinfo),log的大小还在不段地增长,设计一个方案,给出一个query能快速返回queryinfo。

以上所有问题中,凡是不涉及高并发的,基本可以采用Google的三个技术解决,即GFS、MapReduce和Bigtable,这三个技术被称为“Google的三驾马车”,Google只公开了论文而未公开源代码,开源界对此非常感兴趣,于是仿效这三篇论文实现了一系列软件,如Hadoop、HBase、HDFS、Cassandra等。

在Google这些技术还未出现之前,企业界在设计大规模分布式系统时,采用的架构往往是Database+Sharding+Cache,现在很多公司仍采用这种架构。在这种架构中,仍有很多问题值得去探讨。如采用什么数据库,是SQL界的MySQL还是NoSQL界的Redis/TFS,两者有何优劣?采用什么方式进行数据分片(Sharding)?是水平分片,还是垂直分片?据网上资料显示,weibo.com和taobao图片存储中曾采用的架构是Redis/MySQL/TFS+Sharding+Cache。该架构解释如下:前端Cache是为了提高响应速度;后端数据库则用于数据永久存储,防止数据丢失;而Sharding是为了在多台机器间分摊负载。最前端由大块的Cache组成,要保证至少99%(该数据在weibo.com架构中的占比是编者推测的,而在taobao图片存储模块是真实的)的访问数据落在Cache中,这样可以保证用户访问速度,减少后端数据库的压力。此外,为了保证前端Cache中的数据与后端数据库中的数据一致,需要有一个中间件异步更新(这是因为同步代价太高。请思考,异步有缺点,如何弥补?)数据。另外,为了分摊负载压力和海量数据,会将用户的微博信息经过分片(即Sharding)后存放到不同的结点上。

这种架构的优点非常明显——简单,在数据量和用户量较小时完全可以胜任。但其扩展性和容错性差、维护成本高,尤其是数据量和用户量暴增之后,系统不能通过简单地增加机器解决该问题。

于是,新的架构便出现了,即前面讲到的“Google的三驾马车。

1)GFS是一个可扩展的分布式文件系统,用于大型的、分布式的、对大量数据进行访问的应用。它运行于廉价的普通硬件上,提供容错功能。现在开源界有Hadoop分布式文件系统(Hadoop Distributed File System,HDFS),该文件系统虽然弥补了数据库+Sharding的很多缺点,但自身仍存在一些问题,例如,由于采用master/slave架构,因而存在单点故障问题;元数据信息全部存放在master端的内存中,因而不适合存储小文件,或者说如果存储的大量小文件,那么存储的总数据量不会太大。(www.xing528.com)

2)MapReduce是针对分布式并行计算的一套编程模型。其最大的优点是编程接口简单、自动备份(数据默认情况下会自动备三份)、自动容错和隐藏跨机器间的通信。在Hadoop中,MapReduce作为分布计算框架,而HDFS作为底层的分布式存储系统,但MapReduce不是与HDFS耦合在一起的,用户完全可以使用自己的分布式文件系统替换HDFS。当前MapReduce有很多开源实现,如Java实现Hadoop MapReduce、C++实现Sector/sphere等,甚至有些数据库厂商将MapReduce集成到数据库中。

3)BigTable俗称“大表”,用来存储结构化数据。编者个人认为,BigTable在开源界最火爆,其开源实现最多,包括HBase、Cassandra、levelDB等,使用也非常广泛。

除了Google的这“三驾马车”以外,还有其他一些技术可供学习与使用。

1)Dynamo亚马逊的key-value模式的存储平台,可用性和扩展性都很好,采用分布式散列表(Distributed Hash Table,DHT)对数据分片,解决单点故障问题。在Cassandra中,也借鉴了该技术,在BT和电驴中,也采用了类似算法

2)虚拟结点技术该技术常用于分布式数据分片中。具体应用场景是:有一大堆数据(maybe TB级或者PB级),需按照某个字段(key)分片存储到几十(或者更多)台机器上,同时想尽量负载均衡且容易扩展。传统的做法是“Hash(key)mod N”,这种方法最大的缺点是不容易扩展,即增加或者减少机器均会导致数据全部重新分布,代价太大。这时便可以使用上面提到的DHT(现在已经被很多大型系统采用)。还有一种是对“Hash(key)mod N”的改进:假设要将数据分布到20台机器上,传统做法是“Hash(key)mod 20”,而改进后,N的取值要远大于20,如20000000,然后额外采用一张表记录每个结点存储的key的模值,例如,

这样当添加一个新的结点时,只需将每个结点上的部分数据移动给新结点,同时修改一下这个表即可。

3)Thrift:它是一个跨语言远程过程调用协议(Remote Procedure Call Protocol,RPC)框架。RPC的使用方式与调用一个普通函数一样,但执行体发生在远程机器上。跨语言是指不同语言之间进行通信,例如C/S架构中,Server端采用C++编写,Client端采用PHP编写,若要让两者之间通信,则thrift是一种很好的方式。

对于这一节开始提出的几道笔试题,都可以通过上面介绍的知识点来加简答,例如:

1)关于高并发系统设计,主要有以下几个关键技术点:缓存索引、数据分片、锁粒度尽可能小。

2)问题2涉及现在通用的分布式文件系统的副本存放策略。一般是将大文件切分成小的块(如64MB)后,以块为单位存放三份到不同的结点上,这三份数据的位置需根据网络拓扑结构配置。一般而言,如果不考虑跨数据中心,可以这样存放:两个副本存放在同一个机架的不同结点上,而另外一个副本存放在另一个机架上,这样从效率可靠性上都是最优的(Google公布的文档对此有专门的证明)。如果考虑跨数据中心,可将两份存在一个数据中心的不同机架上,另一份存到另一个数据中心。

3)问题4涉及BigTable的模型。主要思想是将随机写转化为顺序写,进而大大提高写速度。具体方法为:由于磁盘物理结构的独特设计,其并发的随机写(主要是因为磁盘寻道时间长)非常慢,考虑到这一点,在BigTable模型中,首先会将并发写的大批数据放到一个内存表(称为“memtable”)中,当该表大到一定程度后,会顺序写到一个磁盘表(称为“SSTable”)中,这种写是顺序写,效率极高。说到这里,可能有读者问,随机读可不可以这样优化?答案是:看情况而定。通常而言,如果读并发度不高,则不可以这么做,因为如果将多个读重新排列组合后再执行,则系统的响应时间太慢,用户可能无法接受,而如果读并发度极高,也许可以采用类似机制。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈