系統設計工作室 是做什麼的?
當使用者要求設計、解釋或學習一個系統的高階設計(HLD)時使用:例如「設計 Uber」、「Netflix 的系統設計」、「支付閘道的 HLD」、「設計 URL 縮短器」、「為設計 X 做面試準備」。產出物是一個自包含、可導航的 HTML 設計文件,以 artifact 形式發布,支援淺色和深色模式,並可選擇性地包含一個互動式圖表伴侶。當使用者希望取得可在本地執行的檔案時,則將指南和圖表以一個包含頁籤(§9)的 HTML 頁面形式交付。
此儲存庫中的參考範例展示了品質標準:examples/stock-broker/(預設主題,指南和圖表為獨立頁面)和 examples/uber/(產品主題,手繪架構 SVG,指南和圖表在同一個檔案中)。
1. 決定主題與風格
首先對請求進行分類。這決定了內容的角度和視覺呈現。
- 已命名的產品或公司(Uber、Netflix、WhatsApp、Swiggy、Zerodha、Airbnb、Spotify、Stripe、Instagram 等):指南標題為「<公司> 的系統設計」,並以該產品領域為主題(請參閱 §5.2)。全文使用該公司自身的領域詞彙(Uber:乘客、司機、行程、派單、尖峰加價、預計到達時間;Netflix:節目、播放、CDN、編碼階梯;WhatsApp:聊天、送達回條、最後上線時間)。
- 通用系統(URL 縮短器、聊天應用程式、支付閘道、速率限制器、通知服務、「一個共享乘車應用程式」且未提及公司名稱)或無法歸類的冷門產品:使用預設模板主題(§5.1)。
- 使用者指定了風格(例如「讓它看起來像 Stripe 的文件」、「樸素簡約」):優先遵循此要求。
對於已命名的公司,請在設計前進行研究:搜尋其公開的工程部落格文章和演講(例如 Uber:H3 地理空間索引、Ringpop、Schemaless、Cadence;Netflix:Open Connect、EVCache、Zuul)。使用公開資訊,並標記其來源(例如「根據 Uber Engineering 部落格」),在指南頁尾列出來源,並將其他所有內容標記為假設。切勿將推斷的設計呈現為該公司實際的內部架構。
2. 在開始構建前進行腦力激盪
在撰寫任何 HTML 之前,先釐清(並在一條簡短訊息中向使用者說明):
- 領域的主導洞察:一個若被忽略會使整個設計失敗的邊界條件或核心概念。例如:「經紀商負責路由,交易所負責撮合」;「支付閘道從不持有資金,收單機構才持有」;「Uber 的派單是在秒級延遲預算下的地理空間匹配問題」。將其作為重點提示放在概述中。
- 路徑劃分:哪些路徑需要強一致性(金錢、訂單、庫存、預訂 → CP)以及哪些傾向於可用性(動態消息、搜尋、在線狀態、位置 ping、分析 → AP)。在邊界處將它們分離。
- 難點問題:冪等性、排序、扇出、熱點鍵、地理分區、對帳、恰好一次處理的聲明。
- 範圍內 / 範圍外(哪些被視為外部整合)。
- §1 中的主題決定:使用哪個產品主題,或使用預設主題。
如果請求確實模棱兩可(是哪個產品?面試深度還是生產環境深度?),提出一個問題釐清;否則直接開始。
3. 必備章節(按此順序編號)
- 概述:系統是什麼、主導洞察的重點提示、範圍內 / 範圍外列表。
- 需求:功能需求表(領域 → 能力,使用該領域的真實詞彙和列舉值)和非功能需求表(屬性 → 目標 → 備註)。務必包含延遲、可用性、一致性(按路徑區分 CP/AP)、持久性、可擴展性、安全性、冪等性。
- 容量估算:假設 → 推導數值的表格(使用者數、DAU、峰值並發數、平均和峰值寫入/秒、讀取/秒、扇出出口流量、儲存/天)。展示計算過程以便驗證;最後用一個重點提示說明每個路徑的擴展軸向。對於真實公司,應以公開報導的規模為基準並引用之。
- 架構:一個渲染後的圖表(見 §6)以及針對每個路徑和事件骨幹的說明文字。
- 元件深入探討:針對每個核心服務:職責、運作機制(狀態機、協定、演算法)、持有的資料、故障處理。
- 核心流程生命週期:產品的旗艦端到端流程(Uber:請求乘車 → 配對 → 行程;Netflix:按下播放 → 串流;WhatsApp:發送訊息 → 已送達 → 已讀),以步驟表呈現(#、步驟、負責方、狀態/事件),並加上同步/非同步邊界提示。
- 資料模型與資料表結構:ER/類別圖(見 §6),然後是非關聯式儲存(快取鍵模式、時間序列佈局、地理索引、搜尋索引),最後是事件主題(主題、分割鍵、事件)並附上一個範例事件 JSON。請不要將原始 SQL DDL 作為主要的資料表結構視圖。
- API 設計:慣例表(認證、冪等性、錯誤封裝、速率限制、分頁、版本控制)、帶有彩色方法標籤的端點表、關鍵寫入操作的一個完整請求和回應範例(展示狀態碼語義,例如 202 表示非同步)、狀態碼表,以及串流協定(WebSocket/SSE/gRPC 串流)(如果有的話)。
- 一致性與可靠性:每項保證適用的位置、Saga 模式 + 補償機制、冪等性層、故障場景表。
- 擴展性與效能:分片鍵、無狀態自動擴展、分區、快取、流量高峰處理。
- 安全性與合規性:認證/授權、資料保護、法規資料保留、濫用防護。
- 可觀測性:黃金指標、追蹤、對帳儀表板、警報。
- 權衡取捨:決策 → 選擇與原因表,並以「請記住這五點」的重點提示作為結尾。
4. 準確性標準(發布前檢查)
- 容量中的每個數字都源自於陳述的假設,並且內部一致(已說明平均值與峰值的倍數關係)。
- 架構圖中的每個元件都出現在深入探討或流程中,反之亦然。
- ER 圖中的每個實體都被某個流程或 API 使用;每個 API 的寫入路徑都涉及一個真實的實體。
- 資料表結構章節中的 Kafka/佇列主題與架構圖中的邊緣標籤相符。
- 金錢被建模為複式記帳分類帳(如果有金錢相關);冪等性鍵同時出現在資料表結構(唯一約束)和 API(標頭)中。
- 使用該領域的真實術語(訂單類型、如 FIX/ISO 8583 等協定、法規),並在必要時說明這是假設。
- 對於已命名的公司:每個關於其實際技術棧的聲明都應有來源;其他所有內容都標記為假定。
- 切勿聲稱能夠實現真正的恰好一次處理;應描述冪等性加上對帳機制。
5. 主題、淺色模式與深色模式
每個指南都附帶淺色和深色模式:預設遵循讀者的系統設定,並在標題中提供一個切換按鈕(會保存在瀏覽器中)。在撰寫頁面之前,請先載入 artifact-design 技能。
5.0 Token 系統(兩種模式)
所有顏色都使用 CSS 自訂屬性。切勿在規則、SVG 或圖示中硬編碼顏色;請始終使用 token。在 :root 上定義淺色值,然後定義深色值兩次(一次是系統偏好,除非讀者選擇了淺色;另一次是明確的深色選擇):
:root{ color-scheme:light; /* light tokens */ }
@media (prefers-color-scheme: dark){
:root:not([data-theme="light"]){ color-scheme:dark; /* dark tokens */ }
}
:root[data-theme="dark"]{ color-scheme:dark; /* dark tokens, repeated */ }
body{ background:var(--bg); color:var(--ink); }
必備 token 角色(每個主題都需設定所有角色,涵蓋兩種模式)。使用純十六進位值(不要用 rgba(...)),因為圖表渲染器會以逗號分割:
| Token | 角色 |
|---|---|
--bg, --surface, --surface-2, --line, --line-soft | 頁面、卡片、凸起卡片、邊框 |
--ink, --ink-mid, --ink-dim | 標題/強調文字、正文、說明文字 |
--accent, --accent-ink | 主題的代表色,以及繪製在其上的文字 |
--svc, --svc-bg | 圖表中的服務 |
--bus, --bus-bg | 佇列/事件匯流排 |
--ext, --ext-bg | 外部系統 |
--store, --store-bg | 資料儲存 |
--ok, --warn, --danger, --info | 提示框、方法標籤、CP/AP 標籤 |
--code-bg, --code-ink, --code-key, --code-str, --code-num, --code-com | 程式碼區塊 |
--font-display, --font-body, --font-mono | 字型家族 |
對比度:在兩種模式下,正文文字(--bg 和 --surface 上的 --ink-mid)至少需達到 4.5:1;--surface 上的強調文字至少需達到 4.5:1。在深色模式下效果良好的亮色強調色,通常需要在淺色模式下使用較暗的色調,因此請分別為每種模式選取值,而不是重複使用。
將其放在 <head> 中的樣式表之前,以便保存的選擇能在無閃爍的情況下應用:
<script>
(function(){var t=null;try{t=localStorage.getItem('sdg-theme')}catch(e){}
if(t==='light'||t==='dark')document.documentElement.dataset.theme=t;})();
</script>
標題中的切換按鈕(<button class="theme-toggle" id="themeToggle" aria-label="切換顏色主題"></button>)以及接近 <body> 結尾處的腳本:
<script>
(function(){
var root=document.documentElement, mq=matchMedia('(prefers-color-scheme: dark)');
function current(){return root.dataset.theme||(mq.matches?'dark':'light');}
function label(){var b=document.getElementById('themeToggle');if(b)b.textContent=current()==='dark'?'☀ 淺色':'☾ 深色';}
document.getElementById('themeToggle').addEventListener('click',function(){
var next=current()==='dark'?'light':'dark';root.dataset.theme=next;
try{localStorage.setItem('sdg-theme',next)}catch(e){}
label();document.dispatchEvent(new Event('themechange'));});
mq.addEventListener('change',function(){if(!root.dataset.theme){label();document.dispatchEvent(new Event('themechange'));}});
label();
})();
</script>
5.1 預設模板主題(通用系統)
適用於任何未與特定產品相關的通用系統:
- 字型:Space Grotesk(顯示用)、Inter(正文)、JetBrains Mono(識別碼、列舉值、主題、路徑)。
- 深色:午夜基底。
--bg #0a0e17,--surface #141b2c,--surface-2 #1a2336,--line #28324e,--ink #eaf0fb,--ink-mid #aab6d2,--ink-dim #7a86a4,--accent #5ec7df,--svc #4fd0e0/--svc-bg #152036,--bus #f3ab54/--bus-bg #241d12,--ext #fb7f95/--ext-bg #2a1622,--store #93a3c0/--store-bg #131b2c。 - 淺色:冷色調紙張。
--bg #f6f8fc,--surface #ffffff,--surface-2 #eef2f8,--line #d6deea,--ink #0f1729,--ink-mid #45536b,--ink-dim #5f6c85,--accent #0b7287,--svc #0b7287/--svc-bg #e3f3f7,--bus #a35a00/--bus-bg #fdf0dd,--ext #b4234a/--ext-bg #fde7ec,--store #55627a/--store-bg #eef1f6。 - 佈局:英雄區(眉毛標題、主標題、包含主導洞察的一段摘要、4 張 TL;DR 卡片:峰值規模、連接方式、CP 路徑、AP 路徑),然後是兩欄式主體,在桌機上具有固定的目錄和滾動監聽功能,在行動裝置上則有浮動的「☰ 目錄」抽屜。
5.2 產品主題(已命名的公司)
頁面應讓人感覺屬於該產品的世界,同時又清楚表明這是一份獨立的研究。根據產品公開的視覺特徵,推導出完整的 token 組(兩種模式):它的色調、字型風格、形狀語言(銳利 vs 圓潤)、密度,以及一個標誌性元素。起點參考(近似即可,意在引發聯想而非複製):
| 產品 | 色調方向 | 字型(免費替代方案) | 形狀與元素 |
|---|---|---|---|
| Uber | 單色黑/白,一個綠色強調色 | Inter Tight,粗體顯示字重 | 銳利邊角,高對比度;地圖路線和上/下車點 |
| Netflix | 接近黑色搭配深紅色強調色;淺色模式暖白 + 紅色 | Bebas Neue 顯示用,Inter 正文 | 電影感大標題,海報卡行 |
| 柔和中性色上的青綠色;深色模式深綠灰色 | Inter / 系統 UI | 對話氣泡提示,雙勾號狀態標記 | |
| Airbnb | 暖白搭配珊瑚色強調色 | Nunito Sans | 大量圓角,柔和陰影,友好間距 |
| Spotify | 黑色搭配亮綠色;淺色模式白色 + 綠色 | Figtree 或 DM Sans | 藥丸按鈕,波形/進度條元素 |
| Stripe | 淺色優先,靛藍/紫色強調色,柔和漸層 | Inter | 清晰細線,程式碼區塊作為一級元素 |
| Swiggy / Zomato | 奶油色上的暖橙色或紅色;深色深棕黑色 | Poppins | 圓角卡片,訂單追蹤時間軸 |
| Zerodha | 乾淨白色搭配藍色強調色;深色石板色 | Inter | 密集數據表,滾動報價條 |
對於表中未列出的公司,應用相同的方法:識別其標誌性顏色、風格和元素,然後為兩種模式構建。
產品主題的護欄:
- 靈感來源,絕不複製。 不使用 Logo、文字標記、應用圖示、吉祥物、螢幕截圖或複製的 UI 畫面,也不使用專有字型(Uber Move、Netflix Sans、Circular、Cereal):使用免費替代方案。元素以通用方式繪製(一條路線、一個對話氣泡),而非從產品中提取。
- 標題為研究性質:「Uber 的系統設計」或「設計一個 Uber 規模的共享乘車平台」,切勿讓人誤以為是 Uber 發布的。
- 頁尾總是包含:「獨立教育研究。與 <公司> 無關,亦未獲其背書。架構根據公開來源和所述假設重建。」以及來源列表。
- 圖表、表格、提示框和標籤仍使用與預設模板相同的元件結構,並透過 token 重新著色。產品主題改變的是視覺效果,而非 13 個章節的結構。
5.3 共享元件
- 表格置於圓角滾動包裝器中;提示框(關鍵 / 警告 / 資訊 / 注意事項)帶有彩色左邊框;方法標籤(GET
--ok, POST--info, PUT--warn, DELETE--danger);CP/AP 標籤。 - 程式碼區塊僅用於 JSON 承載、鍵模式和協定訊息,帶有標題欄標明語言或端點,並使用
--code-*token 設定語法顏色。 - 手機寬度...