為什麼系統設計面試具有挑戰性#

許多人在系統設計面試(System Design Interviews, SDIs)中表現不佳,主要原因有三:

  1. SDI 的開放本質:題目沒有標準答案,需要處理開放式設計問題
  2. 缺乏大規模系統開發經驗:難以從實務角度思考設計取捨
  3. 準備不足:未花足夠時間針對 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),即使丟失幾台伺服器仍能正常服務使用者?
  • 服務冗餘:是否有足夠的服務副本在運行,使得少數故障不會導致整個系統停擺?
  • 效能監控:如何監控服務效能?當關鍵元件故障或效能下降時,是否能收到告警?

總結來說,充分準備面試中保持條理是系統設計面試成功的關鍵。