讀取擴展 (Scaling Reads)

核心問題

讀取流量成長遠快於寫入。 一個 Instagram feed 載入可能觸發 100+ 次讀取,但用戶一天只發一篇(一次寫入)。一般讀寫比至少 10:1,內容型應用可達 100:1 以上。

這是物理限制,不是 code 問題

CPU 指令數、RAM 容量、磁碟 I/O 都有硬上限。碰到瓶頸時,加再多程式碼都沒用 → 必須從架構下手。


解法的演進順序(必背)

1. 先把 Database 自己調好   ── index / 硬體 / denormalization / materialized view
        ↓ 還不夠
2. 水平擴展 Database         ── read replica / sharding
        ↓ 還不夠
3. 加外部 Caching Layer      ── application cache (Redis) / CDN edge cache
面試加分點

很多人直接跳到「分散式 caching」,卻沒先把更簡單的 index / replica 用盡。先從你擁有的開始 —— 現代 DB 在正確 index 下能承受遠超預期的負載。

粗略觸發點:讀取 > 50,000~100,000 次/秒(已有適當 index)才需要考慮水平擴展或加 cache。


第一步:Database 內部優化

技巧 做法 代價 / 注意
Index 在常 query/join/sort 的欄位加索引,O(n)→O(log n) 「index 太多拖慢寫入」被過度放大;index 太少死掉的應用遠多於太多
硬體升級(垂直擴展) SSD(隨機 I/O 快 10~100×)、加 RAM、更快 CPU 最快買到喘息空間;但面試官通常不想聽這個(迴避核心)
Denormalization 用空間換速度,允許資料重複,避免大量 join 寫入變複雜(改名要更新多處);先確認讀寫比
Materialized View 預先算好昂貴的聚合(如平均評分),背景排程更新 結果有延遲
Denormalization 是典型讀寫取捨

重複儲存讓讀取更快,但讓寫入更複雜。寫入也頻繁時,這個複雜度可能不划算。


第二步:水平擴展

Read Replica(首選)

Replication Lag 是核心挑戰(面試常考)

寫入 primary 後資料需時間傳播到 replica。用戶寫完馬上讀,可能讀到還沒同步的 replica → 看不到自己的改動。詳見 05-Database-Advanced/03-Replication

Sharding

對讀取擴展有兩個好處:資料集變小、負載分散。但 Sharding 主要是寫入擴展技術,運維複雜度高 —— 大多數讀取問題加 cache 更有效。詳見 05-Database-Advanced/02-Sharding10-Design-Patterns/02-Scaling-Writes


第三步:外部 Caching Layer

關鍵觀察:存取模式高度偏斜。幾百萬人讀同一則爆紅推文,DB 一直在回答完全一樣、幾乎不變的問題。

層次 延遲 說明
Application Cache(Redis/Memcached) < 1ms 坐在 app 和 DB 中間,hit 直接回,miss 才查 DB 並回填
CDN / Edge Cache 個位數 ms 延伸到全球 edge;可降低 origin 負載 90%+
CDN 只快取「多用戶共享」的內容

公開貼文、商品目錄、搜尋結果 ✅;個人偏好、私人訊息、帳戶資訊 ❌(hit rate = 0)。詳見 07-Caching-Storage/01-Caching

Cache Invalidation 五策略

策略 機制 適用
TTL 固定存活時間到期失效 更新模式可預期的資料(安全網,5~15 分)
Write-through 寫 DB 時同步更新/刪 cache 需一致性,但增加寫入延遲
Write-behind 失效事件排 queue 非同步處理 降低寫入延遲,短暫過時
Tagged 給 entry 加標籤,相關資料變動時整批失效 複雜依賴關係
Versioned keys key 內含版本號,更新即遞增 簡單可靠,需追蹤版本
TTL 由非功能性需求決定

需求說「搜尋結果最多 30 秒過時」→ TTL = 30 秒。讓 cache 策略有依據,而不是靠猜。


常見 Deep Dive


何時用 / 何時不用

✅ 適合 ❌ 不適合
內容型應用(社群、電商、影音) 寫入密集(Robotaxi 位置追蹤,讀寫比 2:1)→ 先做寫入擴展
QR/短網址(讀寫極度不平衡) 小規模(1000 用戶)→ 單一良好 DB 即可,別過度設計
Ticketmaster 活動頁、News Feed、YouTube metadata 強一致(金融、庫存)→ 需積極失效 + 更短 TTL
即時協作(Google Docs)→ 需即時更新,caching 反而有害
讀取擴展 ≠ 降低延遲

讀取擴展是關於減少 DB 負載。如果 DB 負載沒問題、只是要更低延遲,那是不同問題(edge computing / service mesh 優化)。