面試官:如何設(shè)計一個高并發(fā)系統(tǒng)?你會怎么回答呢?
一、高并發(fā)系統(tǒng)面臨的挑戰(zhàn)
在互聯(lián)網(wǎng)業(yè)務(wù)場景中,當系統(tǒng)需要處理每秒數(shù)萬甚至數(shù)十萬的并發(fā)請求時,傳統(tǒng)的單體架構(gòu)將面臨嚴峻考驗。典型的高并發(fā)瓶頸主要存在于以下四個層面:
1. 硬件資源瓶頸:單機CPU處理能力、內(nèi)存容量、磁盤I/O吞吐量、網(wǎng)絡(luò)帶寬等物理限制
2. 數(shù)據(jù)庫瓶頸:傳統(tǒng)關(guān)系型數(shù)據(jù)庫的ACID特性導(dǎo)致寫入性能低下,單表存儲能力受限
3. 網(wǎng)絡(luò)瓶頸:TCP連接數(shù)限制、HTTP協(xié)議頭冗余、頻繁的三次握手消耗
4. 同步阻塞瓶頸:線程上下文切換開銷、鎖競爭導(dǎo)致的資源等待
二、核心架構(gòu)設(shè)計原則
2.1 水平擴展架構(gòu)
負載均衡策略
? LVS四層負載均衡:基于IP+端口進行流量分發(fā),支持DR/NAT/TUN模式
? Nginx七層負載均衡:支持HTTP/HTTPS協(xié)議,提供加權(quán)輪詢、IP哈希、最小連接數(shù)等算法
? 動態(tài)權(quán)重調(diào)整:基于節(jié)點負載情況(CPU、內(nèi)存、連接數(shù))實時調(diào)整權(quán)重
? 一致性哈希算法:通過虛擬節(jié)點實現(xiàn)平滑擴容縮容,減少數(shù)據(jù)遷移量
upstream backend {
hash $request_uri consistent;
server 10.0.0.1:8080 weight=5;
server 10.0.0.2:8080 weight=3;
server 10.0.0.3:8080 backup;
}
無狀態(tài)服務(wù)設(shè)計
? Session狀態(tài)存儲:采用Redis Cluster存儲會話數(shù)據(jù),通過JWT Token傳遞會話信息
? 請求上下文傳遞:使用TraceID實現(xiàn)全鏈路追蹤,結(jié)合OpenTracing協(xié)議
? 配置中心化:通過Apollo或Nacos實現(xiàn)配置動態(tài)下發(fā),避免服務(wù)重啟
2.2 多級緩存體系
緩存架構(gòu)層次
1. 客戶端緩存:HTTP Cache-Control、ETag、LocalStorage
2. CDN緩存:邊緣節(jié)點緩存靜態(tài)資源,通過Purge API主動刷新
3. 反向代理緩存:Nginx Proxy Cache基于LRU算法緩存動態(tài)內(nèi)容
4. 進程內(nèi)緩存:Caffeine實現(xiàn)本地?zé)狳c緩存,設(shè)置軟引用避免OOM
5. 分布式緩存:Redis Cluster集群模式,采用CRC16分片算法
緩存更新策略
? Cache-Aside Pattern:先讀緩存,未命中時查詢數(shù)據(jù)庫并回填
? Write-Through:同步更新緩存和數(shù)據(jù)庫,保證強一致性
? Write-Behind:異步批量更新,提升寫入吞吐量
? 過期策略:TTL隨機化(基礎(chǔ)時間±隨機值)避免緩存雪崩
public Object getData(String key) {
Object value = redis.get(key);
if (value == null) {
if (redis.setnx(key + ":mutex", 1, 60)) {
value = db.query(key);
redis.setex(key, 300, value);
redis.del(key + ":mutex");
} else {
Thread.sleep(50);
return getData(key);
}
}
return value;
}
2.3 數(shù)據(jù)庫優(yōu)化方案
分庫分表策略
? 垂直分庫:按業(yè)務(wù)模塊拆分(用戶庫、訂單庫、商品庫)
? 水平分表:采用ShardingKey(用戶ID哈希)分片,使用基因法避免跨片查詢
? 全局索引表:建立ID映射關(guān)系表,解決分片鍵與查詢條件不匹配問題
? 雙寫機制:新老分片方案并行期間,通過canal同步數(shù)據(jù)
讀寫分離架構(gòu)
? 主從復(fù)制:基于GTID的半同步復(fù)制,設(shè)置從庫read_only=ON
? 讀寫分離中間件:MyCat實現(xiàn)SQL路由,自動識別SELECT語句
? 數(shù)據(jù)延遲處理:通過影子庫壓測確定延遲閾值,重要業(yè)務(wù)強制讀主
2.4 異步處理機制
消息隊列設(shè)計
? Kafka分區(qū)設(shè)計:根據(jù)業(yè)務(wù)Key(如訂單ID)分區(qū),保證順序性
? 消費冪等性:通過Redis原子操作實現(xiàn)去重
? 批量壓縮:配置linger.ms=20和batch.size=16384提升吞吐量
? 死信隊列:處理失敗消息,設(shè)置重試次數(shù)閾值
@KafkaListener(topics = "order_topic")
public void process(OrderMessage message) {
String idempotentKey = "msg:" + message.getMsgId();
if (redis.set(idempotentKey, "1", "NX", "EX", 3600)) {
orderService.createOrder(message);
}
}
異步化改造
? Servlet3.0異步請求:通過AsyncContext釋放容器線程
? CompletableFuture鏈式調(diào)用:整合多個微服務(wù)調(diào)用
? 響應(yīng)式編程:基于Project Reactor實現(xiàn)背壓控制
2.5 限流降級策略
限流算法實現(xiàn)
? 滑動窗口算法:基于Redis的zset實現(xiàn)時間窗計數(shù)
? 令牌桶算法:Guava RateLimiter的SmoothBursty實現(xiàn)
? 動態(tài)限流:Sentinel根據(jù)QPS/線程數(shù)/系統(tǒng)負載動態(tài)調(diào)整閾值
public voidconfigureRules() {
List<FlowRule> rules = newArrayList<>();
FlowRulerule=newFlowRule();
rule.setResource("createOrder");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(1000);
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
rule.setWarmUpPeriodSec(10);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
熔斷降級機制
? 熔斷狀態(tài)機:Closed->Open->Half-Open狀態(tài)轉(zhuǎn)換
? 異常比例統(tǒng)計:Hystrix滑動窗口統(tǒng)計最近10秒失敗率
? 服務(wù)降級方案:返回兜底數(shù)據(jù)(緩存值/默認值)、排隊頁面、服務(wù)托底
三、進階優(yōu)化手段
3.1 連接池優(yōu)化
? Redis連接池:Lettuce配置共享連接,設(shè)置maxActive=1000
? 數(shù)據(jù)庫連接池:Druid開啟異步銷毀,配置minIdle=50,maxActive=500
? HTTP連接池:OkHttp設(shè)置連接?;?分鐘,最大空閑連接數(shù)200
3.2 協(xié)議優(yōu)化
? 序列化協(xié)議:Protobuf相比JSON減少50%數(shù)據(jù)體積
? 長連接復(fù)用:HTTP/2多路復(fù)用替代短連接
? 二進制傳輸:WebSocket替代輪詢方案
3.3 流量調(diào)度策略
? DNS智能解析:根據(jù)用戶地理位置返回最優(yōu)IP
? 全站加速:QUIC協(xié)議解決TCP隊頭阻塞問題
? 邊緣計算:在CDN節(jié)點運行WebAssembly處理簡單邏輯
四、全鏈路壓測方案
1. 影子庫壓測:復(fù)制生產(chǎn)環(huán)境數(shù)據(jù)庫結(jié)構(gòu),隔離測試數(shù)據(jù)
2. 流量錄制回放:通過tcpdump抓取真實流量,調(diào)整時間倍率
3. 服務(wù)全鏈路監(jiān)控:Pinpoint追蹤每個Span的耗時和狀態(tài)
4. 彈性擴縮容:根據(jù)CPU利用率動態(tài)調(diào)整K8s副本數(shù)
五、容災(zāi)設(shè)計要點
1. 多活架構(gòu):單元化部署,每個單元包含完整業(yè)務(wù)閉環(huán)
2. 數(shù)據(jù)同步:使用GoldenGate實現(xiàn)跨機房雙向同步
3. 故障演練:ChaosBlade模擬網(wǎng)絡(luò)分區(qū)、節(jié)點宕機等場景
4. 灰度發(fā)布:基于Header的流量染色,逐步切量驗證
六、總結(jié)
高并發(fā)系統(tǒng)設(shè)計需要從架構(gòu)設(shè)計、中間件選型、代碼優(yōu)化等多個維度進行系統(tǒng)性優(yōu)化。在實際實施過程中,需要建立完善的監(jiān)控體系,持續(xù)跟蹤系統(tǒng)瓶頸。建議采用漸進式優(yōu)化策略,通過全鏈路壓測驗證優(yōu)化效果,同時建立容災(zāi)預(yù)案,保證業(yè)務(wù)連續(xù)性。隨著云原生技術(shù)的發(fā)展,Service Mesh、Serverless等新范式正在改變高并發(fā)系統(tǒng)的實現(xiàn)方式,架構(gòu)師需要持續(xù)關(guān)注技術(shù)演進趨勢。
本文轉(zhuǎn)載自微信公眾號「程序員秋天」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系公眾號。