应届生在面试的时候,偶尔也会遇到一些系统设计题,而这些题目每每只是测试一下求职者的知识面,或者测试求职者对系统架构方面的了解,通常不会涉及到具体的编码工做。虽然如此,对于此类问题,不少人仍是感受难以应对,也不知道从何提及。前端
如何应对此类题目呢?在正式介绍基础知识以前,首先罗列几个常见的系统设计相关的面试笔试题,以下所示。node
(1)设计一个DNS的Cache结构,要求可以知足每秒5000次以上的查询,知足IP数据的快速插入,查询的速度要快(题目还给出了一系列的数据,好比:站点数总共为5000万,IP地址有1000万,等等)。面试
(2) 有N台机器,M个文件,文件能够以任意方式存放到任意机器上,文件可任意分割成若干块。假设这N台机器的宕机率小于1/3,想在宕机时能够从其余未宕机的机器中完整导出这M个文件,求最好的存放与分割策略。算法
(3) 假设有三十台服务器,每台服务器上面都存有上百亿条数据(有可能重复),如何找出这三十台机器中,根据某关键字,重复出现次数最多的前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,如今不少公司(好比taobao,weibo.com)仍采用这种架构。在这种架构中,仍有不少问题值得去探讨。如采用什么数据库,是SQL界的MySQL仍是NoSQL界的Redis/TFS,二者有何优劣?采用什么方式sharding(数据分片),是水平分片仍是垂直分片?据网上资料显示,weibo.com和taobao图片存储中曾采用的架构是Redis/MySQL/TFS+sharding+cache,该架构解释以下:前端cache是为了提升响应速度,后端数据库则用于数据永久存储,防止数据丢失,而sharding是为了在多台机器间分摊负载。最前端由大块大块的cache组成,要保证至少99%(该数据在weibo.com架构中的是本身猜的,而taobao图片存储模块是真实的)的访问数据落在cache中,这样能够保证用户访问速度,减小后端数据库的压力,此外,为了保证前端cache中数据与后端数据库中数据一致,须要有一个中间件异步更新(为啥异步?理由简单:同步代价过高。异步有缺定,如何弥补?)数据,这个有些人可能比较清楚,新浪有个开源软件叫memcachedb(整合了Berkeley DB和Memcached),正是完成此功能。另外,为了分摊负载压力和海量数据,会将用户微博信息通过片后存放到不一样节点上(称为“sharding”)。网络
这种架构优势很是明显:简单,在数据量和用户量较小的时候彻底能够胜任。但缺定迟早一天暴露出来,即:扩展性和容错性太差,维护成本很是高,尤为是数据量和用户量暴增以后,系统不能经过简单的增长机器解决该问题。
因而乎,新的架构便出现了。主要仍是Google的那一套东西,下面分别说一下:
GFS是一个可扩展的分布式文件系统,用于大型的、分布式的、对大量数据进行访问的应用。它运行于廉价的普通硬件上,提供容错功能。如今开源界有HDFS(Hadoop Distributed File System),该文件系统虽然弥补了数据库+sharding的不少缺点,但自身仍存在一些问题,好比:因为采用master/slave架构,于是存在单点故障问题;元数据信息所有存放在master端的内存中,于是不适合存储小文件,或者说若是存储的大量小文件,那么存储的总数据量不会太大。
MapReduce是针对分布式并行计算的一套编程模型。他最大的优势是:编程接口简单,自动备份(数据默认状况下会自动备三份),自动容错和隐藏跨机器间的通讯。在Hadoop中,MapReduce做为分布计算框架,而HDFS做为底层的分布式存储系统,但MapReduce不是与HDFS耦合在一块儿的,你彻底可使用本身的分布式文件系统替换掉HDFS。当前MapReduce有不少开源实现,如Java实现Hadoop MapReduce,C++实现Sector/sphere等,甚至有些数据库厂商将MapReduce集成到数据库中了。
BigTable俗称“大表”,是用来存储结构化数据的,我的以为,BigTable在开源界最火爆,其开源实现最多,包括:HBase,Cassandra,levelDB等,使用也很是普遍。
除了Google的这“三驾马车”之外,还有其余一些技术可供学习与使用:
Dynamo:亚马逊的key-value模式的存储平台,可用性和扩展性都很好,采用DHT(Distributed Hash Table)对数据分片,解决单点故障问题,在Cassandra中,也借鉴了该技术,在BT和电驴的中,也采用了相似算法。
虚拟节点技术:该技术经常使用于分布式数据分片中。具体应用场景是:有一大坨数据(maybeTB级或者PB级),咱们需按照某个字段(key)分片存储到几十(或者更多)台机器上,同时想尽可能负载均衡且容易扩展。传统的作法是:Hash(key) mod N,这种方法最大缺点是不容易扩展,即:增长或者减小机器均会致使数据所有重分布,代价忒大。因而乎,新技术诞生了,其中一种是上面提到的DHT,如今已经被不少大型系统采用,还有一种是对“Hash(key) mod N”的改进:假设咱们要将数据分不到20台机器上,传统作法是hash(key)mod 20,而改进后,N取值要远大于20,好比是20000000,而后咱们采用额外一张表记录每一个节点存储的key的模值,好比:
node1:0~1000000
node2:1000001~2000000
。。。。。。
这样,当添加一个新的节点时,只需将每一个节点上部分数据移动给新节点,同时修改一下这个表便可。
Thrift:Thrift是一个跨语言的RPC框架,分别解释一下“RPC”和“跨语言”,RPC是远程过程调用,其使用方式与调用一个普通函数同样,但执行体发生在远程机器上。跨语言是指不一样语言之间进行通讯,好比c/s架构中,server端采用C++编写,client端采用PHP编写,怎样让二者之间通讯,thrift是一种很好的方式。
文章最前面的几道题都可以映射到以上几个系统中的某个模块中,如:
(1)关于高并发系统设计。主要有如下几个关键技术点:缓存,索引,数据分片,锁粒度尽量小。
(2)问题2涉及到如今通用的分布式文件系统的副本存放策略。通常是将大文件切分红小的block(如64MB)后,以block为单位存放三份到不一样的节点上,这三份数据的位置需根据网络拓扑结构配置,通常而言,若是不考虑跨数据中心,能够这样存放:两个副本存放在同一个机架的不一样节点上,而另一个副本存放在另外一个机架上,这样从效率和可靠性上,都是最优的(这个Google公布的文档中有专门的证实,有兴趣的可参阅一下。)。若是考虑跨数据中心,可将两份存在一个数据中心的不一样机架上,另外一份放到另外一个数据中心。
(3)问题4涉及到BigTable的模型。主要思想是将随机写转化为顺序写,进而大大提升写速度。具体是:因为磁盘物理结构的独特设计,其并发的随机写(主要是由于磁盘寻道时间长)很是慢,考虑到这一点,在BigTable模型中,首先会将并发写的大批数据放到一个内存表(称为“memtable”)中,当该表大到必定程度后,会顺序写到一个磁盘表(称为“SSTable”)中,这种写是顺序写,效率极高。说到这,可能有读者问,随机读可不能够这样优化?答案是:看状况。一般而言,若是读并发度不高,则不能够这么作,由于若是将多个读从新排列组合后再执行,系统的响应时间太慢,用户可能接受不了,而若是读并发度极高,也许能够采用相似机制。