讀完這章你要能回答:架構是在哪些維度之間取捨?我有沒有用 ADR 留下決策脈絡?
架構決策的影響是長期的,需要深思熟慮。
架構設計的本質#
架構設計的本質是做取捨。沒有完美的架構,只有在特定約束下最合適的架構。
喬新亮在《CTO 成長復盤》中分享了架構設計的核心思想:
架構師的角色#
架構師只是個角色,不是個職位。—— 畢玄
架構師的職責:
- 理解業務需求和技術約束
- 做出關鍵的技術決策
- 指導團隊實施方案
- 為決策的後果負責
架構師需要的能力:
mindmap
root((架構師能力))
💻 技術能力
深度:某個領域的專家
廣度:了解各種技術方案
判斷力:知道什麼時候用什麼
📊 業務理解
理解業務需求
預見未來發展
平衡業務和技術
🗣️ 溝通能力
解釋技術決策給非技術人員
說服團隊接受方案
協調各方利益架構設計的原則#
喬新亮總結的核心原則:
| 原則 | 說明 | 例子 |
|---|---|---|
| 簡單 | 能簡單就不要複雜 | 能用單體就不要微服務 |
| 合適 | 滿足當前需求即可 | 不要過度設計 |
| 演進 | 架構會持續演進 | 為變化留空間 |
| 權衡 | 一切都是取捨 | 性能 vs 成本 vs 複雜度 |
第二系統效應與沒有銀彈#
「簡單、合適、演進、權衡」之所以難守,是因為兩股力量在拉扯:人會想把第二個系統做得「完整」,也會期待某個新技術能一舉解決所有問題。兩者都是陷阱。
第二系統效應:一個人設計的第二個系統,是最危險的系統。第一個系統因為經驗不足而克制;嚐到成功後,設計者會把第一版裡所有「當初想做卻沒做」的功能全部塞進第二版,導致過度設計、臃腫不堪。對「這個也加、那個也加」的衝動保持高度警覺。
要理解為什麼沒有一勞永逸的解法,先區分兩種複雜度:
| 複雜度類型 | 來源 | 能否消除 |
|---|---|---|
| 本質複雜度 | 問題本身固有的困難 | 無法消除,只能管理 |
| 偶然複雜度 | 工具、流程、實作引入的困難 | 可透過更好的工具/方法削減 |
過去的生產力躍進(高階語言、IDE)多半是在削減偶然複雜度。但軟體的本質複雜度來自四個內在屬性,它們無法被任何單一技術抹除:
- 複雜(complexity):軟體的狀態空間巨大,沒有兩個部分完全相同。
- 順從(conformity):軟體必須遷就外部世界(既有系統、法規、人)的任意規則。
- 易變(changeability):軟體被期待持續修改,且改動成本相對「便宜」而被無止盡要求。
- 不可見(invisibility):軟體沒有自然的幾何形狀,難以視覺化與直觀掌握。
因此「沒有銀彈」——不存在能讓生產力或可靠性在十年內提升一個數量級的單一技術。真正有效的,是幾個務實方向:
- 買,而非建:能買現成的就別自己造。
- 快速原型:用原型釐清需求,而非一開始就寫死規格。
- 漸進成長:讓系統有機地生長,而非一次設計到位。
- 培育菁英設計者:好設計來自卓越的個人,投資在頂尖設計者身上。
1995 年的回顧:作者改口支持漸進成長
「沒有銀彈」原文寫於 1986 年,當時對「漸進成長 / 增量開發」著墨不深。十年後(1995 年)作者回顧時明確改口,認為漸進式、增量成長才是應對軟體本質複雜度最有力的取向——與其一次性瀑布式地把系統設計完整,不如讓它從一個能跑的最小系統逐步長大。
這也呼應了 開發模式與流程 中對瀑布與敏捷的中立框架:問題不在「哪個模型最好」,而在「面對本質複雜度,漸進演進通常比一次到位更可靠」。
概念完整性:最重要的設計品質#
概念完整性(conceptual integrity)是系統設計中最重要的品質。一個概念一致、由統一思路貫穿的系統,即使少了幾個功能,也遠勝過一堆優秀功能各行其是、彼此打架的拼湊物。
要守住概念完整性,先要分清兩件常被混淆的事:架構與實作。
| 維度 | 回答的問題 | 對象 | 例子 |
|---|---|---|---|
| 架構 | 系統做什麼、長怎樣 | 使用者所見 | API 介面、命令集、資料模型、行為 |
| 實作 | 系統怎麼建出來 | 內部如何做 | 演算法、資料結構、模組切分、選型 |
由此衍生幾個重要觀念:
- 一個架構,多種實作:同一份架構規格可以有多種實作方式;架構是契約,實作是兌現契約的手段。釐清兩者,才能在不破壞使用者所見的前提下自由重構內部。
- form is liberating(形式即自由):明確的架構約束不是束縛,反而是解放——它幫實作者排除無謂的選擇,把精力集中在真正的問題上。
- 設計來自一人或小組,而非委員會:概念完整性需要單一、連貫的心智模型。把架構設計交給大委員會表決,幾乎必然產出妥協而不一致的結果。設計要由一人或緊密小組主導,再廣納回饋。
架構決策的方法#
技術選型的考量#
寶玉提出的技術選型框架:
mindmap
root((技術選型))
📋 業務需求
當前功能需求
預期的規模和增長
性能和可用性要求
合規和安全要求
⚙️ 技術因素
技術成熟度
社區活躍度
與現有技術的整合
學習成本
招聘難度
🏢 組織因素
團隊的技術棧和經驗
維護成本
供應商鎖定風險
長期可持續性決策記錄(ADR)#
架構決策記錄(Architecture Decision Record)的格式:
# ADR-001: 選擇 PostgreSQL 作為主數據庫
## 狀態
已接受
## 背景
需要選擇一個主數據庫來支撐業務系統。
當前預估的數據量:XXX
主要訪問模式:XXX
## 決策
選擇 PostgreSQL 作為主數據庫。
## 理由
- 團隊有 PostgreSQL 經驗
- 支援 JSON 類型,便於處理半結構化數據
- 社區活躍,文件完善
- 開源,無供應商鎖定
## 替代方案
- MySQL:也是可選方案,但團隊經驗較少
- MongoDB:不適合我們的事務需求
## 後果
- 需要培訓部分團隊成員
- 運維需要建立 PostgreSQL 的監控和備份每個重要的架構決策都記錄下來。這樣後人能理解為什麼當時這樣決定,也便於未來重新評估。
高可用設計#
可用性的度量#
喬新亮解釋的可用性標準:
| 可用性 | 年宕機時間 | 月宕機時間 |
|---|---|---|
| 99% (2 個 9) | 3.65 天 | 7.2 小時 |
| 99.9% (3 個 9) | 8.76 小時 | 43.8 分鐘 |
| 99.99% (4 個 9) | 52.56 分鐘 | 4.38 分鐘 |
| 99.999% (5 個 9) | 5.26 分鐘 | 26.3 秒 |
高可用的核心策略#
mindmap
root((高可用))
🔄 冗餘
多實例部署
多機房部署
數據複製
無單點依賴
🛡️ 容錯
故障檢測
自動切換
服務降級
熔斷機制
📊 監控
實時監控
報警機制
快速回應
根因分析異地多活#
畢玄分享了阿里異地多活的經驗:
異地多活是淘寶應對大規模故障的終極方案。
多活的挑戰:
- 數據一致性
- 延遲和同步
- 流量調度
- 成本投入
多活不是簡單的多機房部署,需要從架構層面重新設計。小公司通常不需要,專注做好同城雙活或主備即可。
高性能設計#
性能優化的層次#
喬新亮提出的性能優化框架:
mindmap
root((性能優化))
🏗️ 系統層面
架構優化(緩存、異步、拆分)
數據庫優化(索引、查詢優化、讀寫分離)
緩存策略(多級緩存、緩存更新)
異步處理(消息隊列、批處理)
💻 程式碼層面
算法優化
減少 IO
並發處理
內存管理
🔧 運維層面
硬體升級
負載均衡
CDN 加速
數據庫擴展性能優化的原則#
- 先測量再優化:不要憑感覺優化
- 優化瓶頸:找到真正的性能瓶頸
- 投入產出比:優化是有成本的
- 避免過早優化:先讓它工作,再讓它快
80% 的性能問題來自 20% 的程式碼。找到那 20%,而不是全面優化。
可擴展性設計#
擴展性的維度#
喬新亮總結的擴展性考量:
| 維度 | 說明 | 方法 |
|---|---|---|
| 水平擴展 | 增加機器來提升容量 | 無狀態設計、負載均衡 |
| 垂直擴展 | 升級單機配置 | 硬體升級、優化 |
| 功能擴展 | 增加新功能 | 模塊化、插件化 |
| 組織擴展 | 更多團隊協作 | 服務拆分、清晰邊界 |
為擴展做準備#
設計時考慮:
├── 無狀態:狀態外移到數據庫/緩存
├── 水平分割:數據可以分片
├── 服務邊界:功能可以拆分
└── 介面穩定:減少變更影響
但不要過度設計:
├── 不需要時不拆分
├── 複雜度有成本
├── 適時重構
└── 滿足當前需求優先設計極限情況#
為什麼要考慮極限情況?#
喬新亮強調:
設計系統時,一定要想清楚:極限情況下會發生什麼?
常見的極限情況:
- 流量突增(10 倍、100 倍)
- 依賴服務故障
- 數據庫連接耗盡
- 消息隊列積壓
- 磁盤空間不足
應對策略#
mindmap
root((極限情況應對))
🚦 限流
請求限流
連接限流
資源配額
優先級調度
⬇️ 降級
功能降級
數據降級
服務降級
靜態化
⚡ 熔斷
快速失敗
自動恢復
半開狀態
隔離故障極限情況下的行為應該是可預期的,而不是完全崩潰。設計時就要想好降級方案。
本章要點#
- 架構的本質是取捨:沒有完美方案,只有合適方案
- 概念完整性最重要:分清架構(使用者所見)與實作(如何建),設計由一人/小組主導
- 第二系統最危險:警覺過度設計;區分本質與偶然複雜度
- 沒有銀彈:買非建、快速原型、漸進成長、培育菁英設計者
- 記錄決策:ADR 讓後人理解決策背景
- 高可用三要素:冗餘、容錯、監控
- 性能優化有層次:系統 → 程式碼 → 運維
- 為擴展做準備:但不過度設計
- 考慮極限情況:限流、降級、熔斷