速查表 (Quick Reference)
面試預設選擇
| 決策點 | 預設選擇 | 替代條件 |
|---|---|---|
| 架構模型 | Client-Server | 音視訊通話 → P2P(WebRTC) |
| Client 類型 | Thick Client(SPA/App)+ REST | — |
| CAP 取捨 | AP(可用性優先) | 銀行/庫存/訂票 → CP |
| 擴展策略 | 先垂直,再水平 | 流量持續高 / 需高可用 → 水平 |
| 傳輸層 | TCP | 低延遲 + 可丟包 + 無瀏覽器 → UDP |
| API 範式 | REST | 靈活查詢 → GraphQL;內部高效 → gRPC |
| 即時推送 | SSE | 雙向 → WebSocket;P2P音視訊 → WebRTC |
| LB 類型 | L7 | WebSocket → L4 |
| LB 演算法 | Round Robin | 持久連線 → Least Connections |
| 故障處理 | 重試 + 指數退避 + 抖動 | 持續失敗 → 熔斷器 |
| 分片 routing | Consistent Hashing + vNodes | 固定 shard 數 → hash % N |
| 通用索引 | B-Tree / B+Tree | 等值 → Hash;寫多 → LSM |
| 地理索引 | R-Tree(SQL)/ Geohash(NoSQL) | Uber 鄰近 → H3;地圖切片 → S2 |
| 全文檢索 | Inverted Index(Elasticsearch) | 小規模 → PostgreSQL FTS |
| 隔離等級 | Read Committed | 多次讀同 row 一致 → Repeatable Read;金融 → Serializable |
| 超賣防護 | 原子 UPDATE / SELECT FOR UPDATE |
不要 提升到 Serializable |
| 跨服務交易 | Saga + 補償 | (罕見)強一致需求 → 2PC |
| Shard Key | Hash + Consistent Hashing | 多租戶 SaaS → Range |
| Sharding 時機 | 50TiB / 10k TPS / uncached read 需求 | < 1TB / < 1k TPS 不要分片 |
| Replication | Single-Leader + Semi-Sync | 多 DC → Multi-Leader;高可用寫入 → Leaderless |
| Read-After-Write | 從 primary 讀自己改的 | 追蹤 LSN(不要用時鐘) |
| 快取模式 | Cache-Aside + LRU + TTL | 寫密集 → Write-Behind;靜態媒體 → CDN |
| 快取失效 | 寫入時 delete cache |
不一致敏感 → 短 TTL + 接受最終一致 |
| 讀取擴展 | index → denormalize → replica → cache | 寫密集 → 寫入擴展;小規模不需要 |
| 寫入擴展 | 垂直選型 → sharding → queue → batching | 爆發 → queue;過載 → load shedding |
| Hot Key 寫入 | 拆 sub-key(可聚合 metrics) | 須原子資料(profile)不可拆 |
| 長時間操作 | async worker + queue(回 job ID) | 操作 > 幾秒;queue 深度做 backpressure |
| 任務防重複 | Idempotency Key | poison message → DLQ |
| 大型檔案傳輸 | Presigned URL 直傳 + CDN download | > 10MB;< 10MB 用一般 API |
| 上傳狀態同步 | Storage 事件 + 對帳 | 不要信任 client 通知 |
| 即時更新傳播 | Pub/Sub | 大量關聯狀態 → Consistent Hashing |
| WebSocket LB | L4 | L7 破壞持久連線 |
| 搜尋 | 獨立索引 + CDC(Elasticsearch) | 不要用 LIKE '%...%' |
| 搜尋相關性 | BM25 + Boosting + 業務指標 | autocomplete → Edge N-gram + Redis |
| LLM 注入知識 | RAG | 改行為/風格 → fine-tune |
| 資料管線架構 | 串流(Kappa) | 超大歷史分析(TB+)→ Lambda / 批次 |
| 管線容錯 | at-least-once + 冪等寫入 | 追求 exactly-once 代價高 |
| 資料轉換時機 | ELT(倉儲內轉換) | 需進倉前驗證 / 合規 → ETL |
| 資料庫選型 | 從 PostgreSQL 出發再說明偏離理由 | 極端寫入 → Cassandra;全球多寫 → CockroachDB/DynamoDB |
| 關聯式資料庫 | PostgreSQL(ACID+JSONB+全文+PostGIS) | 每秒數百萬寫 / 全球 active-active → 換 |
| KV / 文件 NoSQL | DynamoDB(託管、個位數 ms、可交易) | 複雜 JOIN/聚合 → 關聯式;避免鎖定 → 開源替代 |
| DynamoDB 一致性 | 最終一致(預設,0.5 RCU) | 需最新值 → 強一致(1 RCU,不支援 GSI) |
| DynamoDB 索引 | GSI(非主鍵屬性查詢) | 同分區換排序鍵 → LSI(僅建表時定義) |
| OLTP / OLAP | 分開建(OLTP + CDC/ETL → OLAP) | 幾十 TB 內 + 即時 + 團隊小 → HTAP |
| OLTP→OLAP 管線 | ETL 先起步 | 即時需求 → CDC(Debezium+Kafka);雲倉 → ELT+dbt |
| 搜尋引擎 | Elasticsearch(複雜搜尋/排序/分面) | 小量/簡單 → PostgreSQL 全文(GIN);< 10 萬筆不需要 |
| ES 深分頁 | search_after | 一致視角 → PIT cursor;不要用 from/size |
| 相似度搜尋 | 向量 DB(ANN, HNSW) | 已用 PG → pgvector;>100M → Pinecone/Milvus |
| 相似度 metric | Cosine(embedding 多 normalize) | binary → Hamming;要快 → Dot Product |
| 二進位資料儲存 | Blob Storage(S3)+ metadata 進 DB | < 幾 MB 且需 SQL 查詢 → 直接放 DB |
| Blob 存取控制 | 私有 Bucket + Presigned URL | 靜態網站才公開;全球讀 → + CDN |
| Blob 成本分層 | 生命週期策略(Standard→IA→Glacier) | 存取不可預測 → Intelligent-Tiering |
| 微服務對外入口 | API Gateway(路由+認證+限流+SSL終止) | 多差異客戶端 → BFF(各自 Gateway) |
| 認證 vs 授權 | Gateway 驗 JWT(authN) | 細粒度資源授權(authZ)留服務層 |
| 部署單位 | 容器(K8s + HPA) | 強隔離 / 不同 OS / legacy → VM |
| 服務狀態 | Stateless(狀態外移 Redis/DB/S3) | 必要持久 → StatefulSet / PersistentVolume |
| 運算模型 | 容器(持續/穩定負載) | 事件驅動+流量峰谷 → Serverless;> 15 分長任務 → Worker |
| Lambda 連 DB | RDS Proxy / PgBouncer 連線池 | 天生 serverless → DynamoDB(無連線概念) |
| Cold Start 緩解 | 小包 + 快語言 + 初始化移 handler 外 | 嚴格 P99 同步 API → Provisioned Concurrency |
| 何時引入 Queue | 需非同步/解耦/削峰時才加 | 同步、強延遲 SLA(< 500ms)→ 不要用 |
| 投遞語義 | at-least-once + consumer 冪等(去重) | exactly-once 幾乎做不到,別追求 |
| Kafka partition key | 選對 key 讓相關事件進同一 partition | 單一 key 爆量 → no key / salting / compound key |
| Kafka 持久化 | acks=all + replication factor 3 | 不可丟訊息時才開最強;先估吞吐再談 scaling |
| 分散式鎖選型 | 效率鎖 → Redis SET NX EX | 正確性 → ZooKeeper/etcd 臨時節點 + fencing token |
| 同一 DB 內競爭 | DB 交易(FOR UPDATE)/ 樂觀鎖 | 不要為單一 DB 上外部分散式鎖 |
| 協調服務選型 | 雲端託管 / etcd / Consul | 深度基礎設施題 / 強一致鎖 → ZooKeeper |
| ensemble 台數 | 3 / 5 / 7 奇數台 | 偶數只增成本不增容錯 |
| Cache key 分片 | Consistent Hashing + vNodes | 不要用 hash % N(擴縮容大量 miss) |
| 防 Cache Stampede | TTL jitter + 應用層 single-flight | 大量 key 同時過期、高流量回源 |
| Cache 高可用 | 每 shard 配 replica(最終一致) | cluster 全掛打垮 DB → 限流回源 + 降級 |
| 跨 region cache | 每區獨立 cluster,不跨區複製 | cache 可重建,failover 容忍 cold cache |
| Redis 定位 | 可重建的加速層,真實來源放持久化 DB | 要真耐久 → AWS MemoryDB |
| Pub/Sub vs Streams | 可容忍遺失 → Pub/Sub | 需可靠投遞/重播 → Streams / Kafka |
| 排行榜/滑動限流 | Redis Sorted Set(log N)+ Lua | 需即時排序或精準滑動視窗 |
| 靜態資產快取 | Hash busting + max-age=1年, immutable | 立即下架 → Purge API;HTML 入口 → 短 TTL / no-cache |
| CDN 高可用 | Multi-CDN + DNS 故障切換 + fallback Origin | 不押注單一 CDN |
| 單 DB 高 contention | Pessimistic Locking(FOR UPDATE) | 低 contention → OCC(單調遞增欄位當版本) |
| 跨多 DB 原子 | Saga(先講) | 要求嚴格強一致才提 2PC |
| 面向用戶競爭流程 | Distributed Lock + 預留機制(reservation) | 票務/電商/共乘,在 contention 前就預防 |
| 限流演算法 | Token Bucket(允許突發、貼近真實) | 嚴格控輸出 → Leaky Bucket;邊界精確 → Sliding Window |
| 分散式限流 | 集中式 Redis 計數器(INCR+EXPIRE/Lua) | 需極低延遲 → 本地計數器 + 定期同步 |
| auto-scaling 來不及 | Load Shedding + Request Prioritization | 上游支援背壓 → 優先 Backpressure 放慢 |
| 外部依賴超時 | Read timeout = 下游 P99 × 2~3 | 須遠小於整體鏈路 SLA |
| 重試策略 | 僅 5xx/網路錯重試 3~5 次 + 指數退避加 Full Jitter | 非冪等操作須先有冪等保護 |
| 下游故障保護 | 熔斷器 fail fast + 降級(serve stale/預設值) | 下游失敗率超閾值 |
| 故障排查順序 | Metrics 告警 → Traces 定位 → Logs 確診 | 生產系統故障排查標準流程 |
| 該監控哪些指標 | 四個黃金信號 Latency/Traffic/Errors/Saturation | 任何服務最基本監控(Google SRE) |
| 集中式日誌選型 | ELK Stack(全文索引) | 成本敏感 → Grafana Loki(只對標籤建索引) |
網路層次 → 網路層次與請求流程
| 層 | 協定 | 功能 |
|---|---|---|
| L3 網路層 | IP | 路由、定址 |
| L4 傳輸層 | TCP, UDP, QUIC | 端到端通訊、可靠性 |
| L7 應用層 | HTTP, DNS, WS, WebRTC | 應用程式通訊 |
Web 請求流程:DNS 解析 → TCP 三次握手 → HTTP 請求 → 伺服器處理 → HTTP 回應 → TCP 四次揮手
TCP vs UDP → 傳輸層協定 TCP vs UDP
| 特性 | TCP | UDP |
|---|---|---|
| 連線 | 面向連線 | 無連線 |
| 可靠性 | 保證交付 | 盡力而為 |
| 標頭 | 20–60 bytes | 8 bytes |
| 場景 | 幾乎所有情況(預設) | 串流、遊戲、VoIP |
瀏覽器只能透過 WebRTC 使用 UDP。
HTTP 方法與狀態碼 → HTTP 與 HTTPS
| 方法 | 語義 | 冪等 |
|---|---|---|
| GET | 取得 | ✅ |
| POST | 建立 | ❌ |
| PUT | 完整更新 | ✅ |
| PATCH | 部分更新 | ❌ |
| DELETE | 刪除 | ✅ |
| 碼 | 含義 |
|---|---|
| 200 / 201 | 成功 / 建立成功 |
| 301 / 302 | 永久 / 暫時重定向 |
| 401 / 403 | 未驗證 / 無授權 |
| 404 / 429 | 不存在 / 頻率過高 |
| 500 / 502 | 伺服器錯誤 / 閘道錯誤 |
API 範式 → API 範式比較、API 設計決策框架
| 範式 | 格式 | 場景 |
|---|---|---|
| REST | JSON | 外部 API(預設) |
| GraphQL | JSON | 前端靈活查詢、多團隊重疊資料 |
| gRPC | Protocol Buffers | 內部微服務(吞吐量 ~10x) |
策略:內部 gRPC + 外部 REST
決策樹:
External or Internal?
├── Internal ────────────► RPC / gRPC
└── External
└── Over/Under-fetching concern?
├── Yes ─────► GraphQL
└── No ─────► REST
即時通訊 → 即時通訊協定
| 協定 | 方向 | 底層 | 場景 |
|---|---|---|---|
| SSE | Server → Client | HTTP/TCP | 通知、事件推送 |
| WebSocket | 雙向 | TCP | 聊天、遊戲 |
| WebRTC | P2P | UDP | 音視訊通話 |
決策:SSE 夠嗎?→ 需要雙向?→ WebSocket → 需要 P2P 音視訊?→ WebRTC
負載平衡 → 負載平衡
| 類型 | 層級 | 路由依據 | 場景 |
|---|---|---|---|
| 客戶端 LB | — | 客戶端查詢 registry | 內部微服務、gRPC |
| L4 LB | 傳輸層 | IP/Port | WebSocket(必選) |
| L7 LB | 應用層 | URL/Header/Cookie | HTTP 流量(預設) |
演算法:無狀態 → Round Robin;長連線 → Least Connections;Session 持久 → IP Hash
降低延遲:靜態內容 → CDN;地理相關資料 → 區域分片
故障處理模式 → 故障處理模式
| 模式 | 解決 | 關鍵字 |
|---|---|---|
| 重試 + 指數退避 + 抖動 | 暫時故障 | exponential backoff + jitter |
| 冪等性 / 冪等鍵 | 重試副作用 | idempotency key |
| 熔斷器 | 級聯故障 | Closed → Open → Half-Open |
熔斷器狀態機:
Closed ──失敗超閾值──► Open ──逾時到期──► Half-Open
▲ │
└──────── 測試成功 ──────────────────────┘
測試失敗 → 回到 Open
Client-Server Architecture → 主從架構
| 角色 | 職責 |
|---|---|
| Client | UI、收集輸入、發請求、展示回應 |
| Server | 驗證授權、商業邏輯、讀寫 DB、回傳結果 |
Thin Client(SSR)vs Thick Client(SPA/App)— 現代預設 Thick + REST
C/S vs P2P — 音視訊通話才考慮 P2P
CAP Theorem → CAP 定理
| 組合 | 保證 | 犧牲 | 場景 |
|---|---|---|---|
| CP | 一致性 + 分區容忍 | 可用性 | 銀行、庫存、訂票 |
| AP | 可用性 + 分區容忍 | 一致性 | 社群動態、DNS、購物車 |
| CA | — | — | 現實中不存在 |
決策:「暫時不一致會造成嚴重後果嗎?」→ 是 → CP;否 → AP(預設)
Scalability → 可擴展性
| 策略 | 做法 | 上限 | 複雜度 | 適合時機 |
|---|---|---|---|---|
| Vertical Scaling | 升級單機規格 | 有物理限制 | 低 | 短期快速解法 |
| Horizontal Scaling | 增加機器 + LB | 理論無限 | 高 | 長期大規模成長 |
順序:先垂直,碰到上限或需高可用時再水平
水平擴展挑戰:Session 狀態、資料一致性(→ CAP)、LB SPOF
REST 要點 → REST 架構風格
| 動詞 | 冪等 | 用途 |
|---|---|---|
| GET | ✅ | 讀取 |
| POST | ❌ | 建立 |
| PUT | ✅ | 完整更新 |
| PATCH | 依設計(通常 ❌) | 局部更新 |
| DELETE | ✅ | 刪除 |
狀態碼:401(未認證)vs 403(無權限);201 Created(建立成功,搭 Location header)
參數:Path(指向資源)/ Query(篩選)/ Body(POST/PUT/PATCH 結構化資料)
反模式:POST /updateUser、GET /deleteUser、GET 帶 body
GraphQL 要點 → GraphQL 查詢語言
| 操作 | 對應 |
|---|---|
| Query | 讀取 |
| Mutation | 修改 |
| Subscription | 即時推送(通常 WebSocket) |
核心問題:
- N+1:batch resolver 用 DataLoader 合成
IN (...) - Cache 難:POST + 單一 endpoint → 用 persisted queries 取回 CDN cache
- 惡意查詢:用 query complexity / depth limit
gRPC 要點 → RPC 與 gRPC
- Protobuf 二進位序列化 → ~10x JSON 吞吐量
- IDL(.proto) 定義介面,生成跨語言 stub
- HTTP/2 → 四種模式:unary / server stream / client stream / bidirectional
- 相容規則:新欄位用新 tag、刪除欄位
reserved、不改型別 - 陷阱:面試不要過早跳 gRPC;瀏覽器需 gRPC-Web
API Security → API 安全
AuthN vs AuthZ:「你是誰」vs「你能做什麼」
| 方式 | 類型 | 典型場景 |
|---|---|---|
| API Key | AuthN | 內部 / 低敏感 API |
| JWT | AuthN | 公開 App 身份驗證 |
| OAuth 2.0 | AuthZ | 第三方授權 |
| mTLS | AuthN | 內部微服務(雙向) |
| RBAC | AuthZ | 公司內部管理(角色) |
| ABAC | AuthZ | 金融 / 政府(屬性) |
| Scope | AuthZ | OAuth token 粒度控制 |
- JWT 放
Authorization: Bearer <token> - Access token 短期 + Refresh token
- 不要把敏感資料放 JWT payload(只有 base64,非加密)
Consistent Hashing → 一致性雜湊
核心問題:hash(key) % N 在 N 變動時會搬走幾乎所有 key。
解法:
- Hash Ring:節點與 key 映射到圓環,順時針找第一個節點
- Virtual Nodes:每節點多個位置 → 分佈均勻 + 可按硬體能力分配
搬遷量:hash % N → O(K);Consistent Hashing → O(K/N)。
觸發場景:Distributed Cache sharding、Cassandra/DynamoDB routing、Sticky Sessions、Rate Limiting、CDN edge routing。
索引結構決策 → 資料庫索引概論
| 需求 | 首選索引 |
|---|---|
| 通用查詢 / 範圍 / 排序 | B-Tree / B+Tree(預設) |
| 純等值查詢 | Hash Index(O(1)) |
| 寫多 / 時序 / log ingest | LSM Tree(Cassandra、RocksDB) |
| 地理鄰近搜尋 | Geohash / R-Tree / H3 / S2 |
| 全文關鍵字檢索 | Inverted Index(Elasticsearch/Lucene) |
B-Tree 要點 → B-Tree 索引
- 平衡多叉樹,葉節點距離相等
- B+Tree:只葉節點存資料 + 葉節點間 linked list → 範圍查詢更快
- InnoDB / PostgreSQL / MongoDB 都用 B+Tree 或近似變體
LSM Tree 要點 → LSM Tree
寫入:WAL → MemTable(SkipList)→ SSTable flush → Compaction
- 把隨機寫變順序寫 → 寫入吞吐極高
- 查詢用 Bloom Filter 跳過 SSTable
- 代價:寫放大 + 讀取可能多層
Hash Index 要點 → 雜湊索引
hash(key) → bucket→ O(1) 等值查詢- 碰撞處理:Chaining or Open Addressing
- 不支援範圍、排序、前綴
Geospatial 要點 → 地理空間索引
| 技術 | 特色 |
|---|---|
| Geohash | 2D→1D 字串,用 B-Tree 前綴 |
| Quadtree | 固定切 4 等份(遊戲、GIS 可視化) |
| R-Tree | 彈性可重疊 MBR(SQL 空間索引標準) |
| S2 | 地球→立方體→4 邊形 cell(地圖切片) |
| H3 | 地球→二十面體→6 邊形 cell(Uber 鄰近搜尋) |
Inverted Index 要點 → 倒排索引
- Term Dictionary + Posting List
- Posting 含 Doc ID、TF、positions(phrase query 用)
- 應用:Elasticsearch、Lucene、PostgreSQL FTS、MySQL FULLTEXT
Database Transactions → 資料庫交易
ACID:Atomicity / Consistency / Isolation / Durability
四種隔離等級
| 隔離等級 | Dirty | Non-repeat | Phantom | 預設於 |
|---|---|---|---|---|
| Read Uncommitted | ✅ | ✅ | ✅ | 幾乎不用 |
| Read Committed | ❌ | ✅ | ✅ | PostgreSQL |
| Repeatable Read | ❌ | ❌ | ✅ | MySQL InnoDB |
| Serializable | ❌ | ❌ | ❌ | 金融 |
並發異常與解法
- Dirty Read:讀到未 commit 資料
- Non-repeatable Read:同 row 值變了
- Phantom Read:範圍查詢 row 數變了
- Lost Update(重要!):兩交易同時改 → 後寫覆蓋前寫
- 解:Optimistic Locking(version 欄位)或 Pessimistic Locking(
SELECT FOR UPDATE)
- 解:Optimistic Locking(version 欄位)或 Pessimistic Locking(
- 超賣本質是 Lost Update:原子
UPDATE qty = qty - 1 WHERE qty > 0即可,不要動隔離等級
分散式交易
- 2PC:強一致但脆弱(coordinator 崩潰會卡死)
- Saga:本地交易 + 補償,現代微服務主流
ACID 的 C 是「商業 constraint」,CAP 的 C 是「副本同步」。完全不同。
Sharding → 資料分片
Shard Key 三條件
- 高基數(cardinality)
- 均勻分佈
- 契合查詢模式
三種策略
| 策略 | 優點 | 缺點 |
|---|---|---|
| Range | 支援範圍查詢 | 容易熱點(如 created_at) |
| Hash(預設) | 分佈均勻 | 擴容大搬資料 → 用 Consistent Hashing |
| Directory | 靈活 | SPOF + 多一次 lookup |
三大挑戰
| 挑戰 | 解法 |
|---|---|
| Celebrity Hot Spot | 隔離到專屬 shard / 複合 key hash(uid+date) |
| 跨 shard 查詢 | 快取 / 反正規化 / 背景預計算 |
| 跨 shard 一致性 | 設計成同用戶資料同 shard → 避免 / Saga / 接受最終一致 |
1TB 以下、< 10k TPS 寫入幾乎都不需要分片。先 index → cache → replica → 升級硬體 → 才談 sharding。
Replication → 資料複寫
三大架構
| 架構 | 適用 | 主要挑戰 |
|---|---|---|
| Single-Leader | 大多數讀取密集應用 | Replication Lag、Failover |
| Multi-Leader | 多 DC、離線編輯 | 寫入衝突 |
| Leaderless | 高可用寫入、最終一致 | Quorum 一致性、版本合併 |
Replication Lag 三大不一致
| 問題 | 解法 |
|---|---|
| Read-After-Write | 自己改的從 primary 讀 / 追蹤 LSN(不要用時鐘) |
| Monotonic Read | 同用戶總是讀同一 replica(hash(user_id) 路由) |
| Consistent Prefix | 有因果關係的寫入放同一 partition / version vector |
Failover 三大坑
- 非同步資料遺失 → 半同步 + 選資料最新的 follower
- Split Brain → STONITH / Fencing Token / Raft consensus
- Timeout 拿捏(太長復原慢、太短誤觸發)
Quorum(Leaderless)
公式:w + r > n → 讀寫節點必有重疊。
常見 n=3, w=2, r=2(容忍 1 個失效)。
Sloppy Quorum + Hinted Handoff:寫到「非家節點」暫存,網路恢復後送回家 → AP 配置。
Caching → 快取機制
快取位置(latency 由低到高)
In-Process(ns) < Redis 同區(< 1ms) < CDN(20–40ms)
四種模式
| 模式 | 寫入 | 適用 |
|---|---|---|
| Cache-Aside(預設) | App 寫 DB → delete cache | 通用 |
| Write-Through | App 寫 cache → cache 同步寫 DB | 讀必新鮮 |
| Write-Behind | App 寫 cache → 背景非同步寫 DB | 高寫吞吐、可丟資料 |
| Read-Through | Cache 自己 miss 後查 DB | CDN 本質 |
淘汰策略
LRU 預設(90% 工作負載適合)+ TTL 防過時。LFU 適合長期熱門,FIFO 幾乎不用。
三大陷阱
| 問題 | 最有效解 |
|---|---|
| Cache Stampede | Request Coalescing(Single Flight) |
| Cache Consistency | 寫入時 delete + 適度 TTL |
| Hot Key | 複製到多節點(TTL 錯開)+ in-process 備援 |
面試五步驟
- 確認瓶頸 → 2. 決定快取什麼 → 3. 選架構(預設 Cache-Aside)→ 4. 淘汰策略(LRU+TTL)→ 5. 說缺點(失效 / 故障 / Stampede)
Numbers to Know → 系統設計關鍵數字
核心量級
| 元件 | 關鍵指標 | Scale Trigger |
|---|---|---|
| Cache(Redis) | < 1ms、100k+ ops/sec、1TB 上限 | hit < 80% / latency > 1ms |
| Database | 50k TPS 讀 / 10–20k TPS 寫 / 64TiB | 50TiB / 10k TPS 寫 / uncached < 5ms |
| App Server | 100k+ 連線 / 8–64 核 / 64–512GB | CPU > 70% / 頻寬 ≈ 20Gbps |
| Kafka Broker | 1M msg/sec / 1–5ms / 50TB / 週月保存 | 800k msg/sec / 200k partition |
Latency 量級直覺
memory ≪ disk ≪ network
- Memory(in-process):ns
- Memory(Redis 同區):< 1ms
- Disk(DB cached):1–5ms
- Disk(DB uncached):5–30ms
- Network(跨區):10–100ms+
過早 sharding 是頭號錯誤 —— < 1TB / < 1k TPS 通常不需要。
Scaling Reads → 讀取擴展
演進順序:index → denormalize / materialized view → read replica → cache(app + CDN)
| Deep Dive | 解法 |
|---|---|
| query 變超慢 | 加 index(複合 index 注意欄位順序) |
| hot key 幾百萬讀 | Request Coalescing + Cache Key Fanout |
| cache 過期打爆 DB | Probabilistic Early Refresh / 主動刷新 |
| 更新需立刻反映 | Cache Versioning(key 帶版本,免 race) |
Cache invalidation:TTL / write-through / write-behind / tagged / versioned keys
Scaling Writes → 寫入擴展
四策略:垂直選型 → sharding/partitioning → queue + load shedding → batching + 階層聚合
- DB 選型:Cassandra(append-only,10k+ 寫/秒)vs MySQL(B-tree update,~1k)
- Partition key:高基數均勻(
hash(userID));爛 key(國家)→ shard 不均 - Horizontal sharding(分 row)vs Vertical partitioning(分 column)
- 爆發:Queue 吸收(短暫才用,會掩蓋問題)/ Load Shedding(丟最不重要的)
- Hot key 壓垮 shard:拆 sub-key(只適用可聚合 metrics)
- Resharding 不停機:dual-write 雙寫 + 讀新 shard
Long-Running Tasks → 長時間執行任務
核心:web server 回 job ID(ms) + worker pool 處理。queue 只放 job ID。
| 故障 | 解法 |
|---|---|
| worker 崩潰 | heartbeat 偵測 → 重試 |
| job 一直失敗 | DLQ(3~5 次後隔離 + 監控) |
| 重複提交 | Idempotency Key |
| queue 暴增 | Backpressure(依 queue 深度 擴展,非 CPU) |
| 長短 job 混 | 分 fast / slow queue(避免 head-of-line) |
| 依賴鏈 | 帶 context 串接 / orchestrator(Step Functions、Temporal) |
Queue 選型:Kafka(安全預設)/ SQS / RabbitMQ / Redis+Bull
Handling Large Blobs → 大型檔案處理
10MB → Blob Storage(S3)。Presigned URL 直傳 + CDN download,server 不碰 bytes。
- 限制烘焙進簽名:
content-length-range、content-type - 斷點續傳:Multipart Upload(S3 5MB+/塊)+
ListParts續傳 - 狀態同步:Storage 事件(主)+ 對帳(安全網),別信任 client 通知
- 下載:CDN + Range Request(大檔案斷點續傳)
- 防濫用:quarantine bucket 掃描通過才可存取
Real-time Updates → 即時更新
兩個 hop:① client-server 協定 ② server 端傳播
第一 hop(協定):
| 協定 | 方向 | 何時用 |
|---|---|---|
| Polling | client 拉 | 不在意延遲(基準) |
| SSE | server → client | 單向推送 |
| WebSocket | 雙向 | 高頻雙向(L4 LB) |
| WebRTC | P2P | 音視訊通話 |
第二 hop(傳播):Pull(DB)/ Consistent Hashing(大量關聯狀態)/ Pub/Sub(廣播首選)
重連:heartbeat 偵測殭屍連線 + 序列號補發遺漏(Redis Stream)
Search System → 搜尋系統
不用 LIKE。獨立搜尋索引 + CDC + Kafka 非同步同步。
- 倒排索引(詞 → 文件)+ 文字分析(斷詞 / lowercase / stop word / stemming)
- Indexing pipeline:CDC(推薦) > 雙寫(非原子、易不一致)
- 排序:BM25(TF 有上限 / IDF 越罕見越高)+ Boosting(
name^3)+ 業務指標 - Autocomplete:Edge N-gram + Redis(100ms 內)
- Faceted Search:Aggregation API(一次回結果 + 計數)
- Shard 數建立後不可改(10~50GB/shard);零停機 Reindex 用 alias
RAG → 檢索增強生成 RAG
解 foundation model 限制:cutoff / 缺領域深度 / 缺私有資料 / 無法引用(hallucination 是症狀)
四元件:Ingestion → Retrieval → Augmentation → Generation
- Ingestion:chunking → embedding → vector DB(offline)
- Retrieval:Hybrid Search(dense semantic + sparse lexical)+ reranking
- Augmentation:query + context 組 prompt,「不知道就說不知道」降 hallucination
- vs fine-tune / 長 context:RAG 划算、可引用來源、知識即時、獨立調整
- Agentic RAG:agent 當 orchestrator(構建 query、驗證 context)
Data Pipeline → 資料管線設計
核心決策:批次 vs 串流(由延遲容忍度決定,< 10 分必串流)
| Batch | Stream | |
|---|---|---|
| 框架 | Spark(中間結果留記憶體) | Kafka + Flink |
| 適合 | 報表、ML 訓練、帳單 | 詐欺、即時儀表板、告警 |
- 架構:Kappa(單套串流,主流)vs Lambda(批+串雙管線,超大歷史分析)
- 轉換:ELT(倉儲內轉換,現代首選)vs ETL
- 三模式:CDC / Fan-out / Enrichment
- 容錯:at-least-once + 冪等寫入;Watermark 處理遲到事件(event time)
- 倉儲:Data Warehouse(schema-on-write)/ Data Lake(schema-on-read)/ Lakehouse
資料庫總覽與選型 → 資料庫總覽與選型
兩個正交維度看全景:資料模型(table / document / KV / wide-column / graph)× 工作負載(OLTP / OLAP)。
| 模型 | 代表 | 適用 |
|---|---|---|
| Relational (ACID) | PostgreSQL / MySQL | 複雜關係、強一致、JOIN |
| Key-Value | Redis / DynamoDB | 超低延遲、快取、Session |
| Document | MongoDB | schema 靈活演進 |
| Wide-Column | Cassandra(BASE) | 高寫吞吐、時序、無單點 |
| Graph | Neo4j | 高度連結、多跳查詢 |
| Vector | Pinecone / pgvector | 相似度搜尋(非精確查詢) |
選型三問:① 資料形狀/查詢模式 → ② OLTP or OLAP → ③ 規模與一致性取捨。別一開始就背「SQL vs NoSQL」。
MVP / 純快取 / 純檔案 → 不要過度工程(SQLite、Redis、Blob Storage 各司其職)。
PostgreSQL → PostgreSQL
- 索引:B-tree(預設、等值/範圍/排序);GIN(全文 tsvector、JSONB);PostGIS/GiST(地理);涵蓋索引
INCLUDE(免回表);部分索引WHERE(只索引子集) - 豐富功能常省掉額外系統:GIN 全文搜尋 ≈ 取代 Elasticsearch(簡單需求);JSONB ≈ 取代 MongoDB;PostGIS ≈ 地理空間 DB
- 寫入路徑:buffer + WAL(記憶體)→ commit 時 WAL fsync 落盤 → 背景寫髒頁 → 索引更新。單核 ~5k INSERT/s、~1–2k UPDATE/s
- 寫入擴展:垂直 → 批次 → write offloading(Kafka)→ 表分區 → sharding(無內建,需 Citus)
- 並發競態(拍賣出價):Read Committed 下兩交易讀同一 maxBid →
SELECT … FOR UPDATE(列鎖) 或 Serializable(需重試) - 複製:同步(強一致、慢)/ 非同步(快、有 lag);讀取擴展 read replica;read-your-writes → 剛寫的讀 primary;failover 提升 replica
| 隔離等級 | Dirty | Non-repeat | Phantom |
|---|---|---|---|
| Read Committed(預設) | ❌ | ✅ | ✅ |
| Repeatable Read | ❌ | ❌ | ❌(PG 特有,比標準強) |
| Serializable | ❌ | ❌ | ❌ |
何時偏離 PG:極端寫入(→ Cassandra)/ 全球多寫 active-active(→ CockroachDB/DynamoDB)/ 純 KV(→ Redis)。
DynamoDB → DynamoDB
- 全託管 NoSQL KV、schema-less、個位數 ms(DAX → 微秒)
- 主鍵:Partition Key(hash → 決定分區)+ Sort Key(分區內 B-tree 範圍/排序);底層 = 中心化 hash 分區 + 分區內 B-tree
- 每請求選一致性:最終(預設、0.5 RCU)/ 強(
ConsistentRead=true、1 RCU、不支援 GSI) - 交易:
TransactWriteItems,跨表最多 100 item,可序列化隔離 - 容量:1 RCU=4KB 強讀(或 2 次最終讀);1 WCU=1KB 寫;每分區上限 ~3000 RCU / 1000 WCU
- DAX(讀寫快取,直連 DynamoDB 的寫才自動失效)、Streams(CDC → ES/Lambda/分析)、Global Tables(跨區)
| 索引 | 分區鍵 | 大小 | 吞吐 | 一致性 | 建立 | 上限 |
|---|---|---|---|---|---|---|
| GSI | 不同 | 無限 | 獨立 | 僅最終 | 隨時 | 20 |
| LSI | 同 | 10GB/分區 | 共用 | 最終+強 | 僅建表時 | 5 |
OLTP vs OLAP → OLTP vs OLAP
| 維度 | OLTP | OLAP |
|---|---|---|
| 目標 | 快速個別交易 | 大規模聚合分析 |
| 查詢 | 點查詢、小範圍 | 全表掃描、GROUP BY |
| 儲存 | Row-oriented | Column-oriented |
| Schema | 正規化 | 星型 / 雪花 |
| 延遲 | 毫秒 | 秒~分鐘 |
| 代表 | PostgreSQL / DynamoDB | BigQuery / ClickHouse / Snowflake |
column 對分析快三因素:① 只讀需要欄位(I/O 省 90%+)② 同型別高壓縮(字典編碼)③ 向量化 SIMD。
連接管線:ETL(先起步、簡單可靠有延遲)/ CDC(Debezium+Kafka,近即時、複雜)/ ELT+dbt(雲倉現代主流)。HTAP(TiDB/SingleStore)省管線但兩邊妥協。
Elasticsearch → Elasticsearch
- 概念:document / index / mapping / field;
keyword(不分詞、像 hash)vstext(分詞、走 inverted index);nested 正規化取捨;_version樂觀鎖 - 底層:Lucene 之上的分散式協調層;Node 五型(master / data / coordinating / ingest / ML);routing =
hash(_id) % shards;shard × replica → 吞吐 X×Y - Lucene segment 不可變:更新 = soft delete + 插新 doc,merge 才清 → 不適合高頻更新
- segment 內:inverted index(哪些 doc 符合)+ doc values(欄式,排序/聚合用);query planner 用統計選 term 交集順序
- 分頁:from/size(深分頁貴)→ search_after → PIT cursor(一致視角)
- 限制:別當唯一 DB / source of truth、讀多寫少、最終一致、反正規化、CDC 同步權威來源
向量資料庫 → 向量資料庫
- embedding:128–1536 維陣列表示語意;相似度 Cosine(多 normalize、常見)/ L2 / Dot / Hamming(binary)
- KNN O(n) 太貴 → ANN:在 recall / latency / memory 三角平滑取捨
| 索引 | 概念 | 優 | 缺 |
|---|---|---|---|
| HNSW(主流) | 高維 skip list 多層 graph | O(log n)、95%+ recall、低延遲 | 記憶體 ~×2、建索引慢、插入貴 |
| IVF | k-means 分群 + nprobe | 建索引快、記憶體小 | recall 較低 |
| LSH | hyperplane 雜湊分桶 | 建索引快、適合 streaming | 實務 recall 較低 |
- filter:pre-filter(可能套不進索引)vs post-filter(可能不足 K);hybrid(BM25 + vector)
- 選型階梯:先 pgvector / ES kNN / Redis VSS → 規模 >100M 才上 Pinecone / Weaviate / Milvus / Qdrant
- Numbers:1536 維 float32 ≈ 6KB/向量;HNSW 索引再 ×2;查詢 <10ms;recall 95%+
- 陷阱:非交易型(別當 source of truth)、embedding drift(換模型要重建)、cold start、索引建構慢
物件儲存(Blob Storage) → 物件儲存
| 類型 | 存取單位 | 修改 | 適用 |
|---|---|---|---|
| File | 路徑 | 就地修改 | NFS / EFS |
| Block | block 位址 | 隨機讀寫 | DB / VM 磁碟(EBS) |
| Object | key(取整個物件) | 不可變(整份替換) | S3 / GCS / Azure Blob |
- 耐久性 11 個 9(跨 ≥3 AZ 冗餘)≠ 可用性 99.99%(當下能否存取)
- 分層 Standard → IA → Glacier(越便宜取回越貴)+ 生命週期策略 自動降級
- 安全:私有 Bucket + Presigned URL + Block Public Access + 最小權限 IAM;版本控制(防誤刪/回滾);CRR(非同步、DR/合規/讀延遲)
- 角色:DB 存 metadata + Blob 存內容;資料管線中繼(S3 event → Lambda);靜態資源 + CDN;Data Lake(Parquet + Athena)
API Gateway → API 閘道
- 微服務統一入口,集中橫切關注點:路由 / 認證(JWT) / 限流 / SSL 終止 / 請求-回應轉換 / 請求聚合 / 快取
| Load Balancer | API Gateway | |
|---|---|---|
| 層次 | L4 / L7 | L7 |
| 職責 | 流量分散、高可用 | 路由、認證、限流、轉換 |
| 懂業務 | 否 | 是 |
| 產品 | ALB / NLB、Nginx | AWS API GW、Kong、Envoy |
- SPOF → 多實例 + 前掛 LB;限流計數器 → 共享 Redis
- authN 在 Gateway(驗 JWT 簽名)/ 細粒度 authZ 在服務
- BFF:為 Web / Mobile / 第三方各維護一個 Gateway。別把業務邏輯塞爆 Gateway(→ 第二個 monolith)
負載平衡器(基礎設施) → 負載平衡器
- 功能:流量分配(最大化吞吐、避免局部過載)/ 健康檢查(含依賴)/ HA failover(VIP/anycast)/ SSL 終止 / Sticky Session(過渡,應外移 session)/ Global LB(DNS/Anycast)
- 演算法:Round Robin(預設)/ Least Connections(長連線)/ IP Hash(黏性)/ Weighted RR(混合規格)
- L4(WebSocket/長連線)vs L7(一般 HTTP,靈活路由)
- 面試:只在入口畫一個 LB 或省略只說「水平擴展」。網路層細節見 負載平衡
容器化與編排 → 容器化與編排
| 虛擬機器 | 容器 | |
|---|---|---|
| 隔離 | 完整 kernel | 行程層(共用 kernel,namespace/cgroups) |
| 啟動 | 幾分鐘 | 幾秒/幾百 ms |
| 記憶體 | 幾 GB | 幾十~幾百 MB |
| 適合 | 強隔離、跑不同 OS、legacy | 微服務、快速擴展、高密度 |
- Docker:Image(唯讀藍圖)/ Container(執行實例)/ 分層快取 / Registry
- K8s:Pod(最小單位)/ Deployment(維持 N 個 Pod)/ Service(穩定端點)/ HPA(自動擴展);滾動更新零停機
- Stateless(狀態外移 Redis/DB/S3/ConfigMap);liveness(活著嗎→重啟)vs readiness(能收流量嗎→移出 Service)probe
無伺服器運算(Serverless) → 無伺服器運算
- FaaS(Lambda,事件觸發、按毫秒計費)vs BaaS(Firebase/Auth0/S3)。面試講 Serverless 通常指 FaaS
- Cold Start(分配容器+初始化,幾百 ms~幾秒)vs Warm Start(保溫 5–15 分,無額外延遲)
| VM | 容器(K8s) | Serverless | |
|---|---|---|---|
| 啟動 | 分鐘 | 秒 | ms~秒(含 cold start) |
| 閒置成本 | 高 | 中 | 零 |
| 執行上限 | 無 | 無 | 15 分 |
| 計費 | 小時 | CPU/記憶體 | 毫秒 |
- 適合:流量不穩 / 事件管線 / 排程 / 邊緣。不適合:>15 分長任務 / 低延遲 P99 / 持續高流量(貴)/ 複雜狀態
- 模式:API GW + Lambda;DB 連線爆炸 → RDS Proxy/PgBouncer 或 DynamoDB;SNS fan-out
- Cold Start 緩解:快語言 + 小包 + 初始化移 handler 外 + Provisioned Concurrency。vendor lock-in 明顯
分散式快取 → 分散式快取
難點不在「快」,而在 cache 自己變成一個要設計與維運的分散式系統(sharding / replication / failover / 一致性 / 流量偏斜)。
| 問題 | 解法 | 取捨 / 為何 |
|---|---|---|
| key 如何分片 | Consistent Hashing + vNode | % N 擴縮容幾乎全 key 重映射→災難 |
| hot key(流量偏斜) | 多副本隨機讀 / 本地快取 / 拆邏輯 key | CH 只均勻分布,不解流量偏斜 |
| cache stampede | TTL jitter(源頭)+ single-flight(回源) | 大量 key 同時過期、高流量回源 |
| cluster 全掛 | replica + failover;限流回源 + 降級 | 90% 回源 → DB 瞬間 N 倍流量雪崩 |
| partial node 退化 | timeout + 重試上限 + circuit breaker | 變慢非 crash → retry 風暴更危險 |
| multi-region | 每區一套、不跨區複製 | cache 可重建,failover 容忍 cold |
Cache replication 用 eventual consistency 即可 —— cache 不是 source of truth,丟資料代價低。
Consistent Hashing ≠ 解 hot key:分布均勻不等於流量均勻。
Invalidation 以 TTL 為主、廣播失效為輔:漏訊息最多 stale 一段 TTL,不會永久錯。
Redis → Redis
記憶體中的資料結構伺服器,單執行緒保證命令原子,速度優先換微秒延遲與多用途瑞士刀。
| 用途 | 結構 / 命令 | 重點 |
|---|---|---|
| 快取 | String + SETEX / TTL |
可重建加速層,真實來源在持久化 DB |
| 分散式鎖 | SET NX EX + Lua check-and-del |
嚴格場景 Redlock + fencing token |
| 排行榜 | Sorted Set ZADD/ZREVRANGE |
log N 即時排序 |
| 滑動視窗限流 | Sorted Set(timestamp 當 score)+ Lua | 固定視窗用 INCR+EXPIRE |
| 可靠佇列 | Streams + consumer group | 至少一次 + XCLAIM 接手 |
| 即時推播 | Pub/Sub | at-most-once 不持久化,離線必丟 |
| 部署模式 | 解決 | 限制 |
|---|---|---|
| 單節點 | 最簡單 | 無容錯、無擴展 |
| HA Replica | 讀分流 + 容錯 | 寫仍集中 primary;async 故障切換掉資料 |
| Cluster | 16384 slot 水平擴展 | 預設僅單鍵;跨鍵需 hash tag {} |
耐久性是取捨:RDB 兩快照間掉資料、AOF everysec 最多掉 1 秒;要真耐久用 AWS MemoryDB。
單執行緒陷阱:一條 O(N) 大命令(KEYS *)卡全場,用 SCAN 取代。
Pub/Sub 會丟、Streams 可重播:需可靠投遞別用純 Pub/Sub。
訊息佇列 → 訊息佇列
Queue 是緩衝層,買到非同步 / 解耦 / 削峰填谷;代價是最終一致、亂序、重複投遞,且它不增加系統容量,只是把過載往後推。
| 決策 | 預設選擇 | 條件 / 取捨 |
|---|---|---|
| 何時引入 | 需非同步/解耦/削峰時才加 | 同步、強延遲 SLA(< 500ms)不要用 |
| 投遞語義 | at-least-once + consumer 冪等 | exactly-once 幾乎做不到,靠去重模擬 |
| 重複投遞為何發生 | ack 在處理後丟失 → broker 超時重投 | 用 message_id 去重表攔截 |
| 過載堆積 | backpressure:回壓 / 限流 / 429 | 平均到達率 > 處理率時加 worker 沒用 |
| 失敗訊息 | 重試 N 次 → DLQ + 告警 | 一條毒訊息不阻塞正常流量 |
| RabbitMQ vs Kafka | 靈活路由/任務隊列 → RabbitMQ | 高吞吐可重播 log → Kafka |
Queue 不是銀彈:解決時間不均與耦合,不解決整體吞吐不足。
多 consumer 必失序:靠 partition key 路由 + 單 consumer 保序,代價是該 key 吞吐受限。
Kafka → Kafka
分散式 append-only commit log,可同時當可水平擴展的 message queue 與可重播的 event stream。一句話:always available, sometimes consistent(AP)。
| 名詞 | 一句記憶 |
|---|---|
| Topic | 邏輯分組(組織資料) |
| Partition | 實體分片(擴展 + 保證順序);順序只在 partition 內 |
| Offset | consumer 記「讀到哪」 |
| Consumer Group | 一個 partition 組內只給一個 consumer |
| 決策 | 預設選擇 | 條件 |
|---|---|---|
| 相關事件按序 | 選對 partition key 進同一 partition | hash(key) % num_partitions |
| 持久化保證 | acks=all(等所有 ISR)+ RF 3 | 不可丟訊息 |
| hot partition | no key / salting / compound key / 背壓 | 單一 key 流量爆量 |
| 要不要談 scaling | 先估吞吐:單 broker ~1TB、~100萬則/秒 | 不超過量級可能不必談 |
| consumer 重試 | 自建 retry topic + DLQ | Kafka 無內建 consumer 重試(SQS 有) |
順序保證只在單一 partition 內,非整個 topic。
預設 at-least-once:commit 前掛會重複 → 下游冪等或 transactional API。
Anti-pattern:大檔塞 Kafka;應存 S3,topic 只放指標訊息。
分散式鎖 → 分散式鎖
讓多台機器對共享資源互斥。核心難點不是上鎖,而是「持鎖節點當機如何安全釋放」與「鎖過期但節點以為仍持鎖」。第一個該問:真的需要鎖嗎?
| 實作 | 一致性 | 自動釋放 | 適用 |
|---|---|---|---|
| Redis(TTL) | 弱(AP) | TTL 到期 | 效率鎖、已有 Redis |
| ZooKeeper/etcd | 強(CP) | session 斷則節點消 | 正確性、強一致 |
| DB 鎖 | 強(交易) | commit/連線斷 | 單一 DB 內 |
| K8s replicas:1 | N/A(無競爭) | N/A | 簡單、放棄高可用 |
效率鎖 vs 正確性鎖:效率 → Redis SET NX EX 夠;正確性 → fencing token(單調遞增,資源拒收較舊 token)+ 共識儲存。
釋放不能裸 DEL:寫唯一 token,Lua 原子 check-and-delete,否則誤刪別人的鎖。
臨界區比 TTL 久:用「安全 TTL 上界 + fencing token」而非靠 watchdog 續租。
同一 DB 內競爭別上外部鎖:優先 FOR UPDATE 或樂觀鎖(version + CAS)。
ZooKeeper → ZooKeeper
強一致、高可用的分散式協調服務(非資料庫):ZNode + ensemble + watches 組出服務發現、設定管理、leader 選舉、分散式鎖。讀多寫少、資料 < 1MB、CAP 選 CP。
| primitive | 作用 |
|---|---|
| ZNode(資料) | persistent(設定)/ ephemeral(存活)/ sequential(排序+鎖+選舉) |
| ensemble | 3/5/7 奇數台多數決;3→容忍1、5→容忍2、7→容忍3 |
| watches | ZNode 變動一次性回呼(取代輪詢 / n² 廣播) |
| 決策 | 選擇 | 條件 |
|---|---|---|
| 選協調服務 | 一般題 → 雲端託管 / etcd / Consul | 深度基礎設施題 / 共識大腦 → ZK |
| 分散式鎖 | 正確性/長鎖/階層 → ZooKeeper | 高吞吐/短鎖/簡單 → Redis(Redlock) |
| ensemble 台數 | 3 / 5 / 7 奇數 | 偶數只增成本不增容錯 |
ephemeral 是殺手鐧:session 結束自動刪 → 免費故障偵測,由 ensemble 統一裁決「誰死了」。
leader 選舉避免羊群效應:只 watch 序號小一號的節點。
follower 讀可能 stale:要最強一致先 sync。
Kafka 已從 ZooKeeper 遷 KRaft(內建共識取代外部協調)。
內容傳遞網路(CDN) → 內容傳遞網路
地理分散的快取網路,把內容複製到離使用者最近的 Edge,用空間換時間降延遲並把流量擋在源站外。本質是分散到全球的 read-through cache。
| 內容類型 | 快取策略 | 為何 |
|---|---|---|
| JS/CSS(hash 在檔名) | max-age=1年, immutable |
改檔即改 URL,舊快取自然作廢 |
| 圖片/影片 | 長 TTL + 需要時 Purge API | 違規/洩漏需即時下架 |
| HTML 入口 | 短 TTL 或 no-cache | 入口頁需指向最新帶 hash 資產 |
| 失效機制 | 取捨 |
|---|---|
| Hash Busting(首選) | 最乾淨,可搭超長 immutable TTL |
| Purge API | 即時但全球傳播需時間、大量 purge 致回源尖峰 |
| Stale-While-Revalidate | 使用者不等待,代價是短暫看到舊內容 |
別用短 TTL 求即時:摧毀 hit ratio、打爆源站;正解是 immutable + hash busting。
Cache Hierarchy(Origin Shield):收斂數百 Edge 的回源,把源站 QPS 從 Edge 數量級降到物件數量級。
CDN SPOF:Multi-CDN + DNS 故障切換 + fallback Origin(源站要能直接服務)。
動態內容也能加速(就近 TLS、骨幹路由、連線重用),但每人不同的回應不可快取,別在所有流量前都畫 CDN。
處理競爭 → 處理競爭
多個 process 搶同一資源造成 race condition。心法是複雜度遞進:能塞進單一 DB 就用 pessimistic/optimistic,不行才上分散式協調。
| 情境 | 選擇 | 複雜度 |
|---|---|---|
| 單一 DB、高 contention | Pessimistic Locking(FOR UPDATE) |
低 |
| 單一 DB、低 contention | Optimistic Concurrency(自然版本) | 低 |
| 需自動偵測衝突 | Isolation = SERIALIZABLE | 低 |
| 多 DB、必須強一致原子 | 2PC | 非常高 |
| 多 DB、要韌性可接受最終一致 | Saga | 高 |
| 面向用戶競爭流程 | Distributed Lock + 預留機制 | 中 |
Atomicity 擋不住 race:transaction 只保證自身內部,擋不住別人同時讀到一樣的資料。
OCC 版本號用單調遞增欄位(如 review_count)避免 ABA。
黃金法則:盡量把有 contention 的資料放同一個 DB,避開整個分散式協調。
Hot partition / 名人問題:先質疑能否改變問題;真需強一致用 queue-based serialization(單 worker)。
別過度設計:簡單 row lock / OCC 就夠時別硬上 distributed lock。
過載保護 → 過載保護
核心是讓系統在壓力下優雅降級而非全面崩潰(10 倍流量下還能服務 30%)。層層疊加的多層防線,每層擋的東西不同。
| 層次 | 手段 | 擋什麼 |
|---|---|---|
| 預防 | Rate / Concurrency Limiting | 防濫用、保護後端資源 |
| 吸收 | Queue-based Load Leveling | 平滑瞬間峰值(不拒絕、延後) |
| 擴容 | Auto-scaling | 從根本增加容量 |
| 自保 | Load Shedding + Prioritization | 都跟不上時主動丟棄部分請求 |
| 隔離 | Bulkhead | 局部過載不蔓延成全面崩潰 |
| 協同 | Backpressure | 壓力訊號沿鏈路向上傳播 |
| 限流演算法 | 特性 | 適用 |
|---|---|---|
| Token Bucket(預設) | 允許突發、貼近真實 | 通用最常用 |
| Leaky Bucket | 強制平滑、不允突發 | 嚴格控制對外輸出速率 |
| Sliding Window | 邊界精確 | 邊界突發敏感 |
| Fixed Window | 最簡單 | 有邊界突發(跨窗 2 倍量) |
Rate ≠ Concurrency limiting:前者管每秒幾個、後者管同時處理中的數量(更貼近資源)。
分散式限流:集中式 Redis 計數器(INCR+EXPIRE/Lua);被限流回 429 + Retry-After。
擴容快、縮容慢防振盪;空窗靠預測擴容 + load shedding + 佇列緩衝。
Load Shedding(丟不丟)vs Prioritization(丟誰)vs Backpressure(放慢不丟)。
可靠交付 → 可靠交付
故障是常態。由細到粗、層層疊加的防線:超時 → 重試 → 冪等性 → 退避加抖動 → 故障切換 → 降級。目標不是防故障,而是讓故障時優雅應對、自動恢復、不放大災情。
| # | 防線 | 解決 | 前提 / 代價 |
|---|---|---|---|
| 1 | Timeout | 卡住依賴拖垮自己(級聯) | Read timeout = 下游 P99×2~3 |
| 2 | Retry | 暫時性故障(5xx/網路) | 只重試暫時錯 + 需冪等 |
| 3 | Idempotency | 重試的重複副作用 | 冪等鍵(POST)/ 去重表 |
| 4 | Backoff + Jitter | 驚群效應(同步重試脈衝) | Full Jitter 最常推薦 |
| 5 | Failover | 節點/DB 永久掛 | 切換 downtime、可能丟資料 |
| 6 | Fallback + 熔斷器 | 能力暫不可用還要能服務 | serve stale / 預設值 |
at-least-once + 冪等 Consumer + 去重表 = 等效 exactly-once(不需真 exactly-once)。
該重試 vs 不該:5xx/網路重試;4xx/業務錯誤/非冪等不重試;上限 3~5 次。
熔斷器三狀態 Closed → Open → Half-Open(探針成功逐步放量)。
Failover(找健康同類)vs Fallback(用簡陋替代撐過去)。
可觀測性 → 可觀測性
從外部輸出推斷內部狀態。三支柱回答三個不同問題,互補不替代;並用 SLI/SLO/SLA + Error Budget 把可靠性量化。
| 支柱 | 回答 | 形式 | 擅長 |
|---|---|---|---|
| Metrics | 系統狀態如何? | 數值+時序 | 告警、趨勢 |
| Logs | 這事件發生什麼? | 文字事件 | debug 確診 |
| Traces | 請求走哪條路? | DAG | 找跨服務瓶頸 |
排查口訣:Metrics 告警 → Traces 定位 → Logs 確診。
| 選型 / 概念 | 預設 | 替代 / 補充 |
|---|---|---|
| 該監控哪些 | 四個黃金信號 Latency/Traffic/Errors/Saturation | Google SRE 最基本 |
| Metrics 系統 | Prometheus(Pull)+ Grafana | 短命任務用 Push/Pushgateway |
| 集中式日誌 | ELK(全文索引) | 成本敏感 → Grafana Loki(只索引標籤) |
| 分散式追蹤 | OpenTelemetry + Jaeger/Tempo | OTel 是標準不是產品 |
P99 必須用 Histogram,平均值會被快請求拉低掩蓋尾端。
對症狀告警(用戶有感)不對原因(CPU 高),避免告警疲勞。
高基數(user_id)放 Logs/Traces,別塞 Metrics label(時序爆炸)。
SLA < SLO 留緩衝;SLO 別設 100%(99.9% → 每月約 43 分鐘 error budget)。
案例招牌取捨速查(Case Studies)→ 案例研究
| 案例 | 難度 | 招牌取捨(core_tradeoff) |
|---|---|---|
| QR Code 產生器 | easy | redirect 用 302 而非 301——放棄瀏覽器快取省的一跳延遲,換擁有者可改/刪對應、每次掃描取最新 |
| 地震通知系統 | medium | geo 比對用「預寫 cell→devices 反向索引、alert 時 polyfill」而非即時算距離——犧牲精確與少量邊界誤判,換 sub-second fan-out |
| Polymarket 預測市場 | hard | 撮合 append-only、永不回滾——鏈上結算失敗只 retry/升級 ops,絕不 rollback off-chain fill;犧牲鏈上鏈下強原子,換 deterministic ordering 與可重建 |
| Amazon 價格追蹤 | medium | 資料蒐集用 extension 群眾外包 + 優先式 crawler 的 hybrid,而非暴力爬全站——犧牲覆蓋均勻與純淨度,換熱門優先、新鮮度高、不被 rate limit 卡死 |
| Robotaxi 叫車 | hard | 配對狀態放 Redis(非 stateless worker 記憶體)+ DB partial unique index 兜底——犧牲純記憶體簡單與一點延遲,換多 worker 共享下的 1 AV:1 Ride 強一致 |
| Spotify 熱門排行 | medium | 用 OLAP + 批次(Spark) 而非直接掃 OLTP——犧牲分鐘級新鮮度,換「數十億筆聚合準時完成且不拖垮線上寫入」;要 <1 min 再升 Flink streaming |
| Messenger 即時通訊 | hard | 分片用 chat_id(pub/sub) 而非 user_id——放棄「以使用者為中心」的直覺,換「同一 chat 單一 owner→順序唯一權威 + fan-out 從 N 接收者降到 M gateway」 |
| Webhook 平台 | hard | 選 at-least-once 而非 exactly-once——接受客戶可能收到重複、要求對方冪等,換接收端暫掛也絕不丟事件的可靠與簡單 |
| Google Docs 協作編輯 | hard | 用中心化 OT(單一序列器)而非 CRDT——犧牲離線/P2P/高併發上限,換每按鍵 50–100ms 極低延遲與決定性總序 |
| YouTube 影音平台 | hard | 影片 bytes 永遠不經過我們的 service——client presigned URL 直傳 S3、manifest+多 format ABR 串流,把 GB 級流量推離 app server,代價是複雜度攤到 client + 離線轉碼 DAG |
| ChatGPT Tasks 排程 | hard | watcher(查詢)與 worker(執行)用 queue 解耦 + 接受 at-least-once 而非 exactly-once——犧牲精準一次語意,換突發吸收 + crash 容錯 + 獨立擴展,代價是 job 須冪等 |
| Airbnb 訂房平台 | hard | 訂房用「邏輯可用性(reserved + expiration)」而非實體鎖——犧牲一條 cron 補償路徑與「狀態即時翻回」的乾淨,換「不長持 DB lock、付款前就鎖 inventory、cron 延遲也不影響正確性」 |
| Q&A 客服 Agent | hard | 答案必須完全 grounded 在檢索 context——寧可主動拒答「轉真人」也不讓 LLM 用預訓練知識補答;用「會拒答的準確」換「什麼都答的流暢」 |
| LLM 推論 API | hard | dual-trigger batching——用 max_wait(~50ms)人為延遲湊批,犧牲單請求延遲換 GPU batch 填充率;time trigger 設延遲天花板、size trigger 設吞吐地板 |