# [面試][系統設計]如何設計一個像 Facebook 的社交平台

- 作者：林鼎淵（Dean Lin）
- 網址：https://deanlin.net/blog/202110/fullstack-career-notes-day-22/
- 發布：2021-10-07
- 主題：職涯成長
- 系列：全端工程師生存筆記
- 標籤：iT 邦幫忙鐵人賽、面試、系統設計、System Design、mind-map
- 摘要：其實前面 10 幾篇文章的內容都是系統設計的一環，只是問題的方向是從你過往的履歷、技術或是面試公司的需求出發，透過詢問細節來評核你技術的硬實力。

> 擅長嘴砲溝通的人在這個環節有較多優勢。

其實前面 10 幾篇文章的內容都是系統設計的一環，只是問題的方向是從你過往的履歷、技術或是面試公司的需求出發，透過詢問細節來評核你技術的硬實力。

再確認求職者的硬實力過關後，有些面試官會給你一個情境來做系統設計；然後依據你在這道題目上的應對進退，決定要給你 Junior 還是 Senior 的職稱。

> 如果你面試的職缺是 Tech Lead，這題回答得不好有高機率直接出局。

## 大綱

1. **初探系統設計**

2. 1.1 Junior 跟 Senior 工程師的差異
3. 1.2 系統設計的題目來源
4. 1.3 面試官在找的是同事

5. **如何設計一個像 Facebook 的社交平台**

6. 2.1 縮小問題範圍，確認具體需求
7. 2.2 先提出一個簡單的解決方案
8. 2.3 提出減少耗能的解決方案
9. 2.4 從自己擅長的面向切入
10. 2.5 不要有預設立場
11. 2.6 主動提出不同設計的優缺點

12. **衍伸問題**

13. 3.1 你有使用過 Mind Map 跟 Sitemap 嗎？它們的使用時機是？

## 1. 初探系統設計

筆者在第一次遇到系統設計的問題時表現得很差，因為我把它當成一個技術性的問題，所以不停的在輸出自己的想法及觀點，面試完的當下還覺得自己表現的超棒，肯定會拿到 Offer。

果然在兩天後收到 Offer Get 的信件，但核薪結果沒有到達自己的期待；當時我並不了解自己在哪個環節犯了錯，於是向人資詢問主管對我的評價，我收到的評價是：「技術完全沒問題、經驗豐富、自我學習能力高；但在系統架構的設計上能力稍顯不足，主觀思維太多。」

在這之後我才知道面試有「系統設計」這個類型的題目，也明白當時的回答並不是面試官期待的答案。

### 1.1 Junior 跟 Senior 工程師的差異

Junior 工程師在看到問題後會想直接提出解決方案；而 Senior 工程師則會先釐清問題，從整體架構去思考。

會有這樣的差異是很正常的，因為 Junior 工程師在入職後，往往是接受任務分配的一方，所以他們已經習慣「收到問題 → 解決問題」的作業模式；很少人會去思考為什麼要這樣做、能不能這樣做，以至於可以完成交辦的任務，卻缺乏對整體架構的思維。

而 Senior 工程師除了要寫程式外，有時還要跟 PM 討論需求、規劃系統架構、分配工作給 Junior 工程師、幫 Junior 工程師 Debug；有些工程師討厭做這些事情，因為會耽誤到自己寫程式的時間，但正因為這些事情讓他有更完整的架構思維與溝通能力。

### 1.2 系統設計的題目來源

雖然系統設計的範圍很廣，但面試官愛考的就大概就是以下幾種：

- **經典面試題**
很多面試官都是去題庫裡面找題目，我這裡也是建議讀者先熟悉題庫；透過反覆練習題庫，除了掌握基本盤外；在面對沒有接觸過的系統也能做到基本的應對進退。
- **面試公司的系統**
有些知名企業喜歡向求職者詢問：「如果是你，會如何設計我們公司的系統？」
這個問題除了考系統設計外，其實也是想知道求職者對面試公司的系統了解有多深。
- **你履歷上的技能**
像是筆者在履歷上有網頁爬蟲的經歷，面試官就會以此詢問筆者：「如何設計一個網頁爬蟲的系統？」

> **備註：**
> 每個面試官在意的細節都不一樣；有些題目除了要系統設計外，他還要你提供不同方案的人力資源配置、功能時程預估、所需硬體資源…，要你設計一套可以讓組織運轉的流程。
> 如果沒有一定的實務基礎，面對這些延伸的問題基本沒有招架之力。

### 1.3 面試官在找的是同事

問題走向完全看面試官的喜好，因為沒有固定的解答，所以回答是否被接受也是看你跟面試官頻率是否契合。

今天面試官要找的是同事，在確認技術過關後；他想透過這個關卡更進一步了解求職者：

- 是否具備分析問題的能力。
- 會經過討論再做出設計，而不是一開始就有許多預設立場。
- 能夠清晰闡述自己的策略。
- 溝通時雙方在同一個頻率，不會出現雞同鴨講的狀況。
- 能評估自己提出方案的優缺點，並提出可行的優化方案。

與其說是考試，更像是同事間在討論一個議題；有時也會遇到你認為自己的方案沒問題，但面試官就是覺得不可行的狀況；此時你可以先了解面試官顧慮的點，可能真的有自己忽略的細節。

有時面試官的技術能力未必高於求職者，也許你提出的方案更好，但因為已經超過面試官知識範圍所以不被採納；此時並不建議堅持己見，你可以說：「也許有我忽略的細節，您的考慮應該是對的。」然後轉移到下一個話題。

如果你遇到一個自己完全不熟悉的領域，連回答的頭緒都沒有，請跟面試官討論你想解決的問題，並說明為什麼會卡住，千萬不要不懂裝懂瞎掰答案；多跟面試官互相分享彼此的想法，面試官自己也很清楚求職者是不可能在短時間內給出完美的答案，面對自己不熟悉的議題，就算有不會知識也是很正常的。

- 系統設計不只是單純的考試，而是評估你在工作上會如何討論問題。
- 雙方有來有往聊得越開心，就算你的回答有犯錯也容易被忽略。

會錄取的求職者未必技術能力最好，但絕對是在面試過程中溝通流暢的。

## 2. 如何設計一個像 Facebook 的社交平台

### 2.1 縮小問題範圍，確認具體需求

大部分主管在交代事情時，只會給一個方向，並不會把細節說清楚；所以面試官也是想透過這個問題來了解在未來交辦工作時，你會如何面對。

- **縮小問題範圍**
Facebook 是一個經歷十幾年改版、無數菁英灌注青春與熱血的系統，它所提供的服務實在是太多了，所以要先確認問題回答的方向，比如說：「Facebook 有提供蠻多種服務的，像是發文動態、Messager、廣告系統；我們要先從哪一塊來做討論？」

- **不要急著提出解決方案**
當年筆者沒搞清楚狀況，把它當成高流量架構設計的問題；直接丟出一堆像是 Load Balance、Repliaction、DB Sharding…的技術方案；我當時說的很開心，但回答的內容完全偏離了面試官想要了解的方向。

> 使用什麼技術可以等需求確定後再討論，如果一開始在分析問題時就走偏了，那後面再多的努力也沒有用。

### 2.2 先提出一個簡單的解決方案

假設面試官把問題縮小到打造一個 Messager 的系統，那核心功能就非常明確；此時你只要簡單敘述設計概念就好；不要急著說出使用 Node.js + Socket.io + MongoDB 這些工具來打造系統。

- **簡述基礎解決方案**
我們會需要一個聊天伺服器來處理訊息間的溝通，當用戶發送訊息時，訊息會先傳送到伺服器並儲存；如果接收方在線上就直接傳送訊息給他，如果不在線就透過推播通知。
在 UI 介面上，使用者發送訊息成功時會有時間戳記；當接收方點開訊息時也會有已讀的標記。

> 通常考題都會涵蓋「前端、後端、資料庫」的設計；這樣面試官才能依照自己在意的點深入詢問。

### 2.3 提出可以減少耗能的可行方案

資源永遠是有限的，更高的硬體規格代表更多的預算，此時就需要 `trade-off（權衡）`。

接著讓我們從資源消耗的角度來探討 Messager 這個系統中，好友上線顯示綠燈的功能要如何設計。

最簡單的做法是當用戶一上線，就向所有好友發送上線通知；但這個設計在系統成長到百萬用戶，且特定時段上線的活躍用戶數量高達 30 萬時，這種發送通知的方法對資源的消耗極大。

- **有什麼方式可以減輕資源消耗？**
很多人打開 Messager 只是簡單回覆訊息就關掉，所以系統其實沒必要爲剛上線的用戶立刻發送通知；我會建議把發送上線通知的策略改為顯示活躍用戶，可能要在線 5 分鐘以上再發送通知；透過減少請求的次數來降低對系統資源的消耗。

### 2.4 從自己擅長的面向切入

在提出基礎的解決方案後，題目就會往細節發展，此時你可以主動向面試官確認一些系統需求，假設你擅長大流量高併發的議題，你就故意問面試官：「這個系統在設計上要考量到大流量以及高併發的問題嗎？」

主動引導面試官將話題轉向自己擅長的領域是很重要的；但如果面試官對這個議題沒有興趣，千萬不要自顧自的一直講。

> 如果你對某個領域不擅長就不要挖坑給自己跳，假如你主動提及資料庫相關問題，面試官可能就因為你履歷上有 MySQL 跟 PostgreSQL 的經驗，而詢問你兩者的優缺點及使用時機，如果你答不出來反而會被扣分。

### 2.5 不要有預設立場

Messager 系統除了傳送訊息這個基礎功能外，還有建立聊天群組、回覆特定訊息、移除訊息、對訊息傳送表情符號…等眾多功能。

如果你打算在這些功能上開闢戰場，請先詢問面試官是否需要這些功能；而不是沒有經過溝通，自己覺得理所當然就直接開始設計。

> **經驗分享**
> 在系統開發上，如果你要做的功能在需求規格以外，一定要先跟 PM 溝通；你認為必要的功能對客戶來說可能根本不需要，甚至系統有可能因為多出來的功能而產生無法預期的 Bug；千萬不要自作聰明。

### 2.6 主動提出不同設計的優缺點

如果面試官把話題帶到 `DB Sharding` 上面，比如：「隨著用戶成長，儲存用戶的 Table 資料量太大，效率越來越低，有什麼解決方案嗎？」

**筆者會用下面的角度來回答：**

考慮到用戶數量會持續成長，為了減輕資料庫的負擔，我會將這個 Table 切分到多個資料庫來分散壓力，這邊提供兩種切分策略：

- **Range-based partitioning**
第一種是挑選一個合適的欄位作為切分條件，像是以用戶的「年齡」做為切分條件；不過使用這種方式可能會造成不均勻的 Server load，因為每個年齡段的用戶數量不同。

- **Hash partitioning**
為了解決 Server load 不均勻的問題，第二種方案則是挑選一個欄位用 `Hash Function` 計算出一個值，用這個值來決定資料要放到哪個資料庫。

> 可以採用 `Consistent Hashing` 讓資料均勻分布在不同 DB；這個方案在 DB 數量有增減時，也能盡量避免原有的 Key 被重新分配。

系統設計沒有標準答案，如果你有能力提出多種解決方案，並能說出各自的利弊是非常加分的。

## 3. 衍伸問題

### 3.1 你有使用過 Mind Map 跟 Sitemap 嗎？它們的使用時機是？

考點：設計系統架構時的輔助工具

- **Mind-Map**
在專案做需求訪談時，我會先透過 Mind Map 來幫助發想與記錄想法，透過這張圖即使開會偏離重點也可以快速拉回；在會後我會透過它向同事說明需求的關聯性、以及一些功能的限制條件，讓他們快速理解這個專案的目標。
- **Sitemap**
在需求明確後，我會用 Sitemap 規劃系統架構，設計頁面之間的關聯性與階層，完成流程上的模擬；並檢視規劃是否有下列問題：

- 如果需要 SEO 的頁面被埋得太深就要重新規劃，避免 Google 爬蟲不到。

- 檢查是否有規劃不良導致的孤兒網頁。

> **孤兒網頁**：系統沒有連結可以抵達的網頁。

### 筆者碎碎念

即使經驗豐富，面對一個從未思考過的問題，也很難提出合適的設計；這邊建議讀者可以透過以下方式，有意識地培養自己系統設計的能力：

- 上網找題庫，吸收他人在系統設計上的經驗。
- 找 Mentor 做模擬面試，熟悉答題方向。
- 在閒暇時思考知名的系統是如何設計出來的（ex：Youtube、Google、Twitter…）。

感謝大家的閱讀，如果喜歡我的文章可以`訂閱`接收通知；如果有幫助到你，按`Like`可以讓我更有寫文的動力，我們明天見～

### 參考資源

1. [系統設計面試 6 個技巧｜我面 Google 前的準備方法](https://www.youtube.com/watch?v=zomYKjlvJGU&ab_channel=HackBear%E6%B3%B0%E7%91%9E)
2. [軟體工程師系統設計面試準備指南](https://medium.com/jktech/acf6ab1f502f)
3. [系統設計面試（第一部分）](https://wizardforcel.gitbooks.io/gainlo-interview-guide/content/5.html)
4. [donnemartin/system-design-primer](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md)
5. [從 Sitemap 的應用，談 SEO 的學習](https://www.yesharris.com/sitemap-seo/)

> 在許多人的幫助下，本系列文章已成功出版，除了添加新的篇章，更完善了每個案例的應對進退；如果對現在的職涯感到迷茫，也許這本書能帶給你不一樣的觀點～
> **天瓏書局：** [https://www.tenlong.com.tw/products/9786263334571](https://www.tenlong.com.tw/products/9786263334571)

---

關於作者：林鼎淵（Dean Lin），台灣的生成式 AI 企業內訓講師、外商資安公司軟體專家，也是生成式 AI 創新學院發起人。出版 7 本書（包含全台第一本 ChatGPT 應用專書），兩度獲得 iThome 鐵人賽佳作，累積上百場授課與顧問經驗。（https://deanlin.net/about/）
引用時請附上原文網址：https://deanlin.net/blog/202110/fullstack-career-notes-day-22/
