萬金油: 比喻什麼都能做,但什麼都不擅長
系統設計是面試當中的一個常考點,是面試官考察面試者知識廣度與深度最直接的方式。
許多開發者在系統設計面試中痛苦主要是因為下面三個原因
- 系統設計面試屬於開放性問題,沒有一個標準的答案
- 缺乏開發大規模系統的經驗
- 對系統設計問題沒有準備
就像程式碼面試一樣,那些沒有有意識地為系統設計面試做準備的求職者,大多表現不佳,尤其是在谷歌、Facebook、亞馬遜、微軟等頂級公司的面試中。在這些公司中,表現不佳的求職者得到錄用的機會非常有限。另一方面,良好的表現總是會帶來更好的待遇,因為這顯示了候選人處理複雜系統的能力。
第一步 需求分析
對我們要解決的問題確切範圍
並且提出問題
。設計類問題大多是開放式的,它們沒有一個正確的答案,這就是為什麼在面試中儘早澄清模稜兩可的問題變得至關重要。花足夠時間定義系統最終目標的候選人總是有更好的機會在面試中取得成功,此外,由於我們只有35-40分鐘的時間來設計一個大型系統,我們應該明確我們將重點關注系統的哪些部分。
讓我們用一個設計類似twitter的服務來擴充套件這一點。以下是一些設計Twitter時應該首先明確的問題。
- 使用者能夠釋出推文並關注其他人嗎?
- 我們應該設計建立和顯示使用者的時間軸嗎?
- 推文會包含照片和視訊嗎?
- 我們是隻關注後端還是也開發前端?
- 使用者能夠搜尋推文嗎?
- 我們需要展示熱門話題嗎?
- 我們需要設計新的(或重要的)推文推送通知嗎?
這些問題將會決定我們的系統最終設計會是什麼樣子。
第二步 系統介面定義
定義系統所需要的API,這不僅可以建立系統預期的確切規範,而且還可以確保我們沒有弄錯任何要求。 下面是我們類似Twitter服務的一些介面示例:
postTweet(user_id, tweet_data, tweet_location, user_location, timestamp, ...)
generateTimeline(user_id, current_time, user_location, ...)
markTweetFavorite(user_id, tweet_id, timestamp, ...)
第三步 規模估計
估計我們要設計的系統的規模,有助於我們以後關注擴充套件、分割槽、負載平衡和快取。
- 系統的預期規模(例如,新推文的數量,推文的瀏覽數量,每秒鐘時間軸的生成數量,等等)
- 我們需要多少儲存空間? 如果使用者可以在推特上上傳照片和視訊,我們會有不同預期的儲存空間。
- 我們期望的網路頻寬使用量是多少? 這對於決定我們將如何管理流量和平衡伺服器之間的負載至關重要。
第四步 定義資料模型
儘早定義資料模型將闡明資料如何在系統的不同元件之間流動。之後,它將指導資料分割槽和管理。候選人應該能夠識別系統的各種實體,它們將如何相互作用,以及資料管理的不同方面,如儲存、傳輸、加密等。這裡有一些我們的Twitter服務的實體定義。
User: UserID, Name, Email, DoB, CreationData, LastLogin, etc.
Tweet: TweetID, Content, TweetLocation, NumberOfLikes, TimeStamp, etc.
UserFollowo: UserdID1, UserID2
FavoriteTweets: UserID, TweetID, TimeStamp
我們應該使用哪個資料庫系統? 像Cassandra這樣的NoSQL是否最適合我們的需求,或者我們應該使用類似mysql的解決方案? 我們應該使用什麼樣的塊儲存來儲存照片和視訊?
第五步 高層次設計
用5-6個框圖表示我們系統的核心元件。我們應該確定從端到端解決實際問題所需的足夠多的元件。對於Twitter,在較高階別上,我們將需要多個應用程式伺服器來處理所有讀/寫請求,並在它們前面使用負載均衡器進行流量分配。 如果我們假設我們將有更多的讀取流量(與寫入相比),我們可以決定使用單獨的伺服器來處理這些場景。在後臺,我們需要一個高效的資料庫來儲存所有的tweet並支援大量的讀取。我們還需要一個分散式檔案儲存系統來儲存照片和視訊。
第六步 詳細設計
深入挖掘系統的兩三個元件,根據面試官的反饋來確定面試官更關心繫統中哪部分的實現,並且進行進一步的討論。我們應該能夠提出不同的方法,它們的優缺點,並解釋為什麼我們更喜歡一種方法而不是另一種方法。記住,沒有單一的答案,唯一重要的事情是考慮不同選項之間的權衡,同時牢記系統約束。
- 由於我們將儲存大量的資料,我們應該如何劃分資料以將其分佈到多個資料庫?我們是否應該嘗試將一個使用者的所有資料儲存在同一個資料庫中?它會引起什麼問題呢?
- 我們將如何處理推特或關注很多人的熱門使用者?
- 既然使用者的時間線將包含最新的(和相關的)tweets,我們是否應該嘗試以一種優化的方式儲存我們的資料,以掃描最新tweets?
- 我們應該在哪個層引入多少快取來加速呢?
- 哪些元件需要更好的負載平衡?
第七步 瓶頸問題
嘗試討論儘可能多的瓶頸和不同的方法來緩解它們。
- 我們的系統有單點故障嗎? 我們要做什麼來減輕它?
- 我們是否有足夠的資料副本,以便在失去一些伺服器時仍能為使用者提供服務。
- 類似地,我們是否有足夠多的不同服務的副本在執行,以便一些故障不會導致整個系統關閉。
- 我們如何監控服務的表現? 當關鍵元件出現故障或效能下降時,我們是否會收到警報。
總結
總之,面試過程中的有準備和有組織是系統設計面試成功的關鍵。上述步驟將指導您在設計系統時保持跟蹤並涵蓋系統設計的不同方面。