搞定面試中的系統設計題
上次跳槽的時候,我進行了專題訓練,因此總結了一些經驗,希望能夠給大家幫助。
一般來說,社招多少都會考察系統設計題,尤其是針對有了1年以上工作經驗的工程師,這更是面試流程中的家常菜, 除了面試之外,學會系統設計對我們的日常工作也是大有裨益的。
每當我說起“設計”,就會聯想到“戰略”這個詞語,戰略的意思就是,選擇一方面,而放棄另一方面。而軟體設計也是這樣, 我們在多個需求、現實資源中進行權衡,從而給出一套符合當前,以及短期未來中最優的方案。下面這張圖畫出了後端中常見的 一些結構,此外,還可以參考我的《Web開發簡介》
系統設計題想要考察什麼?
首先我們要搞清楚,面試官為什麼要問這一類題目。這一類題目的特點是題目非常開放,涉及到的知識點特別多,每一個地方都可以進行 深挖,而且,往往一個條件進行改變,相對較好的方案就會完全不同。通常來說,面試官使用系統設計題,主要就是考察:
- 思維是否開闊、靈活
- 知識廣度
- 知識深度
- 架構能力是否足夠,是否能設計出可擴充套件的系統
- 是否能熟練使用常見工具並且知曉特性,能夠因地制宜選擇合適的方案和工具
因此,此時我們已經知道面試官到底想要通過系統設計題考察我們什麼,我們也就知道在大的方面,該要怎麼應對面試:
- 加強知識深度:知識深度不僅僅在系統設計題中體現,包括此前的技術面試題都會考察
- 加強知識廣度:瞭解常見工具的特性和什麼場景適合,例如MySQL/PG、Redis。瞭解常見的業務場景特點,例如:論壇一般來說都是讀多寫少,而日誌服務則是寫多讀少。
- 瞭解常見的軟體架構模式,參考:https://jiajunhuang.com/articles/2018_09_16-common_software_archtecture_pattern.md.html
如何解決系統設計題
那麼,當我們拿到一個具體的系統設計題時,我們應該怎麼著手解決它呢?
注意陷阱:warning:
千萬不要張口就來。我們上面的分析已經表明,遇到問題,我們必須先明確問題,然後才能給出有效的解決方案,系統設計題也是如此。 而往往面試官會在這裡面挖坑,就是,給出一個條件相當模糊的系統設計題。例如:請設計一個短連結系統、請設計一個壓測工具。
如果我們張口就來,那麼就中了面試官的套路。在工作中也是如此,如果你碰到了一個產品經理,產品經理還沒有想清楚,就叫你寫程式碼, 那麼後面一定是反覆修改需求,作為工程師的你一定是痛不欲生。因此,我們需要做的第一步就是明確問題,不要張口就來 。
千萬不要自己一個人悶頭想,記得一邊想一邊把你的思路說出來由於別人是不知道你咋想什麼的,如果你一個人皺著眉頭思考,面試官 也很著急,他也不知道你是想不出還是怎麼的。所以,一邊把你的思路描述出來一邊想,這是最好的方式。
明確問題
拿到了問題之後,我們只有一個大概的方向,即我們要做一個什麼。但是並不清楚具體條件,而不同的的業務場景所需要的架構也是不一樣的。 例如,每天只有10000次訪問的短連結系統和每秒鐘有10000次訪問的短連結系統在技術要求上是不一樣的。
因此,第一個我們需要問面試官的問題:
- 這個系統一天的請求量是多少?面試官回答,一天2萬。
雖然現在我們有了更加明確的條件,但是還是不夠具體,我們需要進一步確定:
- 這個短連結系統的峰值是多少?面試官回答:峰值1萬/s。
此刻,我們得到的條件已經清晰很多,我們知道,QPS位10k,相對來說,已經算是高併發了,但是我們還需要繼續確定。
- 這個短鏈系統的短連結是永久儲存的嗎?面試官回答:是。
- 生成的鍛鍊字元長度有要求嗎?越短越好。
- 錄入的長連結大概是多少個字元呢?有長有短。
- 那麼,平均是多少個字元呢?假設是50個位元組。
通過這些我們可以瞭解到,我們需要對短連結進行持久化。而到目前為止,我們可以得出一些計算:
20k * 365 = 7300k 7300k * (6 + 50) / 1024 = 399.21875M
然後我們需要了解一些常見的效能指標,這是我們需要記在腦子裡的:
- Nginx:能輕鬆的處理c100k問題,記憶體越大,能處理的併發量越高
- Redis:https://redis.io/topics/benchmarks 表明,對於GET/SET來說,QPS 10-100k沒啥大問題
- MySQL:https://www.mysql.com/why-mysql/benchmarks/ 表明,對於只讀,QPS 幾百k沒啥問題,對於寫,MySQL 5.7 QPS 100k 幾乎是上限
- PG:https://www.percona.com/blog/2017/01/06/millions-queries-per-second-postgresql-and-mysql-peaceful-battle-at-modern-demanding-workloads/ 也是差不多
這些資料是不準確的,因為:
- 和怎麼用關係很大
- 和硬體配置關係很大
但是我們心裡還是要有個大概印象。
現在我們就可以知道了,這個短鏈系統,併發是10k/s,但是我們還漏掉了一個問題,就是沒有明確是讀的QPS是10k還是寫,還是讀+寫。 這個時候我們仍然可以向面試官提問。但是,不論讀還是寫,QPS為10k,只要硬體配置過得去,不加快取也ok。但是通常來說,我們還是會 選擇加上,原因很簡單:此刻都有QPS都有10k,保不準半年之後更高了。
到此為止,我們已經知曉瞭解決系統設計題的一個大概思路流程,但是這遠遠不夠,因為系統設計題對知識的廣度要求也很高,因此這裡 我還會提供一些常見的知識,希望能夠對大家有所幫助。
常見知識
- 最簡單粗暴也是實踐中最常用的應對方案就是:升級機器、加機器(所以架構的時候要考慮好水平擴充套件)
- 大多數應用都是讀大於寫,解決方案很簡單:加快取+讀寫分離
- 對於寫大於讀的方案,見(關係型)資料庫優化總結
- Nginx:能輕鬆的處理c100k問題,記憶體越大,能處理的併發量越高
- Redis:https://redis.io/topics/benchmarks 表明,對於GET/SET來說,QPS 10-100k沒啥大問題
- MySQL:https://www.mysql.com/why-mysql/benchmarks/ 表明,對於只讀,QPS 幾百k沒啥問題,對於寫,MySQL 5.7 QPS 100k 幾乎是上限
- PG:https://www.percona.com/blog/2017/01/06/millions-queries-per-second-postgresql-and-mysql-peaceful-battle-at-modern-demanding-workloads/ 也是差不多
- B, M, G, T, PB之間的關係換算要清楚
- 需要長時間處理的任務或者是強依賴網路(而網路不確定性大的問題),妥妥的用佇列,例如訊息推送
- 效能優化套路:加機器 - 加快取 - 優化資料庫索引 - 垂直拆資料庫表 - 水平拆資料庫表 - 垂直分庫 - 水平分庫
此外歡迎讀者提供更多常見知識我收錄到此處。
練習題
- 設計一個短連結系統
- 設計一個壓測工具
- 設計一個分散式ID生成器
- 設計一個論壇
- 設計一個微博