為什麼系統設計面試具有挑戰性#
許多人在系統設計面試(System Design Interviews, SDIs)中表現不佳,主要原因有三:
- SDI 的開放本質:題目沒有標準答案,需要處理開放式設計問題
- 缺乏大規模系統開發經驗:難以從實務角度思考設計取捨
- 準備不足:未花足夠時間針對 SDI 進行練習
在 Google、Facebook、Uber 等頂級公司,若候選人表現未達中上水準,獲得 offer 的機會非常有限。反之,優異的系統設計表現通常能帶來更好的職位與薪資,因為它反映了你處理複雜系統的能力。
本課程將透過 七個步驟 的方法,逐步解決多個系統設計問題。
Step 1:釐清需求(Requirements Clarifications)#
務必提問以確定問題的精確範圍。 設計題目大多是開放式的,沒有唯一正解,因此在面試初期釐清模糊之處至關重要。花足夠時間明確定義系統最終目標的候選人,成功機會總是更高。此外,由於面試時間僅有 35-40 分鐘,你需要釐清系統中要聚焦的部分。
以設計類 Twitter 服務為例,在進入下一步之前應回答以下問題:
- 使用者能否發推文並追蹤其他人?
- 是否需要設計建立和顯示使用者時間線(Timeline)?
- 推文是否包含圖片和影片?
- 只關注後端,還是前端也要設計?
- 使用者能否搜尋推文?
- 是否需要顯示熱門趨勢話題?
- 是否需要針對新的(或重要的)推文推送通知?
這些問題的答案將決定最終設計的走向。在面試中主動提問,展現你對需求分析的重視。
Step 2:定義系統介面(System Interface Definition)#
定義系統預期提供的 API。這不僅能建立系統的明確契約(contract),也能確保你沒有遺漏任何需求。
以類 Twitter 服務為例:
postTweet(user_id, tweet_data, tweet_location, user_location, timestamp, ...)
generateTimeline(user_id, current_time, user_location, ...)
markTweetFavorite(user_id, tweet_id, timestamp, ...)Step 3:粗略估算(Back-of-the-envelope Estimation)#
估算你將設計的系統規模是個好習慣,這有助於後續在 Scaling、Partitioning、Load Balancing、Caching 等方面做出決策。
以類 Twitter 服務為例,需要考量:
- 流量規模:每秒多少新推文?多少推文瀏覽?每秒多少時間線生成?
- 儲存需求:需要多少儲存空間?若推文可包含圖片和影片,數字會有所不同
- 網路頻寬:預期的頻寬使用量?這對流量管理和伺服器負載均衡至關重要
Step 4:定義資料模型(Defining Data Model)#
及早定義資料模型能釐清資料在系統各元件之間的流動方式,並為後續的資料分區與管理提供指引。候選人應能辨識系統中的各種實體(Entity)、它們之間的互動方式,以及儲存、傳輸、加密等資料管理面向。
以類 Twitter 服務為例:
- User:UserID, Name, Email, DoB, CreationDate, LastLogin 等
- Tweet:TweetID, Content, TweetLocation, NumberOfLikes, TimeStamp 等
- UserFollows:UserID1, UserID2
- FavoriteTweets:UserID, TweetID, TimeStamp
選擇資料庫系統也是這個階段的重點:NoSQL(如 Cassandra)是否更適合需求?還是應該使用 MySQL 之類的關聯式資料庫?圖片和影片應使用什麼樣的區塊儲存(Block Storage)?
Step 5:高層級設計(High-level Design)#
畫出包含 5-6 個方塊的架構圖,代表系統的核心元件。你需要辨識出足夠的元件,以端到端地解決實際問題。
以類 Twitter 服務為例:
- 需要多個 Application Server 處理所有讀寫請求
- 前端放置 Load Balancer 進行流量分配
- 若預期讀取流量遠大於寫入,可考慮分離讀寫伺服器
- 後端需要高效資料庫,儲存所有推文並支援大量讀取
- 需要分散式檔案儲存系統來存放圖片和影片
Step 6:詳細設計(Detailed Design)#
深入探討 2-3 個元件;面試官的回饋應引導你進一步解釋系統的哪些部分。你應能提供不同方案、各自的優缺點,以及你的選擇理由。
沒有唯一正確答案,重要的是在系統限制條件下,考量不同選項之間的取捨(Trade-offs)。
以類 Twitter 服務為例,需要思考的問題:
- 資料分區:如何分區以分散到多個資料庫?是否應將同一使用者的所有資料存在同一資料庫?這可能造成什麼問題?
- 熱門使用者處理:如何處理頻繁發推或追蹤大量人的使用者?
- 時間線最佳化:使用者時間線包含最新且相關的推文,是否應針對掃描最新推文最佳化資料儲存方式?
- 快取策略:在哪一層引入多少快取以加速系統?
- 負載均衡:哪些元件需要更好的負載均衡?
Step 7:識別並解決瓶頸(Identifying and Resolving Bottlenecks)#
盡可能多地討論瓶頸,以及對應的緩解方案。
- 單點故障(Single Point of Failure):系統中是否存在?如何緩解?
- 資料副本:是否有足夠的資料副本(Replica),即使丟失幾台伺服器仍能正常服務使用者?
- 服務冗餘:是否有足夠的服務副本在運行,使得少數故障不會導致整個系統停擺?
- 效能監控:如何監控服務效能?當關鍵元件故障或效能下降時,是否能收到告警?
總結來說,充分準備和面試中保持條理是系統設計面試成功的關鍵。