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