「緩存淘汰策略到底在淘汰什么?負(fù)載均衡真的只是隨機分配嗎?」——這些面試必問的系統(tǒng)設(shè)計題,答案往往停留在八股文層面。一位開發(fā)者在學(xué)習(xí)筆記里扒開了這些概念的底層邏輯,有些發(fā)現(xiàn)甚至和主流認(rèn)知相反。
一、輪詢與推送:長輪詢不是"更長的輪詢"
![]()
客戶端獲取服務(wù)器更新的方式,本質(zhì)只有兩種:輪詢(Poll)和推送(Push)。但三種具體實現(xiàn)的技術(shù)選型,藏著容易被忽略的工程陷阱。
短輪詢(Short Polling)最直觀:客戶端定時發(fā)請求問服務(wù)器"有消息嗎",沒有就立即返回空響應(yīng)。優(yōu)點是實現(xiàn)簡單,缺點是空跑嚴(yán)重——服務(wù)器壓力隨客戶端數(shù)量線性增長,實時性還受限于輪詢間隔。
長輪詢(Long Polling)常被誤解為"把輪詢間隔拉長",實際上完全不是一回事。客戶端發(fā)起請求后,服務(wù)器會掛起這個HTTP連接,直到有新數(shù)據(jù)才返回響應(yīng)。連接結(jié)束后客戶端立即發(fā)起新請求,保持"隨時待命"狀態(tài)。
這帶來一個反直覺的成本:長輪詢的服務(wù)器資源占用比短輪詢更高。每個掛起的連接都需要維持TCP會話,高并發(fā)場景下容易觸及服務(wù)器的連接數(shù)上限。很多開發(fā)者直到壓測時才意識到,"更優(yōu)方案"反而成了瓶頸。
真正的推送方案是SSE(服務(wù)器推送事件)和WebSocket。SSE基于HTTP,適合服務(wù)器單向推送場景;WebSocket建立后是全雙工通道,雙方隨時發(fā)數(shù)據(jù)。但WebSocket的維護復(fù)雜度常被低估——心跳檢測、斷線重連、代理穿透,每個都是生產(chǎn)環(huán)境的坑。
二、擴展的兩種哲學(xué):縱向是賭命,橫向是手術(shù)
垂直擴展(Vertical Scaling)和水平擴展(Horizontal Scaling)的選擇,本質(zhì)是風(fēng)險偏好的體現(xiàn)。
縱向擴展就是給單臺服務(wù)器加配置:更多CPU、更大內(nèi)存、更快磁盤。這像給老車換引擎——見效快,但天花板明顯。單機性能總有物理極限,且升級過程往往需要停機,形成"維護窗口"的業(yè)務(wù)損失。
更隱蔽的風(fēng)險是單點故障。一臺價值50萬的高端服務(wù)器宕機,和五臺10萬的服務(wù)器掛掉一臺,業(yè)務(wù)連續(xù)性完全不同。后者可以用負(fù)載均衡快速切流,前者直接服務(wù)中斷。
水平擴展則是分布式架構(gòu)的起點:加機器,分流量。但這需要系統(tǒng)層面配合——無狀態(tài)化設(shè)計、數(shù)據(jù)分片策略、分布式事務(wù)處理。很多"無法水平擴展"的遺留系統(tǒng),問題不在技術(shù)而在歷史包袱:session粘滯、本地緩存依賴、數(shù)據(jù)庫自增ID。
一個判斷標(biāo)準(zhǔn):如果擴展需要改動應(yīng)用代碼,說明架構(gòu)債務(wù)已經(jīng)累積。理想狀態(tài)下,擴縮容應(yīng)該只是運維層面的機器增減。
三、負(fù)載均衡:隨機是最差的策略
負(fù)載均衡器(Load Balancer)被簡單理解為"流量分配器",但分配策略的選擇直接影響系統(tǒng)穩(wěn)定性。
輪詢(Round Robin)最公平,卻無視服務(wù)器的實際負(fù)載。一臺機器因為GC停頓響應(yīng)變慢,輪詢?nèi)詴丛床粩嗳埱筮^去。加權(quán)輪詢稍微改進,但權(quán)重調(diào)整往往滯后于真實狀態(tài)。
最少連接數(shù)(Least Connections)策略更聰明:把新請求發(fā)給當(dāng)前活躍連接最少的后端。這適合長連接場景,比如WebSocket服務(wù)。但短連接密集時,連接數(shù)的統(tǒng)計噪聲會讓策略失效。
最實用的往往是健康檢查+動態(tài)剔除的組合。負(fù)載均衡器持續(xù)探測后端狀態(tài),發(fā)現(xiàn)異常立即移出池子。很多故障不是瞬間崩潰,而是響應(yīng)時間逐漸劣化——沒有健康檢查,這些"慢節(jié)點"會持續(xù)拖累整體性能。
反向代理(Reverse Proxy)和正向代理(Forward Proxy)常被混淆。正向代理站在客戶端一側(cè),幫用戶訪問目標(biāo)網(wǎng)站(比如翻墻);反向代理站在服務(wù)器一側(cè),對外暴露統(tǒng)一入口,對內(nèi)分發(fā)到具體服務(wù)。Nginx、HAProxy、AWS ALB都是反向代理的實現(xiàn)。
四、緩存淘汰:LRU不是銀彈
緩存滿了怎么辦?淘汰策略(Cache Eviction Policy)決定哪些數(shù)據(jù)該被扔掉。但"最近最少使用"(LRU)的流行,掩蓋了其他策略的適用場景。
LRU的核心假設(shè)是:過去被訪問的數(shù)據(jù)未來更可能被訪問。這在用戶行為穩(wěn)定的場景成立,但面對周期性批量任務(wù)時會失效。比如每晚運行的報表生成,會把大量冷數(shù)據(jù)一次性灌入緩存,擠掉真正的高頻熱點。
LFU(最不經(jīng)常使用)計數(shù)訪問頻次,能識別長期熱點,但無法適應(yīng)興趣漂移。一個突然爆火的新聞事件,在LFU策略下要積累足夠計數(shù)才能常駐緩存,錯失流量高峰。
TTL(生存時間)策略最簡單:給數(shù)據(jù)設(shè)置過期時間。適合時效性強的場景,比如驗證碼、限時活動。但需要預(yù)估合理的過期時長,太短增加回源壓力,太長導(dǎo)致數(shù)據(jù)陳舊。
生產(chǎn)環(huán)境往往是混合策略:LRU處理常規(guī)流量,TTL兜底異常場景,再輔以手動標(biāo)記的"永不過期"關(guān)鍵數(shù)據(jù)。緩存設(shè)計最難的不是技術(shù)選型,而是對業(yè)務(wù)訪問模式的準(zhǔn)確建模。
五、API網(wǎng)關(guān)與冪等性:分布式系統(tǒng)的安全帶
API網(wǎng)關(guān)作為統(tǒng)一入口,職責(zé)常被過度膨脹。認(rèn)證、限流、路由、協(xié)議轉(zhuǎn)換、日志采集——功能堆砌后,網(wǎng)關(guān)本身成為新的單點瓶頸。一個設(shè)計原則是:網(wǎng)關(guān)只處理橫切關(guān)注點,業(yè)務(wù)邏輯下沉到微服務(wù)。
冪等性(Idempotency)是分布式系統(tǒng)的核心概念,卻少有工程團隊真正落實。定義很明確:同一操作執(zhí)行多次,結(jié)果與執(zhí)行一次相同。但實現(xiàn)層面,網(wǎng)絡(luò)超時、消息重試、用戶重復(fù)點擊,都會打破這個假設(shè)。
HTTP方法的冪等性設(shè)計值得細品。GET天然冪等,因為不修改狀態(tài);POST創(chuàng)建資源,多次調(diào)用會生成多個記錄;PUT更新為指定值,多次執(zhí)行結(jié)果一致;DELETE刪除資源,第一次成功后續(xù)都是"資源不存在"——也算冪等。
實際業(yè)務(wù)中,POST的冪等性最難保證。常見方案是客戶端生成唯一請求ID,服務(wù)端用數(shù)據(jù)庫唯一索引或分布式鎖去重。但請求ID的生成、傳遞、存儲都有成本,很多團隊直到出現(xiàn)重復(fù)訂單才補課。
一個犀利觀察:冪等性實現(xiàn)往往和"性能優(yōu)化"沖突。去重檢查需要額外存儲和查詢,高并發(fā)場景下可能成為瓶頸。這解釋了為什么金融支付系統(tǒng)愿意投入大量工程資源做冪等,而內(nèi)容社區(qū)往往選擇性忽略——業(yè)務(wù)對一致性的容忍度,決定了技術(shù)投入的上限。
六、WebSocket:全雙工的代價
WebSocket解決了HTTP半雙工的痛點,但"隨時雙向通信"的能力不是免費的。
建立連接需要一次HTTP升級握手,這消耗1個RTT。連接維持期間,TCP keepalive和WebSocket心跳包持續(xù)占用帶寬。更重要的是,WebSocket連接有狀態(tài)——服務(wù)器需要維護連接映射表,水平擴展時必須解決會話同步問題。
很多團隊用Redis存儲用戶ID到服務(wù)器實例的映射,實現(xiàn)"消息路由"。但這引入新的依賴:Redis宕機怎么辦?網(wǎng)絡(luò)分區(qū)時消息往哪發(fā)?這些復(fù)雜度在選型演示時往往被跳過。
一個替代方案是SSE(Server-Sent Events),基于HTTP流實現(xiàn)服務(wù)器推送。無法客戶端主動推送,但實現(xiàn)簡單、自動支持HTTP/2多路復(fù)用、代理兼容性更好。如果業(yè)務(wù)場景是服務(wù)器主導(dǎo)的信息流(股價、通知、日志),SSE可能是更務(wù)實的選擇。
七、TCP:可靠性的幻覺
原文對TCP的定義極簡:"兩臺設(shè)備在網(wǎng)絡(luò)上的對話方式"。但這句輕描淡寫背后,藏著系統(tǒng)設(shè)計的關(guān)鍵認(rèn)知。
TCP的可靠性是端到端的承諾,不是應(yīng)用層的保證。數(shù)據(jù)成功抵達操作系統(tǒng)內(nèi)核,不代表業(yè)務(wù)程序已處理;連接正常建立,不代表對方服務(wù)已就緒。很多"神秘丟數(shù)據(jù)"的bug,根源在于混淆了傳輸層和應(yīng)用層的邊界。
WebSocket基于TCP,繼承了這些特性,也繼承了這些問題。應(yīng)用層需要自己實現(xiàn)消息確認(rèn)、順序保證、斷線重連——這些正是MQTT、STOMP等協(xié)議存在的意義。直接裸用WebSocket的團隊,往往在生產(chǎn)環(huán)境踩完所有坑后才意識到需要協(xié)議封裝。
八、學(xué)習(xí)筆記的啟示:概念清晰比架構(gòu)圖重要
這份學(xué)習(xí)筆記的價值,不在于覆蓋了多少高級主題,而在于對每個基礎(chǔ)概念的精準(zhǔn)定義。系統(tǒng)設(shè)計面試常陷入一個誤區(qū):追求分布式事務(wù)、一致性算法等"高級"話題,卻說不清負(fù)載均衡的具體策略。
真正的工程能力,體現(xiàn)在對基礎(chǔ)概念的邊界認(rèn)知:知道長輪詢的資源代價、明白LRU的失效場景、理解冪等性的實現(xiàn)成本。這些細節(jié)不會出現(xiàn)在
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.