系統(tǒng)高可用的十條軍規(guī)
前言
系統(tǒng)高可用是非常經(jīng)典的問(wèn)題,無(wú)論在面試,還是實(shí)際工作中,都經(jīng)常會(huì)遇到。
這篇文章跟大家一起聊聊,保證系統(tǒng)高可用的10條軍規(guī),希望對(duì)你會(huì)有所幫助。
圖片
1.冗余部署
場(chǎng)景:某電商大促期間,數(shù)據(jù)庫(kù)主節(jié)點(diǎn)突然宕機(jī),導(dǎo)致全站交易癱瘓。
問(wèn)題:?jiǎn)喂?jié)點(diǎn)部署的系統(tǒng),一旦關(guān)鍵組件(如數(shù)據(jù)庫(kù)、消息隊(duì)列)故障,業(yè)務(wù)直接歸零。
解決方案:通過(guò)主從復(fù)制、集群化部署實(shí)現(xiàn)冗余。例如MySQL主從同步,Redis Sentinel哨兵機(jī)制。
圖片
MySQL主從配置如下:
-- 主庫(kù)配置
CHANGE MASTER TO
MASTER_HOST='master_host',
MASTER_USER='replica_user',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
-- 從庫(kù)啟動(dòng)復(fù)制
START SLAVE;
效果:主庫(kù)宕機(jī)時(shí),從庫(kù)自動(dòng)切換為可讀寫狀態(tài),業(yè)務(wù)無(wú)感知。
2.服務(wù)熔斷
場(chǎng)景:支付服務(wù)響應(yīng)延遲,導(dǎo)致訂單服務(wù)線程池耗盡,引發(fā)連鎖故障。
問(wèn)題:服務(wù)依賴鏈中某個(gè)環(huán)節(jié)異常,會(huì)像多米諾骨牌一樣拖垮整個(gè)系統(tǒng)。
解決方案:引入熔斷器模式,例如Hystrix或Resilience4j。
Resilience4j熔斷配置如下:
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 失敗率超過(guò)50%觸發(fā)熔斷
.waitDurationInOpenState(Duration.ofMillis(1000))
.build();
CircuitBreaker circuitBreaker = CircuitBreaker.of("paymentService", config);
// 調(diào)用支付服務(wù)
Supplier<String> supplier = () -> paymentService.call();
Supplier<String> decoratedSupplier = CircuitBreaker
.decorateSupplier(circuitBreaker, supplier);
效果:當(dāng)支付服務(wù)失敗率飆升時(shí),自動(dòng)熔斷并返回降級(jí)結(jié)果(如“系統(tǒng)繁忙,稍后重試”)。
3.流量削峰
場(chǎng)景:秒殺活動(dòng)開(kāi)始瞬間,10萬(wàn)QPS直接擊穿數(shù)據(jù)庫(kù)連接池。
問(wèn)題:突發(fā)流量超過(guò)系統(tǒng)處理能力,導(dǎo)致資源耗盡。
解決方案:引入消息隊(duì)列(如Kafka、RocketMQ)做異步緩沖。
用戶下單的系統(tǒng)流程圖如下:
圖片
RocketMQ生產(chǎn)者的示例代碼:
DefaultMQProducer producer = new DefaultMQProducer("seckill_producer");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message msg = new Message("seckill_topic", "訂單數(shù)據(jù)".getBytes());
producer.send(msg);
效果:將瞬時(shí)10萬(wàn)QPS的請(qǐng)求平滑處理為數(shù)據(jù)庫(kù)可承受的2000 TPS。
4.動(dòng)態(tài)擴(kuò)容
場(chǎng)景:日常流量100臺(tái)服務(wù)器足夠,但大促時(shí)需要快速擴(kuò)容到500臺(tái)。
問(wèn)題:固定資源無(wú)法應(yīng)對(duì)業(yè)務(wù)波動(dòng),手動(dòng)擴(kuò)容效率低下。
解決方案:基于Kubernetes的HPA(Horizontal Pod Autoscaler)。
K8s HPA 的配置如下:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
效果:CPU利用率超過(guò)60%時(shí)自動(dòng)擴(kuò)容,低于30%時(shí)自動(dòng)縮容。
5.灰度發(fā)布
場(chǎng)景:新版本代碼存在內(nèi)存泄漏,全量發(fā)布導(dǎo)致線上服務(wù)崩潰。
問(wèn)題:一次性全量發(fā)布風(fēng)險(xiǎn)極高,可能引發(fā)全局故障。
解決方案:基于流量比例的灰度發(fā)布策略。
Istio流量染色配置如下:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- bookinfo.com
http:
- route:
- destination:
host: reviews
subset: v1
weight: 90 # 90%流量走老版本
- destination:
host: reviews
subset: v2
weight: 10 # 10%流量走新版本
效果:新版本異常時(shí),僅影響10%的用戶,快速回滾無(wú)壓力。
6.降級(jí)開(kāi)關(guān)
場(chǎng)景:推薦服務(wù)超時(shí)導(dǎo)致商品詳情頁(yè)加載時(shí)間從200ms飆升到5秒。
問(wèn)題:非核心功能異常影響核心鏈路用戶體驗(yàn)。
解決方案:配置中心增加降級(jí)開(kāi)關(guān),如果遇到緊急情況,能 動(dòng)態(tài)降級(jí)非關(guān)鍵服務(wù)。
Apollo配置中心的示例代碼如下:
@ApolloConfig
private Config config;
public ProductDetail getDetail(String productId) {
if(config.getBooleanProperty("recommend.switch", true)) {
// 調(diào)用推薦服務(wù)
}
// 返回基礎(chǔ)商品信息
}
效果:關(guān)閉推薦服務(wù)后,詳情頁(yè)響應(yīng)時(shí)間恢復(fù)至200ms以內(nèi)。
7.全鏈路壓測(cè)
場(chǎng)景:某金融系統(tǒng)在真實(shí)流量下暴露出數(shù)據(jù)庫(kù)死鎖問(wèn)題。
問(wèn)題:測(cè)試環(huán)境無(wú)法模擬真實(shí)流量特征,線上隱患難以發(fā)現(xiàn)。
解決方案:基于流量錄制的全鏈路壓測(cè)。
實(shí)施步驟:
- 線上流量錄制(如Jmeter+TCPCopy)
- 影子庫(kù)隔離(壓測(cè)數(shù)據(jù)寫入隔離存儲(chǔ))
- 壓測(cè)數(shù)據(jù)脫敏
- 執(zhí)行壓測(cè)并監(jiān)控系統(tǒng)瓶頸
效果:提前發(fā)現(xiàn)數(shù)據(jù)庫(kù)連接池不足、緩存穿透等問(wèn)題。
8.數(shù)據(jù)分片
場(chǎng)景:用戶表達(dá)到10億行,查詢性能斷崖式下降。
問(wèn)題:?jiǎn)螏?kù)單表成為性能瓶頸。
解決方案:基于ShardingSphere的分庫(kù)分表。
分庫(kù)分表的配置如下:
sharding:
tables:
user:
actualDataNodes: ds_${0..1}.user_${0..15}
tableStrategy:
standard:
shardingColumn: user_id
preciseAlgorithmClassName: HashModShardingAlgorithm
preciseAlgorithmType: HASH_MOD
shardingCount: 16
效果:10億數(shù)據(jù)分散到16個(gè)物理表,查詢性能提升20倍。
9.混沌工程
場(chǎng)景:某次機(jī)房網(wǎng)絡(luò)抖動(dòng)導(dǎo)致服務(wù)不可用3小時(shí)。
問(wèn)題:系統(tǒng)健壯性不足,故障恢復(fù)能力弱。
解決方案:使用ChaosBlade模擬故障。
示例命令:
# 模擬網(wǎng)絡(luò)延遲
blade create network delay --time 3000 --interface eth0
# 模擬數(shù)據(jù)庫(kù)節(jié)點(diǎn)宕機(jī)
blade create docker kill --container-id mysql-node-1
效果:提前發(fā)現(xiàn)緩存穿透導(dǎo)致DB負(fù)載過(guò)高的問(wèn)題,優(yōu)化緩存擊穿防護(hù)策略。
10.立體化監(jiān)控
場(chǎng)景:磁盤IOPS突增導(dǎo)致訂單超時(shí),但運(yùn)維人員2小時(shí)后才發(fā)現(xiàn)。
問(wèn)題:監(jiān)控維度單一,無(wú)法快速定位根因。
解決方案:構(gòu)建Metrics-Log-Trace三位一體監(jiān)控體系。
技術(shù)棧組合:
- Metrics:Prometheus + Grafana(資源指標(biāo))
- Log:ELK(日志分析)
- Trace:SkyWalking(調(diào)用鏈追蹤)
定位問(wèn)題流程如下 :
CPU利用率 > 80% → 關(guān)聯(lián)日志檢索 → 定位到GC頻繁 →
追蹤調(diào)用鏈 → 發(fā)現(xiàn)某個(gè)DAO層SQL未走索引
效果:故障定位時(shí)間從小時(shí)級(jí)縮短到分鐘級(jí)。
總結(jié)
系統(tǒng)高可用建設(shè)就像打造一艘遠(yuǎn)洋巨輪。
冗余部署是雙發(fā)動(dòng)機(jī),熔斷降級(jí)是救生艇,監(jiān)控體系是雷達(dá)系統(tǒng)。
但真正的關(guān)鍵在于:
- 故障預(yù)防比故障處理更重要(如混沌工程)
- 自動(dòng)化是應(yīng)對(duì)復(fù)雜性的唯一出路(如K8s彈性擴(kuò)縮)
- 數(shù)據(jù)驅(qū)動(dòng)的優(yōu)化才是王道(全鏈路壓測(cè)+立體監(jiān)控)
沒(méi)有100%可用的系統(tǒng),但通過(guò)這10個(gè)實(shí)戰(zhàn)技巧,我們可以讓系統(tǒng)的可用性從99%提升到99.99%。
這0.99%的提升,可能意味著每年減少8小時(shí)的故障時(shí)間——而這,正是架構(gòu)師價(jià)值的體現(xiàn)。