system-design

system-design

熱門

使用結構化方法設計可擴展的分散式系統,涵蓋負載平衡、快取、資料庫擴展和訊息佇列。當使用者提到「系統設計」、「擴展這個」、「高可用性」、「速率限制器」、「設計 URL 縮短器」、「設計 Twitter」、「設計 Uber」、「設計新聞動態」、「系統設計面試」、「容量規劃」或「分散式架構」時使用。也適用於估算基礎設施需求、選擇微服務或單體架構,或為數百萬並發用戶設計系統。涵蓋常見系統設計(TinyURL、動態消息、聊天)和粗略估算。關於資料基礎知識,請參閱 ddia-systems。關於韌性,請參閱 release-it。

1706星標
171分支
更新於 2026/7/22
SKILL.md
唯讀
名稱
system-design
描述

使用結構化方法設計可擴展的分散式系統,涵蓋負載平衡、快取、資料庫擴展和訊息佇列。當使用者提到「系統設計」、「擴展這個」、「高可用性」、「速率限制器」、「設計 URL 縮短器」、「設計 Twitter」、「設計 Uber」、「設計新聞動態」、「系統設計面試」、「容量規劃」或「分散式架構」時使用。也適用於估算基礎設施需求、選擇微服務或單體架構,或為數百萬並發用戶設計系統。涵蓋常見系統設計(TinyURL、動態消息、聊天)和粗略估算。關於資料基礎知識,請參閱 ddia-systems。關於韌性,請參閱 release-it。

系統設計框架

一種結構化方法,用於設計大規模分散式系統。在架構新服務、審查設計、估算容量或準備系統設計討論時,應用這些原則。

核心原則

從需求開始,而不是解決方案。 在了解限制條件之前就跳到架構,會產生過度設計或設計不足的系統。可擴展的系統是由熟悉的建構區塊(負載平衡器、快取、佇列、資料庫、CDN)組合而成——技巧在於選擇正確的區塊、透過估算來調整大小,並承擔每個選擇帶來的取捨。

評分

目標:10/10。 根據設計滿足多少個快速診斷列來評分——score = round(passed / 8 × 10):9-10 = 全部或幾乎全部列通過——明確的需求、實際的估算、冗餘、明確的資料庫擴展和快取策略、透過佇列的非同步處理、監控、部署計畫,並指出取捨;5-6 = 設計可行但跳過估算、冗餘或運維;<=3 = 在需求或估算之前就提出架構。始終說明當前分數、指出未通過的診斷列,並給出每個問題的具體修正。

系統設計框架

建構可靠、可擴展分散式系統的六個領域:

1. 四步驟流程

核心概念: 每個設計都遵循四個階段:(1) 理解問題並確定範圍,(2) 提出高層級設計並獲得認可,(3) 深入關鍵元件,(4) 總結取捨和未來改進。

為什麼有效: 沒有結構,設計要麼停留在過於抽象,要麼迷失在過早的細節中。四個步驟按比例投入時間——先宏觀輪廓,再深入關鍵處。

關鍵見解:

  • 步驟 1(約 5-10 分鐘):釐清問題、功能和非功能需求、商定規模(DAU、QPS、儲存)
  • 步驟 2(約 15-20 分鐘):高層級圖表,包含 API、服務、資料儲存、資料流箭頭
  • 步驟 3(約 15-20 分鐘):詳細設計 2-3 個最困難或最關鍵的元件
  • 步驟 4(約 5 分鐘):取捨、瓶頸、未來改進
  • 絕不跳過步驟 1——模糊的範圍會浪費所有後續工作;明確取得假設的共識

程式碼應用:

情境 模式 範例
新服務啟動 在編碼前撰寫涵蓋所有四個步驟的一頁設計文件 需求、API 合約、資料模型、容量估算,然後實作
架構審查 依序引導審查者通過步驟 範圍、圖表、深入風險最高的元件、開放問題
事件事後檢討 透過四個步驟的視角追蹤失敗 哪個需求被忽略?哪個區塊失敗?哪個取捨導致問題?

請參閱 references/four-step-process.md 以進行端到端設計——每個階段的時間分配、範例釐清問題,以及四個步驟的提示。

2. 粗略估算

核心概念: 使用二的冪次、延遲數字和簡單算術,在確定架構之前估算 QPS、儲存、頻寬和伺服器數量。

為什麼有效: 估算可防止過度配置(浪費金錢)和配置不足(負載下停機)。2 分鐘的計算可以節省數週的重工。

關鍵見解:

  • 二的冪次:2^10 ≈ 1 千,2^20 ≈ 1 百萬,2^30 ≈ 10 億,2^40 ≈ 1 兆
  • 延遲:記憶體讀取 ~100 ns,SSD 讀取 ~100 us,磁碟搜尋 ~10 ms,同資料中心往返 ~0.5 ms,跨洲 ~150 ms
  • 可用性九個九:99.9% = 每年 8.77 小時停機;99.99% = 每年 52.6 分鐘
  • QPS:DAU x 每日動作數 / 86,400 秒;尖峰通常是平均的 2-5 倍
  • 儲存:每日記錄數 x 記錄大小 x 保留期限
  • 大膽取整——目標是數量級,而非精確度

程式碼應用:

情境 模式 範例
容量規劃 估算 QPS,乘以成長因子 1 億 DAU x 5 動作 / 86400 = 約 5,800 QPS 平均,約 30K 尖峰
儲存預算 每筆記錄大小 x 數量 x 保留期限 5 億推文/天 x 300 位元組 x 365 天 = 約 55 TB/年
SLA 定義 將九個九轉換為允許停機時間 四個九 = 每年約 52 分鐘停機

請參閱 references/estimation-numbers.md 以調整系統規模——完整的延遲表、可用性九個九表,以及 QPS/儲存/頻寬計算範例。

3. 建構區塊

核心概念: 可擴展系統由標準工具組裝而成:DNS、CDN、負載平衡器、反向代理、應用伺服器、快取、訊息佇列和一致性雜湊。

為什麼有效: 每個區塊以一種成本換取另一種(快取以新鮮度換取讀取速度;佇列以延遲換取解耦),因此只在出現特定瓶頸時引入區塊——一開始就全部加入只會增加故障模式。

關鍵見解:

  • 負載平衡器:L4(傳輸層——快速、簡單)vs L7(應用層——內容感知路由)
  • 快取層:客戶端、CDN、網頁伺服器、應用程式(Redis/Memcached)、資料庫查詢快取
  • 快取策略:cache-aside(應用管理)、read-through、write-through(同步)、write-behind(非同步)
  • 訊息佇列(Kafka、RabbitMQ、SQS):解耦生產者和消費者、吸收尖峰、啟用非同步處理
  • 一致性雜湊:在節點變化時以最小重新分配方式將鍵分佈到節點

程式碼應用:

情境 模式 範例
讀取密集型工作負載 在資料庫前使用 cache-aside Redis 快取使用者設定檔並設定 TTL;寫入時失效
流量尖峰 API 和工作器之間的訊息佇列 將圖片調整大小任務排入佇列;工作器以自己的節奏拉取
全球用戶 靜態資源的 CDN 從邊緣提供 JS/CSS/圖片;來源僅提供 API
不均勻負載 分片分配的一致性雜湊 新增節點僅移動約 1/n 的鍵

請參閱 references/building-blocks.md 以選擇元件——DNS、CDN、負載平衡器、快取策略、訊息佇列和一致性雜湊的運作方式及何時引入。

4. 資料庫設計與擴展

核心概念: 根據資料形狀和存取模式選擇 SQL 或 NoSQL;先垂直擴展,當垂直限制達到時再水平擴展(複寫和分片)。

為什麼有效: 資料庫通常是第一個瓶頸。理解複寫、分片和反正規化的取捨,可以延緩昂貴的重新架構,並使成長更有計畫。

關鍵見解:

  • 垂直擴展較簡單但有上限;水平擴展較困難但幾乎無限
  • 複寫:主從(一個寫入器,多個讀取器)適用於讀取密集型;多主適用於多區域寫入
  • 分片:基於雜湊(均勻分佈,範圍查詢困難)、基於範圍(範圍容易,熱點風險)、基於目錄(靈活,額外查詢)
  • SQL 適用於 ACID 交易、聯結、定義的結構;NoSQL 適用於靈活結構、水平擴展、極高寫入吞吐量
  • 反正規化以儲存和寫入複雜度換取讀取速度——當讀取主導且資料變化不頻繁時使用
  • 名人/熱點問題:一個熱門分片需要次要分割或快取層

程式碼應用:

情境 模式 範例
讀取密集型 API 主從架構搭配讀取副本 讀取到副本,寫入到主節點;接受些微延遲
大規模使用者資料 基於 user_id 的雜湊分片 hash(user_id) % num_shards;均勻、獨立的分片
分析儀表板 反正規化的具體化視圖 夜間預先聯結和彙總;從具體化表格提供服務

請參閱 references/database-scaling.md 以處理資料庫瓶頸——複寫拓撲、三種分片策略比較、反正規化取捨,以及 SQL 與 NoSQL 選擇指南。

5. 常見系統設計

核心概念: 大多數系統是少數已知設計的變體:URL 縮短器、速率限制器、通知系統、新聞動態、聊天、搜尋自動完成、網頁爬蟲、唯一 ID 產生器。

為什麼有效: 一個已知設計的心智庫,讓你能辨識新問題類似哪種模式並加以調整,而不是從頭發明。

關鍵見解:

  • URL 縮短器:base62 編碼、鍵值儲存、301 vs 302 重新導向取捨(快取 vs 分析)
  • 速率限制器:在閘道使用 token bucket 或 sliding window;回傳 429 並附上 Retry-After
  • 新聞動態:寫入時扇出(發文時推送)vs 讀取時扇出(閱讀時拉取);名人使用混合模式
  • 聊天:WebSocket 用於即時雙向訊息、佇列用於傳遞保證、心跳存在服務
  • 自動完成:前 k 個熱門查詢的 Trie;預先計算並快取熱門前綴
  • 網頁爬蟲:BFS 搭配 URL frontier、禮貌性(robots.txt、每個網域速率限制)、透過內容雜湊去重
  • 唯一 ID:UUID(簡單、無需協調)vs Snowflake(64 位元、可依時間排序、感知資料中心)

程式碼應用:

情境 模式 範例
短連結服務 Base62 編碼自動增量 ID 或雜湊 https://short.ly/a1B2c3 對應到一個鍵值行
API 保護 閘道的 token bucket 每個金鑰每分鐘 100 個 token;穩定補充;拒絕時回傳 429
社交動態 混合扇出 為粉絲數 <10K 的帳號預先計算動態;閱讀時合併名人貼文

請參閱 references/common-designs.md 以處理類似已知設計的問題——URL 縮短器、速率限制器、新聞動態、聊天、自動完成、網頁爬蟲和唯一 ID 產生器的完整逐步解說。

6. 可靠性和運維

核心概念: 系統的好壞取決於其維持運作、復原和可觀察的能力。健康檢查、監控、日誌記錄和部署策略是首要的設計考量,而非事後才想到。

為什麼有效: 生產系統會以圖表從未預測的方式失敗。運維就緒——指標、警報、回滾計畫、冗餘——決定了故障是短暫問題還是停機事件。

關鍵見解:

  • 健康檢查:存活(程序是否活著?)和就緒(能否處理流量?)——Kubernetes 兩者都使用
  • 可觀察性的三大支柱:指標(Prometheus、Datadog)、日誌(ELK、CloudWatch)、追蹤(Jaeger、Zipkin)
  • 部署:滾動(逐步)、藍綠(在相同環境間即時切換)、金絲雀(先小比例)
  • 災難復原:RPO(可接受的資料遺失)和 RTO(可接受的復原時間)驅動備份和容錯移轉策略
  • 多資料中心:主動-被動(容錯移轉)或主動-主動(需要資料同步和衝突解決)
  • 自動擴展:根據 CPU、記憶體、佇列深度或自訂指標擴展;始終設定最小和最大數量

程式碼應用:

情境 模式 範例
零停機部署 藍綠部署搭配健康檢查閘道 檢查通過後切換到綠色;保留藍色作為即時回滾
逐步推出 金絲雀部署搭配指標比較 5% 流量到新版本;比較錯誤和延遲;推廣或回滾
資料安全 定義 RPO/RTO 並據以實作 RPO 1 小時 = 每小時備份;RTO 5 分鐘 = 自動容錯移轉

請參閱 references/reliability-operations.md 以強化生產環境——健康檢查模式、可觀察性支柱、部署策略、災難復原(RPO/RTO)和自動擴展。

常見錯誤

錯誤 為什麼失敗 修正
在需求之前先有架構 解決錯誤的問題,忽略限制條件 花前 5-10 分鐘確定範圍:功能、規模、SLA
沒有估算 配置數量級錯誤 在選擇元件前估算 QPS、儲存、頻寬
單點故障 一個元件拖垮整個系統 每一層都冗餘:多伺服器、多可用區、多區域
過早分片 在需要之前就引入巨大的運維複雜度 先垂直擴展、讀取副本、積極快取、最後分片
快取沒有失效策略 過時資料導致錯誤和混亂 定義 TTL;cache-aside 搭配寫入時明確失效
到處都是同步呼叫 一個慢服務將延遲串聯到所有呼叫者 非延遲關鍵路徑使用佇列;同步呼叫設定逾時
忽略熱點 一個分片或鍵被大量使用,其他閒置 偵測熱鍵;加入次要分割或本地快取
沒有監控或警報 使用者比你更早發現故障 從第一天起就收集指標、日誌和追蹤

快速診斷

問題 如果否 行動
是否列出功能和非功能需求? 設計基於假設 寫下功能、DAU、QPS、儲存、延遲和可用性 SLA
是否有 QPS 和儲存估算? 容量是猜測 DAU x 動作 / 86400 計算 QPS;記錄 x 大小 x 保留期限計算儲存
每個元件是否都有冗餘? 單點故障 為每個元件加入副本、容錯移轉或多可用區
是否定義了資料庫擴展策略? 成長時會撞牆 先垂直擴展,然後讀取副本,最後用明確的分片鍵進行分片
讀取密集型路徑是否有快取? 資料庫承受不必要的負載 Redis/Memcached cache-aside 搭配定義的 TTL
非同步路徑是否使用佇列? 緊耦合、串聯故障 使用 Kafka/SQS 解耦任務、通知、分析
是否有監控和警報計畫? 對生產故障一無所知 定義指標、日誌彙總、追蹤、警報閾值
是否定義了部署策略? 一次性發布風險高 滾動、藍綠或金絲雀部署,搭配自動回滾

延伸閱讀

如需包含詳細圖表和逐步解說的完整指南:

關於作者

Alex Xu 是一位軟體工程師,曾服務於 Twitter、Apple 和 Oracle,也是 ByteByteGo 的創辦人。他的兩冊《System Design Interview》系列銷量超過 50 萬本,透過結構化思考、估算和清晰溝通,將系統設計轉變為可學習、可重複的技能。