【從一台 Server 到分散式架構】系列序:為什麼我要寫系統設計?

前言

如果你是一個前端工程師,或是略懂一點後端皮毛、會做前後端分離的架構——一個前端、一個後端、一個資料庫,這樣就能做出一個能跑的網站。對很多 side project、內部工具、小流量產品來說,這樣其實就夠了。

但隨著產品長大、流量上來,可能會越來越常遇到「摸不著頭緒」的狀況:

  • 要怎麼評估一個系統需要擴充?應該選擇垂直擴充還是水平擴充
  • 水平擴充之後,為什麼會冒出 Session 亂掉、登入狀態不一致這些問題?
  • 別人提到的 Redis、Kafka、Zookeeper、K8s……什麼時候才該用到這些東西?
  • CAP 理論、強一致、最終一致,在實務上到底怎麼取捨?
  • 資料庫變慢的時候,除了加索引還能做什麼?什麼情境該做讀寫分離、什麼情境才需要 Sharding?
  • 大量用戶一瞬間湧入(例如限時特價、搶票),系統該怎麼設計才不會直接掛掉?
  • 監控、Log、分散式追蹤……出問題的時候要怎麼回溯現場?

這些問題,在「一前一後一 DB」的世界裡不會出現。但一旦產品開始長大、流量上來、團隊變多,它們就會一個一個冒出來。而老實說,在學校、在自學、在大多數的前端養成裡,我們很少被系統性地帶過「一棟建築是怎麼從小平房長成摩天大樓的」——我們會寫房間裡的裝潢(功能),但不太清楚整棟樓的結構是怎麼一步步演進的。

這個系列會用循序漸進、從無到有的思路,搭配生活化的比喻,把這條路走一遍,也把過程留下來,給同樣背景的讀者一張可以依序讀、依序補的地圖。


為什麼系統設計重要?

在動手寫這個系列之前,我反覆問自己:系統設計,到底為什麼值得花時間學?

想了一想,大概有這幾個理由。

第一,它直接影響產品能不能活下去。
一個功能做對、UI 做美,但一上線就 504、一促銷就掛站,用戶只會記得「這個網站很爛」。系統能不能撐住流量、能不能在故障時優雅降級、資料會不會丟失或錯亂,往往決定了產品是「長大」還是「暴斃」。這不是只有後端工程師的事,而是整個團隊、甚至創業者都要有的基本概念。

第二,它決定了我們怎麼做技術選型與取捨。
什麼時候加快取、什麼時候上 Message Queue、什麼時候拆微服務、什麼時候考慮 Sharding,背後都是一連串的取捨:成本、複雜度、一致性、可用性。沒有宏觀的系統思維,很容易要嘛過早優化(堆了一堆用不到的架構),要嘛火燒屁股才在補(架構債一次爆開)。先有「什麼階段會遇到什麼問題」的圖景,才不會瞎忙。

第三,它是職涯與面試的共通語言。
不管是轉後端、走全端、還是面 System Design 考題,面試官想看的都是:你能不能從需求推導出架構、能不能在限制下做取捨、能不能說清楚「為什麼這樣設計」。這些能力,都建立在對系統演進的整體理解上。把「一台 Server 怎麼長成分散式架構」想清楚,等於把一整張地圖攤開,以後不管考題是設計 YouTube、Uber 還是 ChatGPT,你都知道該從哪幾個維度去拆。

第四,它幫助我們和團隊、和利害關係人溝通。
當 PM 說「我們要做限時特價」、當老闆問「我們系統能撐多少人」、當維運問「為什麼這次故障查這麼久」,如果你心裡有一張系統演進的圖,就能用大家聽得懂的方式解釋:瓶頸可能在哪、我們已經做了什麼、接下來要補哪一塊。系統設計不是只有寫 code 的人需要,而是所有參與產品成敗的人,都值得有一個宏觀的認識。

所以,系統設計重要,不是因為「大公司都在考」,而是因為它關乎產品能不能長大、技術決策會不會做對、職涯能不能往上走、團隊能不能對齊。這是我寫這個系列的起心動念。


這個系列會討論哪些議題?

這個系列會用一條主線故事來串:小明跟朋友創業做一個線上課程平台,從 MVP 的一前一後一 DB,一路長到需要負載平衡、快取、讀寫分離、Message Queue、微服務、限流降級、監控追蹤……主線走完之後,在延伸篇會試著用同一套思維對照 YouTube、Uber、Twitter、ChatGPT 這類產品——不是要還原它們的真實架構(那遠比我們講的複雜),而是看這些概念能怎麼用來理解、拆解不同情境的設計取捨。

沿著這條線,會涵蓋的議題包括(先給一個宏觀清單,之後每篇細講):

維度會討論的議題
起點與瓶頸單體架構、請求流程、負載與瓶頸(CPU / DB / 延遲)、垂直 vs 水平擴充、Nginx/負載平衡
資料庫與快取索引與查詢優化、Redis 與快取策略、讀寫分離與主從複製、Sharding
非同步與佇列背景任務、Message Queue、削峰填谷、事件驅動
水平擴充的挑戰多台後端的狀態與 Session、CAP 理論與一致性取捨
系統拆分單體痛點、微服務邊界、API Gateway
高流量與穩定性限流、排隊、降級、熔斷
資料與即時關聯式 vs 文件 vs 搜尋 vs 時序、WebSocket、Pub/Sub、分散式協調
可觀測性監控與指標、Log 與分散式追蹤
容器與編排為什麼要容器化、Kubernetes 在解決什麼
AI 與延伸LLM / RAG 怎麼接、串流與推理、以及用同一套思維看 YouTube / Uber / Twitter / ChatGPT

每一篇都會用情境來帶:例如「流量上來之後 Server CPU 爆了」「資料庫變慢」「登入狀態亂掉」「限時特價一開賣就掛」……從「發生什麼事 → 為什麼現有架構不夠 → 該往哪個方向想 → 引入什麼概念」這樣推進,而不是一上來就丟一堆名詞。同時會用生活化比喻(例如餐廳、廚房、帳本)幫助直覺理解,目標是讓前端工程師、或是沒有分散式背景的人也能看得懂


給大家一個宏觀的 overall 概念

與其把系統設計想成「要背很多架構圖」,不如想成一個問題:

一個網站,是怎麼從「一間小店」長成「一棟帝國」的?

一開始:一間餐廳、一個廚房、一本帳本。客人點餐、廚房出菜、帳本記帳。對應到系統,就是一個前端、一個後端、一個資料庫。在用戶少、請求少的時候,這樣就夠了。

這個系列會用「餐廳、廚房、帳本」來比喻「前端、後端、資料庫」,最起點的對應關係可以這樣看:

  • 餐廳的比喻:客人點餐 → 廚房出菜 → 帳本記帳
  • 對應的系統:使用者 → 後端 API → 資料庫
餐廳比喻對應系統
客人點餐使用者操作前端、發送請求
廚房出菜後端處理邏輯、回傳結果
帳本記帳資料庫儲存與查詢資料

為了方便理解,這就是最基礎的對應關係圖:

但生意變好之後,廚房會忙不過來、帳本會越翻越慢。還有一種狀況:同一間餐廳為了應付人潮,多開了一個出餐口(或多加一組廚房)來分流——問題是,同一個客人可能這次被帶到第一個出餐口、下次被帶到第二個出餐口,而兩個出餐口各自記「這桌是誰、點了什麼」,兩邊沒對齊,就會亂掉。真實世界的「開分店」是各做各的生意,沒有這種「同一客人被不同櫃檯服務」的狀況;但系統做水平擴充時,同一個使用者的請求可能這次打到第一台後端、下次打到第二台後端,所以「誰登入、購物車有什麼」若只存在每一台後端機器自己那裡,就會不一致。於是你要決定:廚房要變大(垂直擴充)還是多開幾間(水平擴充)?帳本要不要抄幾本只給查的副本(讀寫分離)?常被問的菜單要不要寫在小黑板(快取)?訂單太多要不要先丟進排隊區再慢慢做(Message Queue)?多間廚房要不要拆成中餐、西餐、甜點各一間(微服務)?人潮暴衝的時候要不要限流、排隊、關掉次要功能保核心(限流與降級)?

每一個「長大」,都對應一類真實問題;每一類問題,都對應一組我們會在系列裡慢慢講的概念與取捨。你不需要一次全懂,但若先有一個**「系統是會長大的,長大會有不同階段的問題與解法」**的整體圖景,後面每一篇就是在這張地圖上一個點一個點填上去。

下面是系列會走過的「演進路徑」——從起點一路到分散式架構;每個階段都會在後面的篇章裡用情境帶出來:

起點(一前、一後、一 DB)
擴充與優化(負載平衡、快取、讀寫分離)
非同步與佇列(MQ、背景任務)
拆分與高流量(微服務、限流降級)
規模化(Sharding、監控、容器、K8s)

這就是這個系列想給的宏觀概念:從一台 Server 到分散式架構,是一段有脈絡可循的演進,而不是一堆零散的技術名詞。 我們會用小明他們的故事,把這段演進走一遍;你讀完之後,再去看真實世界的 YouTube、Uber、面試考題,就會知道該從哪裡切入、該問什麼問題、該做什麼取捨。


接下來

下一篇開始,我們會從第 01 篇正式進入故事:小明他們做了一個網站——一前、一後、一 DB。那是起點,也是很多人熟悉的樣子。從那裡開始,我們會一步一步看,當用戶變多、需求變複雜,系統會遇到什麼,又該往哪裡長。

如果你跟我一樣,會做前後端分離、但對「再往後」的架構演進感到模糊,希望這個系列可以陪你一起把這張地圖畫出來。我們下一篇見。