系統設計在面試中一定是最讓面試者頭疼的事情之一。 因為系統設計相關的問題通常是開放式的,所以沒有標準答案。你在和麵試官思想的交流碰撞中會慢慢優化自己的系統設計方案。理論上來說,系統設計面試也是和麵試官一起一步一步改進原有系統設計方案的過程。
系統設計題往往也非常能考察出面試者的綜合能力,回答好的話,很容易就能在面試中脫穎而出。不論是對於參加社招還是校招的小夥伴,都很有必要重視起來。
接下來,我會帶著小夥伴們從我的角度出發來談談:如何準備面試中的系統設計部分。
由於文章篇幅有限,就不列舉實際例子了,可能會在後面的文章中單獨提一些具體的例子。
個人能力有限。如果文章有任何需要改善和完善的地方,歡迎在評論區指出,共同進步!
系統設計面試一般怎麼問?
我簡單總結了一下系統設計面試相關問題的問法:
- 設計一個某某系統比如秒殺系統、微博系統、搶紅包系統、短網址系統。
- 設計某某系統中的一個功能比如嗶哩嗶哩的點贊功能。
- 設計一個框架比如 RPC 框架、訊息佇列、快取框架、分散式檔案系統等等。
- 某某系統的技術選型比如快取用
Redis
還是Memcached
、閘道器用Spring Cloud Gateway
還是Netflix Zuul2
。
系統設計怎麼做?
我們將步驟總結成了以下 4 步。
Step1:問清楚系統具體要求
當面試官給出了系統設計題目之後,一定不要立即開始設計解決方案。 你需要先理解系統設計的需求:功能性需求和非功能性需求。
為了避免自己曲解題目所想要解決的問題,你可以先簡要地給面試官說說自己的理解,
為啥要詢問清楚系統的功能性需求也就是說系統包含哪些功能呢?
畢竟,如果面試官冷不丁地直接讓你設計一個微博系統,你不可能把微博系統涵蓋的功能比如推薦資訊流、會員機制等一個一個都列舉出來,然後再去設計吧!你需要篩選出系統所提供的核心功能(縮小邊界範圍)!
為啥要詢問清楚系統的非功能性需求或者說約束條件比如系統需要達到多少QPS呢?
讓你設計一個1w人用的微博系統和100w人用的微博系統能一樣麼?不同的約束系統對應的系統設計方案肯定是不一樣的。
Step2:對系統進行抽象設計
我們需要在一個 High Level 的層面對系統進行設計。
你可以畫出系統的抽象架構圖,這個抽象架構圖中包含了系統的一些元件以及這些元件之間的連線。
Step3:考慮系統目前需要優化的點
對系統進行抽象設計之後,你需要思考當前抽象的系統設計有哪些需要優化的點,比如說:
- 當前系統部署在一臺機器夠嗎?是否需要部署在多臺機器然後進行負載均衡呢?
- 資料庫處理速度能否支撐業務需求?是否需要給指定欄位加索引?是否需要讀寫分離?是否需要快取?
- 資料量是否大到需要分庫分表?
- 是否存在安全隱患?
- 系統是否需要分散式檔案系統?
- ......
Step4:優化你的系統抽象設計
根據 Step 3 中的“系統需要優化的點” 對系統的抽象設計做進一步完善。
系統設計該如何準備?
知識儲備
系統設計面試非常考察你的知識儲備,系統設計能力的提高需要大量的理論知識儲備。比如說你要知道大型網站架構設計必備的三板斧:
- 高效能架構設計: 熟悉系統常見效能優化手段比如引入 讀寫分離、快取、負載均衡、非同步 等等。
- 高可用架構設計 :CAP理論和BASE理論、通過叢集來提高系統整體穩定性、超時和重試機制、應對介面級故障:降級、熔斷、限流、排隊。
- 高擴充套件架構設計 :說白了就是懂得如何拆分系統。你按照不同的思路來拆分軟體系統,就會得到不同的架構。
實戰
雖然懂得了理論,但是自己沒有進行實踐的話,很多東西是無法體會到的!
因此,你還要 不斷通過實戰專案鍛鍊自己的系統設計能力。
保持好奇心
多思考自己經常瀏覽的網站是怎麼做的。比如:
- 你刷微博的時候可以思考一下微博是如何記錄點贊數量的?
- 你看嗶哩嗶哩的時候可以思考一下訊息提醒系統是如何做的?
- 你使用短鏈系統的時候可以考慮一下短鏈系統是如何做的?
- ......
技術選型
實現同樣的功能,一般會有多種技術選擇方案,比如快取用Redis
還是 Memcached
、閘道器用 Spring Cloud Gateway
還是 Netflix Zuul2
。 很多時候,面試官在系統設計面過程中會具體到技術的選型,因而,你需要區分不同技術的優缺點。
系統設計面試必知
系統設計的時候必然離不開描述效能相關的指標比如 QPS。
效能相關的指標
響應時間
響應時間RT(Response-time)就是使用者發出請求到使用者收到系統處理結果所需要的時間。
RT是一個非常重要且直觀的指標,RT數值大小直接反應了系統處理使用者請求速度的快慢。
併發數
併發數可以簡單理解為系統能夠同時供多少人訪問使用也就是說系統同時能處理的請求數量。
併發數反應了系統的負載能力。
QPS 和 TPS
- QPS(Query Per Second) :伺服器每秒可以執行的查詢次數;
- TPS(Transaction Per Second) :伺服器每秒處理的事務數(這裡的一個事務可以理解為客戶發出請求到收到伺服器的過程);
書中是這樣描述 QPS 和 TPS 的區別的。
QPS vs TPS:QPS 基本類似於 TPS,但是不同的是,對於一個頁面的一次訪問,形成一個TPS;但一次頁面請求,可能產生多次對伺服器的請求,伺服器對這些請求,就可計入“QPS”之中。如,訪問一個頁面會請求伺服器2次,一次訪問,產生一個“T”,產生2個“Q”。
吞吐量
吞吐量指的是系統單位時間內系統處理的請求數量。
一個系統的吞吐量與請求對系統的資源消耗等緊密關聯。請求對系統資源消耗越多,系統吞吐能力越低,反之則越高。
TPS、QPS都是吞吐量的常用量化指標。
- QPS(TPS) = 併發數/平均響應時間(RT)
- 併發數 = QPS * 平均響應時間(RT)
系統活躍度
介紹幾個描述系統活躍度的常見名詞,建議牢牢記住。你不光會在回答系統設計面試題的時候碰到,日常工作中你也會經常碰到這些名詞。
PV(Page View)
訪問量, 即頁面瀏覽量或點選量,衡量網站使用者訪問的網頁數量;在一定統計週期內使用者每開啟或重新整理一個頁面就記錄1次,多次開啟或重新整理同一頁面則瀏覽量累計。UV 從網頁開啟的數量/重新整理的次數的角度來統計的。
UV(Unique Visitor)
獨立訪客,統計1天內訪問某站點的使用者數。1天內相同訪客多次訪問網站,只計算為1個獨立訪客。UV 是從使用者個體的角度來統計的。
DAU(Daily Active User)
日活躍使用者數量。
MAU(monthly active users)
月活躍使用者人數。
舉例:某網站 DAU為 1200w, 使用者日均使用時長 1 小時,RT為0.5s,求併發量和QPS。
平均併發量 = DAU(1200w)* 日均使用時長(1 小時,3600秒) /一天的秒數(86400)=1200w/24 = 50w
真實併發量(考慮到某些時間段使用人數比較少) = DAU(1200w)* 日均使用時長(1 小時,3600秒) /一天的秒數-訪問量比較小的時間段假設為8小時(57600)=1200w/16 = 75w
峰值併發量 = 平均併發量 * 6 = 300w
QPS = 真實併發量/RT = 75W/0.5=100w/s
常用效能測試工具
後端常用
既然系統設計涉及到系統效能方面的問題,那在面試的時候,面試官就很可能會問:你是如何進行效能測試的?
推薦 4 個比較常用的效能測試工具:
- Jmeter :Apache JMeter 是 JAVA 開發的效能測試工具。
- LoadRunner:一款商業的效能測試工具。
- Galtling :一款基於Scala 開發的高效能伺服器效能測試工具。
- ab :全稱為 Apache Bench 。Apache 旗下的一款測試工具,非常實用。
沒記錯的話,除了 LoadRunner 其他幾款效能測試工具都是開源免費的。
前端常用
- Fiddler:抓包工具,它可以修改請求的資料,甚至可以修改伺服器返回的資料,功能非常強大,是Web 除錯的利器。
- HttpWatch: 可用於錄製HTTP請求資訊的工具。
常見軟體的QPS
這裡給出的 QPS 僅供參考,實際專案需要進行壓測來計算。
- Nginx :一般情況下,系統的效能瓶頸基本不會是 Nginx。單機 Nginx 可以達到 30w +。
- Redis: Redis 官方的效能測試報告:https://redis.io/topics/benchmarks 。從報告中,我們可以得出 Redis 的單機 QPS 可以達到 8w+(CPU效能有關係,也和執行的命令也有關係比如執行 SET 命令甚至可以達到10w+QPS)。
- MySQL: MySQL 單機的 QPS 為 大概在 4k 左右。
- Tomcat :單機 Tomcat 的QPS 在 2w左右。這個和你的 Tomcat 配置有很大關係,舉個例子Tomcat 支援的聯結器有 NIO、NIO.2 和 APR。
AprEndpoint
是通過 JNI 呼叫 APR 本地庫而實現非阻塞 I/O 的,效能更好,Tomcat 配置 APR 為 聯結器的話,QPS 可以達到 3w左右。更多相關內容可以自行搜尋 Tomcat 效能優化。
系統設計原則
合適優於先進 > 演化優於一步到位 > 簡單優於複雜
常見的效能優化策略
效能優化之前我們需要對請求經歷的各個環節進行分析,排查出可能出現效能瓶頸的地方,定位問題。
下面是一些效能優化時,我經常拿來自問的一些問題:
- 當前系統的SQL語句是否存在問題?
- 當前系統是否需要升級硬體?
- 系統是否需要快取?
- 系統架構本身是不是就有問題?
- 系統是否存在死鎖的地方?
- 資料庫索引使用是否合理?
- 系統是否存在記憶體洩漏?(Java 的自動回收記憶體雖然很方便,但是,有時候程式碼寫的不好真的會造成記憶體洩漏)
- 系統的耗時操作進行了非同步處理?
- ……
效能優化必知法則
SQL優化,JVM、DB,Tomcat引數調優 > 硬體效能優化(記憶體升級、CPU核心數增加、機械硬碟—>固態硬碟等等)> 業務邏輯優化/快取 > 讀寫分離、叢集等 > 分庫分表
系統設計面試的注意事項
想好再說
沒必要面試官剛問了問題之後,你沒準備好就開始回答。這樣不會給面試官帶來好印象的!系統設計本就需要面試者結合自己的以往的經驗進行思考,這個過程是需要花費一些時間的。
沒有絕對的答案
系統設計沒有標準答案。重要的是你和麵試官一起交流的過程。
一般情況下,你會在和麵試官的交流過程中,一步一步完成系統設計。這個過程中,你會在面試官的引導下不斷完善自己的系統設計方案。
因此,你不必要在系統設計面試之前找很多題目,然後只是單純記住他們的答案。
勿要絕對
系統設計沒有最好的設計方案,只有最合適的設計方案。這就類比架構設計了:軟體開發沒有銀彈,架構設計的目的就是選擇合適的解決方案。 何為銀彈? 狼人傳說中,只有銀彈(銀質子彈)才能制服這些猛獸。對應到軟體開發活動中,銀彈特指開發者們尋求的一種克服軟體開發這個難纏的猛獸的“萬能鑰匙?”。
權衡利弊
知道使用某個技術可能會為系統帶來的利弊。比如使用訊息佇列的好處是解耦和削峰,但是,同樣也讓系統可用性降低、複雜性提高,同時還會存在一致性問題(訊息丟失或者訊息未被消費咋辦)。
慢慢優化
剛開始設計的系統不需要太完美,可以慢慢優化。
不追新技術
使用穩定的、適合業務的技術,不必要過於追求新技術。
追簡避雜
系統設計應當追求簡單避免複雜。KISS( Keep It Simple, Stupid)原則——保持簡單,易於理解。
總結
這篇文章簡單帶著小夥伴們分析了一下系統設計面試。如果你還想要深入學習的話,可以參考: https://github.com/donnemartin/system-design-primer 。
參考
- https://github.com/donnemartin/system-design-primer
- https://www.acecodeinterview.com/intro/
- https://gist.github.com/vasanthk/485d1c25737e8e72759f
微信搜“JavaGuide”回覆“計算機基礎”即可獲取圖解計算機基礎+個人原創的 Java 面試手冊。