- 程序員面試筆試真題庫
- 猿媛之家編著
- 2704字
- 2019-08-02 16:54:05
面試筆試經驗技巧6 如何回答系統設計問題
在面試時,求職者偶爾也會遇到一些系統設計問題,而這些題目往往只是測試求職者的知識面,或者測試求職者對系統架構知識的了解,一般不會涉及具體的編碼工作。雖然如此,對于此類問題,很多人還是感覺難以應對。
如何應對此類題目呢?在正式介紹基礎知識之前,首先羅列幾個常見的與系統設計相關的面試筆試題。
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端的內存中,因而不適合存儲小文件,或者說如果存儲的大量小文件,那么存儲的總數據量不會太大。
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”)中,這種寫是順序寫,效率極高。說到這里,可能有讀者問,隨機讀可不可以這樣優化?答案是:看情況而定。通常而言,如果讀并發度不高,則不可以這么做,因為如果將多個讀重新排列組合后再執行,則系統的響應時間太慢,用戶可能無法接受,而如果讀并發度極高,也許可以采用類似機制。
- Reporting with Visual Studio and Crystal Reports
- 程序員面試白皮書
- AngularJS Testing Cookbook
- MySQL數據庫應用與管理 第2版
- Unity 2020 Mobile Game Development
- 三維圖形化C++趣味編程
- 數據結構(Java語言描述)
- Android NDK Beginner’s Guide
- 差分進化算法及其高維多目標優化應用
- Visual C++應用開發
- 從Java到Web程序設計教程
- Spring Boot+MVC實戰指南
- JavaScript+jQuery網頁特效設計任務驅動教程
- C++程序設計教程(第2版)
- 算法設計與分析:基于C++編程語言的描述