30 天前,這個系列是從一句話開始的:
System Design 的第一步,不是畫架構圖,而是先把問題問清楚。
今天是最後一天,與其再加一個新元件,不如看看我們怎麼從 Day 1 那句話,走到今天這個樣子的。
Day 1 完全沒有畫任何架構圖,只做了一件事:把「設計一個像 Threads 的社群平台」這種模糊需求,拆成 Functional / Non-Functional Requirements,再用 Back-of-the-envelope calculation 把使用者數量換算成 QPS、儲存空間、頻寬。
Day 2 才真正動手,而且刻意做得很陽春:
瀏覽器 -> Server -> Database
一台 Server、一個 Database、Session 直接放在 Memory 裡。
Day 3 補上 Feed 該怎麼組:找出 Follow 對象、撈出 Post、排序、用 Cursor 分頁。
這三天定下了整個系列的敘事節奏:
先讓系統能動,再觀察它在哪裡開始喘不過氣,而不是一開始就把所有元件都塞進架構圖。
Day 4 先處理前後端怎麼溝通(REST vs GraphQL),確認現階段 REST 已經夠用。接著開始正面對決「一台 Server 不夠了」的問題:
這六天的共通劇本幾乎一樣:解決一個瓶頸,下一層馬上冒出新的瓶頸,而每個新元件在解決問題的同時,也帶來自己專屬的新麻煩(Replication Lag、Cache Invalidation、CDN 的 TTL 與 Purge)。
這個 Phase 的核心教訓:不是所有工作都需要使用者等在原地看它做完。
系統元件夠多之後,Application 本身也開始扛不住:
這個 Phase 處理的不是效能瓶頸,而是組織與架構層面的擴展,一旦團隊變大、Service 變多了,就需要新的協作與治理方式。
Day 16 留下一個伏筆:資料分散在 SQL、NoSQL、Cache 之後,「怎麼確保各處看到的資料一致」變得更複雜。Day 17 把這個問題拉高到理論層次,完整拆解 CAP Theorem,並用 Primary Failover 當作具體案例。
CAP 不只是理論,它立刻在接下來四天派上用場:
這五天是整個系列理論密度最高的段落:先有理論框架(CAP),才看得懂後面每一個實際決策在取捨什麼。
LIKE,需要 Inverted Index 這種完全不同的資料結構+1,在高流量下藏著 Write Hotspot,靠批次彙總、分片計數、Redis 累加解決這三天的主題其實是同一句話的不同展開:該用什麼工具解決問題,取決於問題本身的形狀,而不是「反正都塞進主 Database」。
這三天不再是「解決一個新問題」,而是把視角從單一元件拉高:先看懂整個系統現在健不健康(Observability),再看向使用者真正操作的介面(Frontend),最後看向系統散佈在世界各地的樣子(Multi-region)。
把前面七個 Phase 提到的元件全部攤開,拼成 PokeThreads 今天的完整樣貌:
Browser / Mobile App
│
▼
CDN (Day 9)
│
▼
Load Balancer (Day 5)
│
▼
API Gateway (Day 14)
├─ Authentication / Authorization (Day 6, 29)
├─ Rate Limiting (Day 15)
└─ WAF (Day 29)
│
▼ gRPC 內部溝通 (Day 13)
│
├──→ User Service (Day 2, 6, 29)
│ └─→ Distributed Cache(Session,Day 6)+ Sharded SQL Primary/Replica(Day 7, 18)
│
├──→ Post Service (Day 2, 9, 10)
│ └─→ Sharded SQL(Day 7, 18)+ Upload Pipeline → Object Storage(Day 9-10)
│
├──→ Feed Service (Day 3, 20, 21)
│ └─→ Distributed Cache(Fan-out Cache,Day 8, 20)+ Sharded SQL(Day 7, 18)
│
├──→ Follow / Social Graph Service (Day 19)
│ └─→ SQL + Redis + Graph Database(Polyglot Persistence,Day 19)
│
├──→ Notification Service (Day 11, 12, 24)
│ └─→ Message Queue / Pub-Sub(Day 12, 24)→ SSE 即時推播(Day 24)
│
├──→ Search Service (Day 22)
│ └─→ Search Engine / Inverted Index(Day 22)
│
└──→ Counter Service (Day 21, 23)
└─→ Distributed Cache(分片計數器,Day 21, 23)
橫跨所有元件:Observability — Logging / Metrics / Tracing(Day 25)
橫跨所有節點:Multi-region 部署 — Region 化 Replica → Active-active(Day 27)
這個系列刻意埋了幾條貫穿全程的線,走到這裡可以收尾了:
把這 30 天出現過的解法抽象化來看,會發現很多次其實是同一種問題換了個場景重新出現。整理成一張對照表:
| 遇到的問題 | 常見解法 | 對應章節 |
|---|---|---|
| 單一節點會是 Single Point of Failure | 增加 Redundancy(多一份備援 + Failover) | Day 5、7、17 |
| 某個操作會拖住主流程,讓使用者乾等 | 拆成非同步,丟進 Message Queue 背景處理 | Day 11-12 |
| 同樣的資料一直被重複查詢 | 加一層 Cache | Day 8 |
| 單一機器裝不下所有資料、扛不住寫入量 | Sharding,把資料真正切開分散 | Day 18 |
| 查詢方式跟資料形狀不合(搜尋、關係圖) | 換成對應的專用資料庫,而不是硬塞進同一個 DB | Day 16、19、22 |
| 單一 Server 撐不住流量 | Horizontal Scaling + Load Balancer | Day 5 |
| Service 之間耦合太緊,牽一髮動全身 | 拆成獨立服務,用明確的介面溝通 | Day 13-14 |
| 流量或 API 被濫用 | Rate Limiting | Day 15 |
| 多節點資料不同步 | 依資料的重要程度選一致性等級,而不是要求全部強一致 | Day 17 |
| 少數 Key/帳號特別熱門,局部過載 | 針對熱點特殊處理(分拆計數器、額外快取),而不是整體擴容 | Day 21、23 |
| 系統出狀況卻不知道從何查起 | Logging + Metrics + Tracing | Day 25 |
這個也不是一本「查表就能解題」的手冊,同一個問題在不同規模、不同限制條件下,答案可能完全不一樣(這也是這系列從頭到尾的主題)。
它更像是一份問題的分類法,先認出眼前麻煩屬於哪一類,才知道該往哪個方向想解法,而不用每次都從零開始摸索。
Day 1 就講過、之後都在印證的同一句話:
System Design 沒有唯一正確答案,只有在目前限制條件下最合理的取捨。
Vertical Scaling 不是錯的,只是撐不了太久;Stateful Server 不是笨方法,只是換到多台 Server 就不管用;SQL 不是過時的技術,但不是每一種資料都適合塞進同一張表。
這系列裡新增的每一個元件,都不是因為「大公司都這樣做」,而是因為前一天的架構,剛好在某個具體場景下撐不住了。
到這裡很容易有個錯覺,以為系統設計出一套「夠完整」的架構之後,接下來就是照著擴充就好。實際上相反,每次解決一個瓶頸,比較像是把某個沒處理的問題往後延,而不是把它徹底消滅。
我們的 PokeThreads 走到今天,還有一長串問題完全沒被碰過,列出來給大家自己接著往下研究:
不是這些不重要,而是每一個都大到可以自己獨立寫一個系列,像是 Saga Pattern、Circuit Breaker、Push Notification Infra,隨便一個都能再多寫好幾篇,更不用說我自己查資料看資料也頭昏眼花了。
這系列從頭到尾想討論的是「看到瓶頸、判斷取捨」的思考方式,而不是窮舉一份「大型系統該有哪些元件」的清單,這種清單就算真的寫得出來,過幾年也會因為新技術出現而過時。
留白比塞好塞滿更實在:一個系統設計系列如果宣稱自己已經涵蓋所有面向,多半代表寫的人低估了真實系統的複雜度。
System Design 沒有一個「做完了」的終點,只有「現在夠用了,之後再說」。
PokeThreads 是虛構的練習案例,如果想看業界怎麼討論「設計一個類似 Twitter/Threads 的社群平台」這種經典題目,這兩篇很適合接著讀:
這兩篇跟這系列的側重點不太一樣:它們比較像是「一次性設計出完整方案」的教學,這系列則是刻意把時間拉長成 30 天,強調「每個元件是在哪個瓶頸下才被加進來的」。兩種角度合著看,會更清楚 System Design 沒有單一標準流程,只是每個人切入的順序不同。
從 Day 2 那個「瀏覽器 -> Server -> Database」的陽春架構,到今天涵蓋 Load Balancer、Stateless Server、Sharded Database、Cache、CDN、Message Queue、Microservices、Search、Counter System、多區域部署、資安防護的系統(即使上一段列的那一長串問題都還沒填),中間沒有任何一步是憑空跳過去的,每一個已經做出來的元件,都能回答「為什麼是現在、為什麼是這個」。
這大概就是 System Design 這件事最值得練習的地方:它不是背下一份「大型系統該有哪些元件」的清單,而是練習在每一個當下,看清楚現在真正的瓶頸是什麼,再決定該加什麼、該用什麼取捨去解決它。
非常歡迎留下你的感想,也歡迎到我的個人網站看其他內容。
感謝一路和我研究如何壯大一個社群網站,我的系列文章也剛好在連假的最後一天完結,雖然可能晚了,但仍祝福你有個愉快的假期(下一週還有雙十連假呢)。