Scalability Patterns

Interview Context

「一台 server 撐不住了,你會怎麼 scale?」是 system design 面試的開場經典題。面試官想看的不是背架構圖,而是你能不能講出每一步是什麼東西先壞掉、你加了什麼元件解決、又引入了什麼新問題。這一頁走完 single server 到 multi-region 的完整演化路徑,也是 DS/MLE 談 model serving scaling 的共同語言。

What You Should Understand

  • 能完整敘述 single server → LB + 多台 app server → cache/CDN → replication → sharding → multi-region 的演化,以及每一步的動機
  • 知道 L4 與 L7 load balancing 的差異,能比較 round robin、least connections、IP hash、consistent hashing
  • 能解釋為什麼 stateless service 是 horizontal scaling 的前提,session 該externalize 到哪裡
  • 掌握 database scaling path:read replica → cache → partitioning → sharding,以及 replication lag 和 hot shard 的處理
  • 能設計流量尖峰的防禦:autoscaling、queue-based load leveling、load shedding、circuit breaker
  • 知道要監控什麼:throughput、latency percentiles(p50/p95/p99)、error rate、saturation(USE/RED)

From One Server to Millions of Users

The classic scaling journey: start with everything on one box, and at each stage identify what breaks first and what you add to fix it. 面試時照這個順序講,每一步都說清楚「痛點 → 解法 → 新的 tradeoff」,就是一個結構完整的答案。

StageWhat BreaksWhat You AddNew Problem Introduced
1. Single serverWeb app + DB 搶同一台機器的 CPU/RAM/IONothing yet — 這是起點Everything is a single point of failure
2. Separate DB serverDB 查詢吃掉 app 的資源Dedicated database serverApp 和 DB 各自仍是 SPOF
3. LB + multiple app servers單台 app server 的 CPU 飽和;掛了就全站停擺Load balancer + N stateless app serversSession 不能存在單台機器上(見 stateless 章節)
4. Cache + CDNDB 被重複的 read query 打爆;靜態資源吃頻寬Redis/Memcached cache layer + CDN for static assetsCache invalidation、cache-DB consistency
5. DB replication單台 DB 的 read throughput 到頂Primary-replica replication(write 走 primary,read 走 replicas)Replication lag → stale reads
6. Sharding單台 DB 的 write throughput / 資料量到頂Horizontal sharding by keyCross-shard join/transaction 困難、hot shard、resharding 痛苦
7. Multi-region跨洲 latency 高、單一 region 掛掉全球停擺Geo-DNS routing + per-region deployment + cross-region data replicationData consistency across regions、failover 複雜度

幾個貫穿全程的原則:

  • Scale out, not up(優先 horizontal scaling):vertical scaling(換更大的機器)簡單但有硬上限,而且沒有 redundancy;horizontal scaling(加更多台)理論上無上限,但要求服務 stateless。
  • 每一層都要消除 SPOF:LB 要有 failover、DB 要有 replica、cache 要有 cluster。一個元件只有一台,它就是你的 availability 上限。
  • Async where possible:耗時的工作(發 email、產報表、跑 inference batch)丟進 message queue,web tier 保持快速回應。

面試敘事技巧

不要一開口就畫 multi-region 大架構。從 single server 講起,讓面試官看到你理解為什麼需要每個元件 — 「我們先假設 QPS 很低,一台就夠;當 read 開始變慢,我會先加 cache 而不是直接 shard,因為 sharding 的複雜度成本高很多。」這種 cost-aware 的推理比背圖高分。

Load Balancing Deep Dive

A load balancer distributes incoming requests across multiple servers, providing scalability (add more servers) and availability (route around dead servers).

L4 vs L7

AspectL4 (Transport Layer)L7 (Application Layer)
Routing based onIP address + TCP/UDP portHTTP headers, URL path, cookies, request body
Sees request contentNo — 只轉發 TCP packetsYes — 完整解析 HTTP request
SpeedFaster, lower overheadSlower(要 terminate 連線、解析 protocol)
CapabilitiesBasic distributionPath-based routing(/api → service A), TLS termination, compression, rate limiting
ExamplesAWS NLB, LVS, HAProxy (TCP mode)AWS ALB, Nginx, HAProxy (HTTP mode), Envoy

實務上常見兩層並用:edge 用 L4 撐超高吞吐,往內用 L7 做 path routing 和 TLS termination。

Load Balancing Algorithms

AlgorithmHow It WorksProsConsBest For
Round robin依序輪流分給每台 server簡單、無狀態假設每台等強、每個 request 等重Homogeneous servers, uniform requests
Weighted round robin依 server 權重按比例分配支援不同機型混用權重要手動調新舊機器混雜、canary 分流
Least connections分給目前 active connection 最少的 server自動適應 request 耗時不均要追蹤 connection 狀態Long-lived / 耗時差異大的 requests(如 model inference)
IP hashhash(client IP) 決定 server同一 client 固定落同一台分佈可能不均;NAT 後大量 client 同 IP需要 session affinity 又不想用 cookie
Consistent hashingServer 排在 hash ring 上,key 順時針找最近節點增減節點只影響 1/N 的 keys實作較複雜;需 virtual nodes 平衡Cache clusters、sharded storage、stateful routing

Consistent hashing 為什麼重要:naive 的 hash(key) mod N 在 N 改變時幾乎所有 key 都要搬家 — 對 cache cluster 來說等於一次全面 cache miss storm。Consistent hashing 讓加減一台機器時,平均只有 1/N1/N 的 keys 需要 remap。搭配 virtual nodes(每台實體機在 ring 上放多個點)可以讓分佈更均勻。

Health Checks

LB 必須知道後端哪些 server 還活著:

  • Passive:觀察真實流量,連續失敗就標記 unhealthy。
  • Active:LB 定期打 health endpoint(如 GET /healthz),連續 N 次失敗 → 移出 rotation;恢復 M 次成功 → 加回來。
  • Health endpoint 應該檢查服務真的能工作(DB 連線、關鍵依賴),而不是只回 200 — 但也不能太重,避免 health check 本身變成負載。

Sticky Sessions vs Stateless

Sticky session(session affinity)讓同一個 user 的 requests 固定落在同一台 server,因為 session state 存在那台機器的記憶體。為什麼這是壞味道

ProblemConsequence
Server dies那台上所有 user 的 session 全部消失 → 被強制登出
Uneven load熱門 user 集中的 server 過載,LB 無法重新平衡
Autoscaling 失效縮容時砍掉哪台都會傷到某群 user;新機器接不到既有 user
Deploy 困難Rolling deploy 每重啟一台就掃掉一批 session

正解是把 state externalize(下一節),讓任何 server 都能處理任何 request。

LB Failover

Load balancer 自己也不能是 SPOF:

ModeHowTradeoff
Active-passiveStandby LB 透過 heartbeat 監控 active LB,掛掉時接手 virtual IP(VRRP/keepalived)簡單;平時 standby 資源閒置;failover 有數秒空窗
Active-active多台 LB 同時服務(DNS round robin 或 anycast 分流)資源利用率高、無單點;設定與 state 同步較複雜

Stateless Services & Session Management

A stateless service keeps no client state between requests — 每個 request 自帶所有必要資訊,或者 state 存在外部共用儲存。這是 horizontal scaling 的解鎖鑰匙。

Where to Keep Session StateLatencyProsCons
App server memoryFastest零依賴綁死 sticky session,無法自由 scale
Redis / Memcached~1ms快、支援 TTL、所有 server 共享多一個要維運的元件
Database~5-10msDurable慢,session 讀寫量大時壓垮 DB
Client-side token (JWT)0(隨 request 帶上)Server 完全 stateless、免查儲存Token 無法即時撤銷、payload 大小受限

Stateless 之後你獲得的能力:

  • 任意加減機器:LB 可以把 request 丟給任何一台,autoscaling 縮容不會傷害任何 user。
  • Rolling deploy / 快速換血:重啟、替換 server 對 user 無感。
  • 容錯:一台掛掉,下一個 request 自然落到別台,user 頂多重試一次。

常見誤區

「Stateless」不代表系統沒有 state — state 永遠存在,只是從 compute tier 搬到專門的 storage tier(Redis、DB、object storage)。面試時說「我把 state externalize 到 Redis,讓 web tier stateless」比說「我做成 stateless」精確得多。同樣的原則適用於 ML serving:model weights 是 read-only artifact 可以每台各載一份,但 user context / feature cache 要放外部共享儲存。

Database Scaling Path

Database 通常是最後、也最難 scale 的元件,因為它有 state。依複雜度由低到高:

Step 1: Read Replicas

Primary 負責所有 writes,changes 非同步複製到多台 read replicas,read query 分散到 replicas。適合 read-heavy workload(多數 web 應用 read:write 約 10:1 或更高)。

Replication lag 是主要代價:replica 落後 primary 數十 ms 到數秒。經典 bug — user 更新個人資料(write 到 primary)後立刻重新整理頁面(read 到 replica),看到舊資料。

MitigationHow
Read-your-writes該 user 寫入後的短時間內,他的 read 強制走 primary
Sticky read after writeSession 記錄最後 write 的 timestamp/LSN,read 只走已追上的 replica
Synchronous replication等至少一台 replica 確認才 commit — 犧牲 write latency 換一致性
業務容忍明確標示「更新可能延遲數秒」— 很多場景其實可以接受

Step 2: Caching Layer

在 DB 前面擋一層 Redis/Memcached。Cache-aside 是最常見的 pattern:先查 cache,miss 才查 DB 並回填。Hit rate 90% 意味著 DB 只承受 10% 的 read 流量。相關細節(eviction、invalidation、stampede)屬於 caching 專章,這裡的重點是:在考慮 sharding 之前,先確認 cache 已經把 read 壓力吃掉

Step 3: Vertical Partitioning

把不同的 tables / columns 拆到不同 DB:orders 一台、users 一台、logs 一台;或把巨大的 blob column 拆出去。按功能切割,實作直觀,但單一 table 太大的問題仍在。

Step 4: Horizontal Sharding

同一張 table 的 rows 按 shard key 切到多台 DB。這是 write scaling 的最終手段,代價最高:

ChallengeWhy It HurtsMitigation
Choosing shard key選錯 key 之後幾乎不可逆選 cardinality 高、access pattern 對齊的 key(如 user_id)
Cross-shard queriesJoin / aggregation 要 fan-out 到所有 shards 再合併Denormalize、預先聚合、或改用 analytics DB
Cross-shard transactions失去單機 ACIDSaga pattern、業務上避免跨 shard 交易
Hot shard某個 key 流量特別大(celebrity problem)見下方
Resharding資料搬遷期間要雙寫或停機一開始就用 consistent hashing 或預切大量 virtual shards

Hot shard mitigation

  • 更細的 shard keyuser_id 改成 hash(user_id + date) 之類的 composite key,把單一熱點打散。
  • Salting:對已知的熱 key 加隨機 suffix 分散到多個 shards,讀取時聚合。
  • 熱點獨立 + cache:celebrity 帳號單獨隔離資源,並用 cache 吸收絕大部分 read。
  • Virtual shards:邏輯上先切 1024 個 virtual shards,物理機器只是 virtual shards 的宿主,搬遷時以 virtual shard 為單位移動。

不要過早 sharding

面試中直接跳到 sharding 是常見扣分點。正確的順序是:cache → read replica → vertical partitioning → 真的不行才 sharding。一台現代 DB server 配合好的 index 和 cache 可以撐到每秒數萬 queries — 多數公司終其一生不需要 shard。展現你知道 sharding 的代價,比展現你會 shard 更值錢。

Nginx & Reverse Proxies in Practice

A reverse proxy sits in front of backend servers and handles incoming traffic on their behalf. Nginx 是最常見的實作,面試常被問「為什麼 Nginx 這麼快」。

Event-driven, non-blocking architecture:傳統 Apache(prefork 模式)一個 connection 配一個 process/thread,一萬個併發連線就要一萬個 threads — memory 和 context switch 成本爆炸(the C10K problem)。Nginx 用少量 worker processes(通常等於 CPU 核心數),每個 worker 跑一個 event loop,用 epoll/kqueue 非阻塞地同時看管數萬條 connections。連線在等待 IO 時不佔用 thread,所以記憶體開銷極低、吞吐極高。

Typical roles of Nginx in a deployment:

RoleWhat It DoesWhy Offload to Nginx
Static file serving直接回 images/JS/CSS,不打到 appNginx serve 靜態檔比 Python/Node app 快一個量級
TLS termination對外 HTTPS,對內解密成 HTTP集中管理憑證;app servers 免除加解密 CPU 成本
Reverse proxy轉發 request 到 upstream app servers,隱藏內部拓撲安全(後端不直接暴露)、可加 buffer/timeout/retry
Load balancingupstream block 內建 round robin / least_conn / ip_hash一個設定檔就有 L7 LB
Compression / cachinggzip response、cache 可快取的回應減少頻寬與後端負載
Rate limitinglimit_req 限制單一 client 的請求速率第一道防濫用防線
# Minimal Nginx reverse proxy + load balancer
upstream app_servers {
    least_conn;                      # pick server with fewest active connections
    server 10.0.0.11:8000 weight=3;  # newer, bigger machine
    server 10.0.0.12:8000 weight=1;
    server 10.0.0.13:8000 backup;    # only used when others are down
}

server {
    listen 443 ssl;
    location /static/ {
        root /var/www;               # serve static files directly
    }
    location / {
        proxy_pass http://app_servers;
        proxy_next_upstream error timeout;  # retry next server on failure
    }
}

Forward proxy vs reverse proxy 一句話區分:forward proxy 代表 client 出門(隱藏 client,如公司網路出口);reverse proxy 代表 server 接客(隱藏 servers,做 LB/TLS/快取)。

Handling Traffic Spikes

平常 1000 QPS 的系統遇到行銷活動打進 20000 QPS,怎麼不倒?分四層防禦。

Autoscaling

根據 metrics 自動加減 instances:

PolicyTriggerNotes
Target tracking維持某 metric 在目標值(如 CPU 60%)最常用;設好目標就自動調
Step scalingMetric 超過閾值 → 加固定數量可分級:CPU 70% 加 2 台,90% 加 5 台
Scheduled依已知模式預先擴容每天晚餐時段、已排定的行銷活動
PredictiveML 預測未來負載提前擴容適合有規律週期的流量

Autoscaling 的限制要講出來才專業:新 instance 冷啟動要 1-5 分鐘(開機、載入 model、暖 cache),瞬間尖峰等不了;scale-in 要設 cooldown 避免震盪;下游(DB)不會跟著自動變大 — app tier 擴容可能只是把壓力更快地灌進 DB。

Queue-Based Load Leveling

在 producer 和 consumer 之間放一個 message queue(Kafka/SQS/RabbitMQ),把瞬間尖峰「攤平」成 consumer 可消化的穩定速率。適用於可以非同步的工作:下單後的 email、影片轉檔、batch inference。User 得到「已受理」的即時回應,實際處理稍後完成。代價是 end-to-end latency 變長,且要監控 queue depth — queue 一直長就是 consumer 追不上。

Graceful Degradation & Load Shedding

當流量超過極限,有選擇地犧牲,保住核心

  • Graceful degradation:關掉非核心功能 — 推薦欄位改回熱門榜(不打 model)、暫停即時通知、搜尋改用簡化 ranking。系統變「笨」但不倒。
  • Load shedding:主動拒絕超額請求(回 429 Too Many Requests),優先砍低優先級流量(爬蟲、預載、免費用戶),保住付費核心操作。快速拒絕 1% 的 requests,遠比 100% 的 requests 全部 timeout 好。
  • Backpressure:下游明確告訴上游「慢一點」,而不是默默累積 queue 直到 OOM。

Circuit Breakers

防止一個掛掉的依賴拖垮整個系統。Circuit breaker 包在對外部服務的呼叫外面,有三個狀態:

StateBehaviorTransition
Closed正常放行,統計失敗率失敗率超過閾值 → Open
Open直接 fail fast(回 fallback),不打依賴等待 timeout 後 → Half-open
Half-open放少量試探請求成功 → Closed;失敗 → Open

沒有 circuit breaker 的災難劇本:依賴的服務變慢 → 你的 threads 全部卡在等它 timeout → 你的服務也沒有可用 thread → 你的上游也卡住 → cascading failure 一路往上燒。Fail fast + fallback(回 cache 值、預設值、降級結果)切斷連鎖。

面試加分句

「Autoscaling 處理的是可預期的緩慢增長,load shedding 和 circuit breaker 處理的是擴容來不及的瞬間尖峰和依賴故障 — 兩者是互補的,不是二選一。」能講出這個層次感,面試官會知道你真的 operate 過系統。

System Performance Metrics

Scale 的前提是知道瓶頸在哪。兩個經典 framework:

RED Method (for request-driven services)

MetricWhatAlert Example
RateRequests per second (throughput)QPS 突降 50% — 上游掛了?
Errors失敗請求數 / 比率Error rate 超過 1%
DurationLatency 分佈(percentiles)p99 超過 500ms

USE Method (for resources: CPU, memory, disk, network)

MetricWhatExample
Utilization資源忙碌時間比例CPU 85% busy
Saturation排隊中的工作量Run queue length、connection pool 等待數
Errors資源層級錯誤Disk IO errors、dropped packets

Why Percentiles, Not Averages

Average latency 會騙人:99 個 request 花 10ms、1 個花 2000ms,平均約 30ms 看起來很棒,但那 1% 的 user 體驗極差。所以看 p50(典型體驗)/ p95 / p99(尾部體驗)。尾部很重要,因為:(1)大流量下 1% 就是每天數十萬個受害 request;(2)一個頁面 fan-out 打 10 個後端服務時,只要任何一個踩到 p99,整頁就慢 — 你的 page-level p50 由 service-level p99 決定(tail amplification)。

另外兩個關鍵觀念:

  • Throughput 和 latency 的關係不是線性:utilization 接近 100% 時,queueing 效應讓 latency 急遽飆升(排隊理論)。所以 capacity planning 通常以 60-75% utilization 為目標水位,留 headroom 吸收尖峰和機器故障。
  • Capacity planning 基本流程:量測單台 instance 的極限(load test 找出 latency 開始劣化的 QPS)→ 用 peak traffic 估算需要的台數 → 加上 redundancy(N+2:容忍 1 台故障 + 1 台在 deploy)→ 對照流量成長率排採購/擴容時程。

Real-World Use Cases

Case 1: 模型推論服務從單機到 Autoscaling 集群

你訓練好一個 fraud detection model,用 FastAPI 包成 API 部署在一台機器上,p99 latency 40ms。行銷部門接了一個大客戶,流量預估成長 20 倍。

這一頁的概念怎麼用上:

  • Model server 天然接近 stateless(weights 是 read-only),把 feature cache 移到 Redis 之後就完全 stateless → 可以放到 LB 後面 horizontal scaling。
  • Inference latency 因輸入而異(有些交易要查更多 features),所以 LB 用 least connections 而不是 round robin,避免慢 request 堆在同一台。
  • Autoscaling 用 target tracking(GPU/CPU utilization 70%),但要注意冷啟動:新 instance 載入 model 要 90 秒,所以配 scheduled scaling 在已知高峰前預先擴容。
  • 過載時的 graceful degradation:model service 超時就 fallback 到 rule-based score,寧可精度略降也不能 block 交易。

Interview follow-ups

  • 你的 health check endpoint 應該檢查什麼?只回 200 夠嗎?(要驗證 model 已載入且能推論,例如對固定樣本跑一次 forward pass)
  • Model 更新時怎麼 rolling deploy 不中斷服務?如果新舊版本的 feature schema 不同呢?
  • GPU instance 很貴,autoscaling 的 scale-in 策略怎麼設才不會震盪?

Case 2: 報表查詢壓垮主庫 — Read Replica 與 Cache

你是 DS,寫了一批 dashboard 查詢直接打 production PostgreSQL。月底主管們同時開報表,heavy aggregation queries 把 primary DB 的 CPU 打到 100%,線上交易開始 timeout — 你的 dashboard 弄倒了主站。

這一頁的概念怎麼用上:

  • Analytics 流量和 transactional 流量必須隔離。第一步:加 read replica,所有報表查詢改連 replica — primary 只服務線上交易。
  • Replication lag 對報表通常無害(晚 5 秒沒人在乎),這是 lag 容忍度高的完美場景。
  • Dashboard 的查詢重複性極高 → 加 cache layer(或 pre-aggregated summary tables,每小時 refresh),同一份月報不需要每次重算。
  • 長期解法:把分析負載搬去 columnar warehouse(BigQuery/Snowflake),OLTP 和 OLAP 徹底分家。

Interview follow-ups

  • 如果某個報表需要「絕對最新」的資料,read replica 的 lag 怎麼處理?
  • Replica 也被打爆了怎麼辦?(加 replica、加 cache、限制查詢併發、改 pre-aggregation)
  • 為什麼 OLTP database 跑 analytics query 特別傷?(row store 對 full scan aggregation 不友善、長交易阻擋 vacuum、buffer pool 被掃光)

Case 3: 行銷活動流量尖峰的 Load Shedding

電商平台辦限時搶購,開賣瞬間 QPS 從 2000 暴衝到 60000。Autoscaling 來不及(冷啟動 3 分鐘),去年同樣的活動把整站打掛,包含跟活動無關的頁面。

這一頁的概念怎麼用上:

  • Scheduled scaling:活動時間已知,提前 30 分鐘擴容到預估容量的 1.5 倍 — predictive 比 reactive 便宜且可靠。
  • Queue-based load leveling:搶購下單改成非同步 — request 進 queue 立刻回「排隊中」,consumer 以 DB 能承受的速率消化。User 等 3 秒拿到結果,遠好過整站 timeout。
  • Load shedding 分級:超額流量按優先級砍 — 先拒爬蟲和未登入流量,再限縮瀏覽類 API,最後才動結帳流程。回 429 + Retry-After,讓 client 有秩序地重試。
  • Circuit breaker 保護無關服務:推薦系統、評論服務等非核心依賴掛了就 fallback 靜態內容,不讓它們的故障擴散到搶購主流程。
  • Cache 靜態化:活動頁面全部 CDN 化,商品詳情 cache TTL 拉長 — 只有庫存和下單需要打到後端。

Interview follow-ups

  • 搶購的庫存扣減怎麼避免 oversell?(Redis atomic decrement / DB row lock / 預扣庫存 + 非同步確認的 tradeoff)
  • 怎麼區分「值得服務的尖峰」和「該擋掉的濫用流量」?
  • 活動後怎麼做 capacity 覆盤?要看哪些 metrics 決定明年準備多少容量?

Hands-on: Load Balancing in Python

Weighted Round-Robin Balancer

class WeightedRoundRobin:
    """Smooth weighted round-robin (same algorithm as Nginx).

    Each pick: add weight to each server's current score,
    pick the highest, then subtract total weight from it.
    Produces an evenly interleaved sequence like A A B A C.
    """

    def __init__(self, servers):
        # servers: dict of name -> weight, e.g. {"s1": 3, "s2": 1, "s3": 1}
        self.weights = dict(servers)
        self.current = {name: 0 for name in servers}
        self.total = sum(servers.values())

    def next_server(self):
        for name, weight in self.weights.items():
            self.current[name] += weight          # accumulate score
        best = max(self.current, key=self.current.get)
        self.current[best] -= self.total          # penalize the chosen one
        return best

lb = WeightedRoundRobin({"s1": 3, "s2": 1, "s3": 1})
sequence = [lb.next_server() for _ in range(5)]   # s1, s1, s2, s1, s3

Least-Connections Balancer

import heapq
import itertools

class LeastConnections:
    """Route each request to the server with the fewest active connections.

    A heap keyed by (active_connections, tiebreaker) gives O(log n) picks.
    Caller must call release() when the request finishes.
    """

    def __init__(self, servers):
        self.active = {name: 0 for name in servers}
        self.counter = itertools.count()          # tiebreaker for equal loads

    def acquire(self):
        # pick server with minimum active connections
        name = min(self.active, key=lambda s: (self.active[s], next(self.counter)))
        self.active[name] += 1
        return name

    def release(self, name):
        self.active[name] -= 1                    # request finished

lb = LeastConnections(["s1", "s2", "s3"])
server = lb.acquire()      # dispatch request to this server
# ... request completes ...
lb.release(server)

Health Checker Loop

import time
import urllib.request

class HealthChecker:
    """Active health checks: probe /healthz, require consecutive
    failures/successes before flipping state (avoids flapping)."""

    def __init__(self, servers, fail_threshold=3, rise_threshold=2):
        self.servers = servers                     # name -> base URL
        self.healthy = {name: True for name in servers}
        self.fails = {name: 0 for name in servers}
        self.rises = {name: 0 for name in servers}
        self.fail_threshold = fail_threshold
        self.rise_threshold = rise_threshold

    def probe(self, url):
        try:
            with urllib.request.urlopen(url + "/healthz", timeout=2) as resp:
                return resp.status == 200
        except Exception:
            return False

    def check_all(self):
        for name, url in self.servers.items():
            if self.probe(url):
                self.fails[name] = 0
                self.rises[name] += 1
                if not self.healthy[name] and self.rises[name] >= self.rise_threshold:
                    self.healthy[name] = True      # add back to rotation
            else:
                self.rises[name] = 0
                self.fails[name] += 1
                if self.healthy[name] and self.fails[name] >= self.fail_threshold:
                    self.healthy[name] = False     # remove from rotation

    def alive_servers(self):
        return [name for name, ok in self.healthy.items() if ok]

    def run(self, interval=5):
        while True:                                # background loop
            self.check_all()
            time.sleep(interval)

Interview Signals

What interviewers listen for:

  • 你按演化順序講架構(先 cache 再 replica 再 shard),而不是一開始就丟出過度設計的大圖
  • 每加一個元件你都能說出它引入的新問題(replication lag、cache consistency、sticky session)
  • 你知道 stateless 是 horizontal scaling 的前提,能具體說 state 要 externalize 到哪裡
  • 你主動談 failure:SPOF 消除、health check、circuit breaker、load shedding、rollback
  • 你用數字說話:latency percentiles 而非 average、utilization 目標水位、單機容量估算

Practice

Flashcards

Flashcards (1/10)

從一台 server 到百萬用戶,講出經典的七步演化。

(1)Single server →(2)DB 分離出去 →(3)LB + 多台 stateless app servers →(4)Cache + CDN →(5)DB read replication →(6)Sharding →(7)Multi-region。每一步的口訣:什麼先壞掉、加什麼、引入什麼新問題。

Click card to flip

Quiz

Question 1/10

單台 app server CPU 飽和且成為 SPOF。演化路徑的下一步是什麼?

Mark as Complete

3/5 — Okay