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