分散式基礎練習題 (Practice - Distributed Systems)
Related Concepts
- 02-Distributed-Systems/01-Client-Server-Architecture
- 02-Distributed-Systems/02-CAP-Theorem
- 02-Distributed-Systems/03-Scalability
- 02-Distributed-Systems/04-Consistent-Hashing
- 02-Distributed-Systems/05-Numbers-to-Know
| 概念 | 預設選擇 | 替代條件 |
|---|---|---|
| 架構模型 | Client-Server | 音視訊通話 → P2P(WebRTC) |
| Client 類型 | Thick Client(SPA/App)+ REST | 無(SSR 已非現代預設) |
| CAP 預設 | AP(可用性優先) | 銀行/庫存/訂票 → CP |
| 擴展策略 | 先垂直,再水平 | 流量大 / 需高可用 → 水平 |
| Sharding routing | Consistent Hashing + vNodes | 固定 shard 數 → hash % N |
Part 1:Client-Server Architecture
Q1(Recall):Client 和 Server 各自的核心職責是什麼?
- Client:呈現 UI、收集使用者輸入、發送請求、展示 Server 回應
- Server:驗證授權、執行商業邏輯、讀寫資料庫、回傳結果
Q2(Recall):Client-Server 架構中「職責分離」帶來哪三個好處?
- 獨立維護:Server 可以更新邏輯和資料結構,不影響 Client
- 多 Client 支援:同一 Server 可同時服務網頁、App、第三方 API
- 獨立擴展:流量增加時只需擴展 Server,不需要改動 Client
Q3(Recall):Thin Client 和 Thick Client 的差異是什麼?現代系統設計通常偏向哪種?
- Thin Client:邏輯在 Server 端,Client 只負責渲染(如傳統 SSR 網頁);輕量但每次互動需請求
- Thick Client:Client 承擔較多邏輯,Server 主要提供資料 API(如 React SPA、手機 App);體驗流暢但前端複雜
現代系統設計預設 Thick Client + RESTful API。
Q4(Application):你在設計一個拍賣系統。請描述 Client-Server 的起手式:Client 是什麼、Server 需要什麼元件、用什麼 API?
- Client:瀏覽器 / 手機 App(Thick Client)
- Server 元件:
- Web Server(Nginx)
- App Server(商業邏輯:驗證出價、更新最高價)
- Database(存儲拍賣品、出價記錄)
- API:
- REST → 取得拍賣品資訊、提交出價
- SSE 或 WebSocket → 即時推送最新出價給所有觀看者
Q5(Recall):什麼情況下應該考慮 P2P 而不是 Client-Server?
當需要客戶端之間直接、低延遲的音視訊通訊時,例如視訊/音訊通話(WebRTC)。
系統設計面試中,除非題目明確涉及即時音視訊,否則一律預設 Client-Server。
Q6(Application):一個朋友說「我要設計 Google Docs,應該用 P2P 讓用戶直接同步」。你的評估是?
不適合用 P2P,應使用 Client-Server:
- P2P 連線複雜(NAT 穿透、STUN/TURN),極難做對
- Google Docs 需要中央服務器做衝突解決(OT/CRDT 演算法)
- 需要持久化儲存、版本歷史 → Server 必須存在
正確設計:Client → Server(WebSocket 雙向同步)→ Database
Q7(Analysis):「Server 不是一台機器而是一個叢集」意味著系統設計時需要考慮哪些額外問題?
- 流量分配:需要 Load Balancer 決定請求發到哪台伺服器
- 狀態管理:多台 Server 如何共享 Session 狀態?(Sticky Session 或集中式 Session Store)
- 資料一致性:多台 Server 背後的資料庫如何保持一致?(CAP 定理取捨)
- 故障處理:一台 Server 掛掉,LB 如何自動切換?(Health Check)
- 擴展策略:何時水平擴展、如何無縫加入新節點?
Q8(Analysis):以「電商網站」為例,哪些部分適合 Thick Client 邏輯,哪些必須在 Server 端?
Thick Client 適合(邏輯在前端):
- 購物車的即時更新(不需要每次點擊都打 API)
- 表單驗證(即時錯誤提示)
- 頁面路由和導航(SPA)
Server 端處理:
- 庫存檢查和最終確認(不能信任前端計算)
- 支付處理(安全需求,邏輯不能暴露)
- 價格計算(避免客戶端篡改)
原則:安全敏感、需要信任的邏輯留在 Server;使用者體驗相關的交互邏輯可以在 Client。
Part 2:CAP Theorem
Q9(Recall):CAP 定理的三個字母分別代表什麼?各自的含義是?
- C(Consistency):所有節點在同一時間看到相同的資料
- A(Availability):每個請求都能在有限時間內獲得回應
- P(Partition Tolerance):系統能在網路斷線/分區時繼續運作
Q10(Recall):為什麼 CA 系統在真實分散式環境中幾乎不存在?
因為在分散式系統中,網路分區(Partition)是不可避免的。
所以 P 幾乎是必選的,只能在 C 和 A 之間二選一。
CA 系統等於假設網路永遠不會出問題,這不切實際。
Q11(Recall):CP 系統和 AP 系統各自犧牲了什麼?請各舉一個真實例子。
- CP 系統:犧牲可用性(Availability)— 網路分區時拒絕服務以保持一致性
- 例:銀行帳戶餘額、庫存管理系統
- AP 系統:犧牲一致性(Consistency)— 節點間資料暫時不同,最終才同步
- 例:社群媒體動態牆、DNS、購物車
Q12(Application):以下場景各應選 CP 還是 AP?說明理由。
(A) 社群媒體動態牆 (B) 飯店訂房系統 (C) 使用者頭像快取 (D) 銀行帳戶餘額
- (A) 社群動態牆 → AP:稍舊的貼文可接受,不一致無嚴重後果
- (B) 飯店訂房 → CP:不能重複訂(同一房間賣給兩人),必須強一致
- (C) 頭像快取 → AP:暫時看到舊頭像無所謂
- (D) 銀行帳戶餘額 → CP:必須精確,不一致可能導致詐騙或超支
Q13(Application):ATM 系統選擇 AP,台北和台中同時提款可能造成什麼問題?如何緩解?
問題:兩邊的 ATM 因為網路斷線無法同步餘額,各自允許提款,結果總提款金額超過帳戶餘額(overdraft,超支)。
緩解方式:
- 設定提款上限(離線模式每次最多 $XX)
- 網路恢復後進行核帳,標記異常帳戶
- 實際銀行 ATM 通常選 CP,寧願拒絕服務也不要超支
Q14(Recall):在系統設計面試中,預設應該選擇 CP 還是 AP?什麼情況下才改選另一個?
預設選 AP(可用性優先)——大多數系統能接受最終一致性。
以下情況才選 CP:
- 有限資源預訂(座位、房間、門票):不能超賣
- 金融系統(帳戶餘額、交易):不能有資料不一致
- 庫存管理:精確數量攸關業務
Q15(Analysis):「最終一致性(Eventual Consistency)」是什麼意思?AP 系統選擇它有什麼代價?
最終一致性:系統保證在沒有新寫入的情況下,最終所有節點會收斂到相同的資料,但無法保證何時完成同步。
代價:
- 用戶可能讀到過期(stale)資料
- 同一用戶先寫後讀,可能讀不到自己的最新寫入
- 需要額外設計衝突解決機制(如 Last-Write-Wins、向量時鐘)
Q16(Analysis):你在設計一個線上購票系統(演唱會門票)。面試官問「你選 CP 還是 AP?為什麼?」請給出完整回答。
選 CP。
理由:演唱會門票是有限資源,如果選 AP,網路分區時兩個節點可能各自賣出同一張票,導致重複預訂,傷害用戶體驗和公司信譽。
具體設計:
- 用分散式鎖或資料庫強一致性保護庫存
- 網路分區時寧願返回錯誤,也不讓重複訂票發生
- 非核心功能(場次介紹、用戶評論)可以用 AP,只有「搶票」這個核心交易需要 CP
Part 3:Scalability
Q17(Recall):Throughput 和 Latency 分別指什麼?它們的關係是?
- Throughput(吞吐量):每秒能處理的請求數(RPS)
- Latency(延遲):單一請求從發出到完成所需的時間
關係:兩者都是效能指標,但方向不同。
高吞吐量 ≠ 低延遲(例如批次處理吞吐量高但延遲也高)。
擴展目標通常是同時提高吞吐量並降低延遲。
Q18(Recall):垂直擴展和水平擴展的做法各是什麼?各有什麼優缺點?
垂直擴展(Vertical Scaling):
- 做法:升級單一伺服器(加 CPU、加 RAM、換更快硬碟)
- 優點:簡單、不需修改應用程式架構
- 缺點:有物理上限;停機風險;後期成本高
水平擴展(Horizontal Scaling):
- 做法:增加伺服器數量 + Load Balancer 分流
- 優點:理論上無限擴展;高可用性
- 缺點:設計複雜;需處理分散式資料一致性
Q19(Recall):一般企業在系統擴展上的策略順序是什麼?為什麼?
先垂直擴展,再水平擴展。
原因:
- 垂直擴展簡單快速,短期有效
- 水平擴展設計複雜,過早引入增加不必要的系統複雜度
- 等到垂直擴展碰到瓶頸(硬體上限 / 成本過高 / 需要高可用性)時,再轉向水平擴展
Q20(Application):以下敘述何者正確?
(A) Horizontal scaling 設計比 vertical scaling 簡單
(B) Vertical scaling 理論上沒有上限
(C) Horizontal scaling 需要處理分散式資料一致性問題
(D) 一般建議直接從 horizontal scaling 開始
答案:(C)
- (A) 錯:horizontal scaling 設計更複雜,需要 load balancer 和分散式架構
- (B) 錯:vertical scaling 有物理上限(單台機器的 CPU、RAM 上限)
- (C) 對:多台機器間需要處理資料一致性(→ CAP 定理)
- (D) 錯:一般先用 vertical scaling,再轉向 horizontal scaling
Q21(Application):你的服務目前是單台 Server,流量突然暴增 10 倍。你的擴展計畫是什麼?
短期(立即應急):垂直擴展 — 升級到更大的 instance(更多 CPU / RAM),快速且不需改架構。
中期(流量持續高):水平擴展 — 加入更多 Server 節點,前端加 Load Balancer。
同時需要考慮:
- DB 瓶頸:加 Read Replica 分擔讀取;考慮 Caching(Redis)
- Session 狀態:改為無狀態(Stateless)Server,Session 存 Redis
- CAP 取捨:多台 Server 後,DB 一致性如何保證?
Q22(Application):水平擴展後,Load Balancer 本身成為單點故障(SPOF)。你如何解決?
Load Balancer 本身也需要高可用設計:
- 主備 LB(Active-Passive):一台 LB 主要處理流量,另一台備用;主機掛掉時自動切換(Failover)
- 多 LB(Active-Active):多台 LB 同時服務,透過 DNS Round-Robin 或 Anycast 分流
- 雲端托管 LB:AWS ALB / GCP Load Balancer 本身已是高可用服務,不需自己管理 SPOF
Q23(Analysis):為什麼可擴展性對業務重要?從技術和商業兩個角度說明。
技術角度:
- 應對高流量:使用者量成長時,避免延遲上升、錯誤增加、宕機
- 可靠性:分散式可擴展設計避免單點故障
- 彈性資源:按需擴縮,不浪費資源
商業角度:
- 業務成長支撐:產品成功後架構必須跟上,否則成長成為壓力而非優勢
- 成本效率:彈性擴縮能避免過度配置資源(over-provisioning)
- 用戶體驗:高延遲 / 宕機直接影響用戶留存和信任
Q24(Analysis):Scalability、CAP Theorem、Client-Server 這三個概念在系統設計中如何串連?
- Client-Server 是基礎框架:Client 發請求,Server 處理
- Scalability 是當 Server 撐不住時的解法:垂直 → 水平擴展,加更多 Server
- CAP Theorem 是水平擴展後的核心取捨:多台 Server 共享資料時,如何在一致性和可用性之間選擇
串連邏輯:
流量增加 → 需要 Scalability(加 Server)
→ 多台 Server 就是分散式系統
→ 分散式系統必須面對 CAP 取捨
→ 根據業務場景選 CP 或 AP
Part 4:Consistent Hashing
Q25(Recall):為什麼不能直接用 hash(key) % N 來分片?請舉例說明。
當 N 改變(加入或移除節點)時,幾乎所有 key 的位置都會變。
例:N=3 時 1,4,7→N1; 2,5,8→N2; 3,6,9→N0;
N=4 時 1,5,9→N1; 2,6→N2; 3,7→N3; 4,8→N0。
9 個 key 有 7 個要搬遷,導致大量資料移動、快取全 miss、系統短時間內崩潰。
Q26(Recall):是非題 — 在 Consistent Hashing 中新增一個節點,所有 key 都需要重新分配。
錯。 只有「新節點與其前一個節點之間」的 key 需要搬到新節點,其他 key 不受影響。
這正是 Consistent Hashing 的核心價值:最小化搬遷。
Q27(Recall):Virtual Nodes(虛擬節點)解決了哪兩個問題?
- 資料分佈不均:節點少時 hash 環位置可能集中,某節點被迫吃下大半流量。虛擬節點把每個實體節點拆成多個位置,讓分佈更均勻。
- 忽略硬體差異:強機可配 50 個 vNode、弱機配 20 個,按能力分配負載,而不是所有節點一視同仁。
Q28(Application):列舉三個適合使用 Consistent Hashing 的系統設計場景。
任三個:
- Distributed Cache sharding(Memcached / Redis Cluster)
- Storage sharding / routing(Cassandra、DynamoDB 風格)
- Sticky connections(聊天室 / 即時服務把 user 或 room 路由到固定節點)
- API Gateway / Sticky Sessions(減少跨節點 session 同步)
- Rate Limiting(user_id / api_key 穩定分到對應節點)
- CDN / Edge Routing(URL 或內容 ID 映射到 edge 節點做快取)
Q29(Application):你的 Redis 叢集原本 3 台,擴充到 5 台。用 hash(key) % N vs Consistent Hashing 差在哪裡?
hash(key) % N:N 從 3 → 5,幾乎所有 key 的位置都會變 → 整個快取層 miss → 資料庫瞬間承受巨量流量(cache stampede)→ 系統崩潰風險高。- Consistent Hashing:只有落在新節點區段的 key 會搬遷,其他 key 保留 → 快取命中率幾乎不變 → 擴容過程平滑。
搬遷量比例:hash % N 約 O(K);Consistent Hashing 約 O(K/N)。
Q30(Analysis):為什麼現代系統通常同時使用 Consistent Hashing + Virtual Nodes?只用其中一個會有什麼問題?
- 只用 Consistent Hashing(無 vNodes):
- 節點少時分佈不均,熱點問題嚴重
- 節點移除時所有流量集中轉到下一個節點 → 負載突然翻倍
- 無法按硬體能力分配
- 只用 Virtual Nodes(不是一致性雜湊):其實 vNode 這個概念依附在環結構上,沒有 consistent hashing 就沒意義。
組合後:搬遷量小(一致性雜湊)+ 分佈均勻(vNodes)+ 可按能力分配(vNode 數量)+ 搬遷更細粒度(每 vNode 搬一小段)→ 生產級分散式系統的標準設計。
Part 5:Numbers to Know
Q31(Recall):配對題 — 將指標與量級配對:
(1) Redis 單節點讀取延遲 (2) Kafka 單 broker 吞吐量 (3) PostgreSQL cached read (4) Aurora/RDS 單節點寫入
/ (a) ~1M msgs/sec (b) <1ms (c) 10–20k TPS (d) 1–5ms
- 1 → (b):Redis < 1ms
- 2 → (a):Kafka 1M msgs/sec per broker
- 3 → (d):PostgreSQL cached read 1–5ms
- 4 → (c):Aurora/RDS 寫入 10–20k TPS
Q32(Recall):一個調校良好的單一資料庫可以支撐多少用戶?什麼時候才真的需要 sharding?
數百萬甚至上千萬用戶。不要在 500GB–2TB 時就急著談 sharding。
需要 sharding 的觸發點:
- 資料規模逼近 50TiB
- 寫入吞吐長期 > 10k TPS
- 未快取讀取要求 < 5ms
- 需要跨區域部署
- 備份時間過長或不可行
Q33(Recall):現代系統中,真正的瓶頸通常是什麼?是記憶體大小嗎?
不是記憶體大小。真正的瓶頸多半是:
- ops/sec(每秒操作數)
- 網路頻寬
這跟幾年前的狀況完全相反。單台機器的記憶體已經很大(最高可達 2TB),通常不會先碰到 RAM 上限。第一個瓶頸通常是 CPU。
Q34(Application):你的同事說「我們有 800GB 資料、每秒 3,000 次查詢,先做 sharding 比較保險」。你的評估是?
過早 sharding,不建議。
800GB 對單一 PostgreSQL 太小,3k QPS 也遠低於 50k TPS 的單機讀取上限。
Sharding 之前還有很多更便宜的招:
- 慢查詢 → 加 index / 優化 SQL
- 讀取瓶頸 → 加 cache → 加 read replica
- 寫入瓶頸 → 調 DB 參數 → 升級硬體
Sharding 的代價(跨 shard 查詢、分散式交易、資料遷移)通常不值得在這個規模引入。Senior+ 面試官會欣賞「根據數據做合理判斷」而不是「盲目套 fancy words」。
Q35(Analysis):「Latency 順序:memory ≪ disk ≪ network」這個量級直覺在系統設計面試中怎麼用?舉一個應用例子。
這個量級直覺幫你選對快取層次和估算延遲預算。
量級:
- Memory(in-process):奈秒級
- Memory(Redis 同區):< 1ms(有網路 hop)
- Disk(DB cached read):1–5ms
- Disk(DB uncached):5–30ms
- Network(跨區):10–100ms+
應用例:「API SLA 要求 < 10ms。如果每次都打 DB(30ms uncached),絕對達不到。我會加 Redis cache(1ms),對 99% 的熱資料 hit cache 後總延遲 < 5ms 是可行的。極端熱 key 再加 in-process cache,做到奈秒級。」
這種「量級 + 推理」就是面試官想聽到的。
| 問題 | 解法 |
|---|---|
| 架構起手式 | Client → API → Server → DB,再考慮擴展 |
| P2P vs C/S | 音視訊通話用 P2P,其餘用 Client-Server |
| 安全邏輯 | 永遠在 Server 端,不信任 Client 輸入 |
| CAP 預設 | AP(可用性);銀行/庫存/訂票 → CP |
| CA 系統 | 現實中不存在(P 不可避免) |
| 擴展順序 | 先垂直,流量持續增加再水平 |
| 水平擴展挑戰 | Session 狀態、資料一致性、LB SPOF |
| 分片 routing | Consistent Hashing + vNodes(節點會變動時) |
| 搬遷量 | hash % N → O(K);Consistent Hashing → O(K/N) |
| vNodes 觸發條件 | 節點少 / 硬體差異大 / 想要平滑擴容 |
| Latency 順序 | memory ≪ disk ≪ network |
| 過早 sharding | < 50TiB 通常不需要;先 index/cache/replica |
| 真正瓶頸 | 通常是 ops/sec 或頻寬,不是記憶體 |