如何答好面試中的系統設計題?
很多考察內容
比如面向對象,介面設計,設計模式,資料庫表,分散式。
首先在性能耗在什麼地方之前不要優化。所謂杞人憂天,你不是百度或者facebook的流量,根本考慮不到很多細節,大多數直接用雲計算平台,直接幫你做了。但面試中還是會考察
這裡就針對Scalability,有一些常見的優化技術,我就把他們列出 7脈神劍。- Cache:緩存,萬金油,哪裡不行優先考慮
- Queue:消息隊列,常見使用Linkedin的kafka
- Asynchronized:批處理+非同步,減少系統IO瓶頸
- Load Balance: 負載均衡,可以使用一致性hash技術做到盡量少的數據遷移
- Parallelization:並行計算,比如MapReduce
- Replication:提高可靠性,如HDFS,基於位置感知的多塊拷貝
- Partition:資料庫sharding,通過hash取摸
作為一位面試過很多人的磚家,我有以下幾點要說:
首先你要知道面試官在系統設計面試中考察三方面的能力
我們面試時,我們希望看到面試者表現出基本的系統知識,同時了解一些設計的技巧。這與演算法面試和程序面試不同,我們在整個過程中,其實主要看中的是你思考論述的過程,而不是你最後提出的解決方案(當然如果你提出的解決方案實在太挫……)。
也就是說,系統設計面試最重要的一點是「溝通」(communication)。
我們不會要求工程師一下子就開發出非常完美的功能。相反地,我們的工程師對於這些開放性問題有著充分的自主權。而且,我們的工作就是各自去為這些問題提出最佳的解決方案我們希望尋找的是那些我們可以完全信任的人。這樣,他們自己就可以做出非常棒的方案,而不需要我們的監管。也就是說,我們需要的工程師,是那些可以管理一個很大項目,同時保持項目持續朝正確方向發展的人。這意味著,你必須可以高效地與身邊的同時進行溝通。因為「閉門造車」在我們的大規模項目中是不可能的。
下面我要介紹一下開放式面試
通常,我們會先讓你按給定的題目設計一個系統。面試官給你的提示往往很簡單 ——但你千萬不要太天真,這些題目往往都是「深不可測」的,面試官們想要看的是在45分鐘內,你可以解決掉多少問題。
大多數時候,我們會把握談話的方向。不過你可以按照自己的理解去解答面試題。
也就是說,你可以提問、在白板上畫示意圖,甚至可以激發出面官的想法。這道問題的限制條件是什麼?系統設計時需要什麼輸入?這些都是你在展開思考時所需要先向面試官澄清的。一定要記住,現實生活中的問題,都不是只有一個答案的哦。任何事情都是一個博弈。
接下來我要談談考察內容
系統是非常複雜的。當你在設計一個系統時,你必須直面所有的複雜性。基於這一點,你必須熟知以下內容:
1 並發性(concurrency)。你知道線程(threads)、死鎖(deadlock)和starvation嗎?你知道如何並行化演算法嗎?你了解一致性(consistency)和連貫性(coherence)嗎?你大概了解IPC和TCP/IP嗎?你知道吞吐量(throughput) 和延遲(latency)的區別嗎?
2 現實表現(real-word performance)。你應當熟悉你電腦的速度和性能,包括RAM、硬碟、SSD以及你的網路狀況。
3 估計(estimation)。估計在幫助你縮小可能性解決方案的範圍時起到了重要的作用。這樣,你就只需寫少數幾個原型或微基準。
4 可用性和可靠性(availability and reliability)。你是否考慮過系統什麼時候會出現bug無法運行嗎(特別是在分散式的環境中)?你知道如何設計一個系統以應當網路故障嗎?你了解持久性嗎?切記,我們並不是要尋找一個熟悉以上所有的問題的「全才」。我們想衡量的是你的熟練程度。我們只需要你對系統設計方面有一定的基礎,並且知道什麼時候應該尋求專家的幫助。
- 那麼要如何準備系統設計面試呢?
就像你在準備演算法面試和程序面試時一樣,你必須刷無數的題,系統設計同樣需要練習。以下提供一些可以幫助你提高的建議:
? 模擬系統設計面試。邀請一個工程師幫你模擬面試。讓他提出一個系統設計問題,如果正好是他正在做的項目那就再好不過了。不要把它當成是一個面試,而是放輕鬆地去思考問題,並提出你能想到的最佳解決方案。
? 在實際的系統中去實踐。你可以在既有的OSS中去練習,也可以與朋友合作搭建一個系統。對於課堂中的系統設計作業,不再把它僅僅當成一個學術訓練,而是把它當成實際問題,思考系統設計過程中的架構和博弈。正如我們生活中遇到的大多事情一樣,只有做了才知道其中會遇到什麼問題,從而真正學到東西。
? 深挖開源系統的運行特點。例如,你可以看看levelDB。這是一個乾淨、小、且編寫良好的系統。你可以讀讀執行命令,了解它是如何在硬碟中存儲數據的,如何將數據壓縮成不同的層?你也可以多多反思一下的博弈問題:哪種數據和大小是最優的?什麼情況下會降低讀寫速度?(提示:比較一下隨機寫和順序寫)
? 多了解一下系統中資料庫和操作系統是如何運行的。這些技術並不只是你口袋中的工具,它們往往會在你設計系統的時候給你帶來啟發。如果你經常像DB或OS一樣思考它們如何處理各自的問題,你也會把這些思考方式應用到其它的系統設計中去。
最後,放輕鬆,表現出你的創造力
系統設計或許比較難,但它也是可以讓你表現自己創造力的地方。在面試時,注意聆聽問題,確保你了解該問題,並且直接、清晰地向面試官表達你的想法,你的表現肯定會得到面試官的認可。
附:系統設計評分標準
以下是個人觀點,以後對其他人有所幫助;
1.首先必須詳細地描述清楚你所做的系統,從系統需求分析、領域模型等描述,讓別人知道你這個系統是做什麼的;
2.面試官會根據你的項目描述從中問一些系統設計、關鍵點、如何優化等問題,這些問題如果是大牛面試官會詳細地去問你的,水的面試官會問你在項目中遇到什麼難點,這種問題太寬,其實沒啥意思;3.作為一個開發者應該對系統非功能性需求這塊平時要關注,即使你的系統沒有什麼流量,但是在設計上也應該去考慮,比如怎麼提高查詢速度、資料庫表設計優化、系統QPS、監控統計、容災,這些本來都是屬於軟體工程里系統的非功能需求分析,只是平實因為系統太小太簡單都被忽略了而已;4.多去學習下其他系統的設計經驗、這些資料從博客、infQ、公眾號等都可以學習到,保持持續學習吧,積累多了,你對這種問題自然好應付;這裡是個人觀點:
1. 熟悉常見的 Web 應用架構模式。比如你經常刷知乎的話,知道知乎的時間線怎麼設計嘛?可以到題庫裡面搜。
2. 如果你拿到了比較熟悉的題目,把它當成一次展示。因為系統設計面試很需要項目經驗,很多公司在系統設計面試的同時會考查你項目經驗。什麼叫展示,去看看 QCon,PyCon 的視頻。
3. 如果你拿到了你不熟悉的題目,但你還記得一些東西,把面試官當成你的同事,把面試當成共同解決這個問題。許多公司會在這裡考查溝通能力,而且這樣也會得到面試官的引導,讓面試更愉悅一點。
4. 這個前面也有人提到了。先考慮單機情況,然後擴展。這樣有個好處就是,一般來說系統設計問題的單機版本就是面向對象設計問題。你起碼可以告訴面試官,你單機上是完全沒問題的。
先考慮大方向(BigPic)然後劃分角色(資料庫、緩存、消息匯流排等等)。最後再談具體的技術(比如 Redis),許多人一談到具體的技術,就說可以用它解決,但不談技術的原理,這個非常麻煩。
我不知道我的答案算不算廣告,但是我自己不是科班出身,幾年的野路子下來雖然自己覺得不錯可還是沒底。
直到上了個號稱北美最好的系統設計班和演算法班之後不說學到多少,就是覺得骨架出來了。
然後我就後悔當年信了很多傻逼老師的話,或者沒有指導或者瞎指導,現在看他們自己代碼寫不好也不會設計。
後面這段跳tone了,但是這段憤青話才是我回答的初衷,這樣我這條就不會被當做軟文了吧。
總之,我是覺得,就是自己先練演算法,這個時候是函數級別的但是沒關係,多敲。然後看點好的系統設計總結,再去分析一些現有的好設計,然後再總結。推薦閱讀: