這篇整理 Aurora read replica 與 fleet 拓樸:單一 cluster 內 read replica 怎麼用、容量怎麼規劃、lag 怎麼管,以及按 business sharding、微服務 ownership、合規市場 boundary 這幾條 driver 判斷什麼條件下拆 cluster、什麼條件下加 replica。共享 storage 為什麼能養大量 replica,在 Aurora storage architecture。

Aurora「最多 15 read replica」是文件數字,而實際 production 部署常常更早遇到拆 cluster 的決策點:blast radius、業務 sharding、微服務 ownership、合規 boundary 早在 15 replica 之前就推動拆 cluster。

問題情境

典型觸發場景:FanDuel Super Bowl / DraftKings 比賽日、流量 5-10 倍尖峰、read query(用戶查 balance、投注紀錄、odds)打爆 primary、需要快速擴 read replica 但又怕 lag 把 stale read 推到 user-facing。

讀者常見的具體疑問:

  • 「加 read replica 後 primary CPU 沒降、為什麼?」
  • 「Auto-scaling 加 replica 要幾分鐘、來不及接尖峰怎麼辦?」
  • 「Reader endpoint round-robin 把 query 打到 lag 大的 replica、用戶看到舊 balance」
  • 「業務跨 200 個 cluster、單個 cluster 才 5-10 個 replica、為什麼不集中?」

進一步問題:讀寫雙峰錯位是 Aurora 讀寫分流的核心 driver。DraftKings 揭露「write workloads spike up significantly around payout events, but opening the app during the game also activates a lot of balance queries」— 比賽進行時讀爆量、payout event 時寫爆量、兩個峰不在同一時刻。這代表 read replica 容量規劃不是「分散負載」、而是「為讀峰專門配置 capacity」。

FanDuel 揭露事件型容量分級:平日 baseline → 季後賽 2-3x → 季冠軍賽 4-5x → Super Bowl 5-10x。容量規劃要按事件級別分段、不是一律 10x。

對 Standard Chartered 這種受監管金融、不能用單一巨型 cluster — 7 個受監管市場 = 7 個獨立 cluster、合規 boundary 比運維成本優先。

核心機制:15 replica 上限、共享 storage、reader endpoint

Aurora read replica 的 first-class concept 是 共享 storage + DNS-based reader endpoint。傳統 PostgreSQL streaming replication 靠 primary push WAL 給 replica、replica 自己 apply;Aurora replica 直接從共享 storage 讀已 apply 的 page、不需要 catch-up。

15 replica 上限:

  • 每個 Aurora cluster 最多 15 個 read replica(跨 AZ)
  • 跨 region replica 走 Aurora Global Database(不算這 15 個)
  • 文件上限不是 production 真實上限 — 多數 production 部署在 5-10 replica 之間遇到拆 cluster 訊號

共享 storage 對 lag 的影響:

  • Replica 不靠 logical replication catch-up、直接從共享 storage 讀
  • Lag 來源是 compute node 的 buffer cache 同步、不是 WAL replay
  • Typical 10-30ms、heavy write 期間可能 100ms+、但 不會像 PostgreSQL 那樣 unbounded

DraftKings 揭露的「lag 可預測」frame(DraftKings case 的「判讀」段):

「30 秒降到 10-30 ms」的工程意義不只是「快」、而是「讓 read-after-write 變得可預測」。30 秒 lag 的世界裡、application 端做 read-after-write 要 cache 用戶最後寫入 30 秒以上、實務上做不到;10-30ms lag 的世界裡、application 可以做「寫操作後 100ms 內走 primary、之後可走 replica」的可規劃策略。

Reader endpoint 行為:

  • DNS-based round-robin、不感知 replica 健康狀態
  • Application 想要依 replica lag 挑 replica 要自己實作;截至 2026-09 的官方文件,RDS Proxy 的 reader endpoint 只把連線導向狀態為 available 的 reader,不依 replica lag 挑選 reader
  • Failover 期間短暫包含 promoted replica(已升 primary)、見 Aurora cross-AZ failover RTO

Auto-scaling policy:

  • CloudWatch metric(CPU / connection)trigger
  • Replica creation 2-5 分鐘
  • 無法用於秒級尖峰 — 是 DraftKings「+50% no sweat」誤讀的關鍵點

跟通用 read replica 差在哪:Aurora replica 不用 catch-up WAL、lag 上限可預測;vs PostgreSQL streaming replication lag 是 unbounded(取決於 primary 寫速度)。可預測 lag 是 read-after-write 場景變得可規劃的前提。

對應 knowledge card:replication-lag、stale-read。

Step-by-step 配置 / Reader endpoint 設計

建 read replica:

1aws rds create-db-instance \
2  --db-cluster-identifier my-cluster \
3  --db-instance-identifier my-replica-01 \
4  --db-instance-class db.r6g.4xlarge \
5  --engine aurora-postgresql \
6  --availability-zone us-east-1b \
7  --promotion-tier 1

Reader endpoint vs Custom endpoint:

1# 預設 reader endpoint:所有 replica round-robin
2# 訪問 url: my-cluster.cluster-ro-xxx.us-east-1.rds.amazonaws.com
3
4# Custom endpoint:group 特定 replica
5aws rds create-db-cluster-endpoint \
6  --db-cluster-identifier my-cluster \
7  --db-cluster-endpoint-identifier my-cluster-analytics \
8  --endpoint-type READER \
9  --static-members my-replica-analytics-01 my-replica-analytics-02

Custom endpoint 適用場景:

  • 分析 query 走獨立 endpoint、不影響 OLTP read replica
  • Read-after-write session 走 primary endpoint、其他 read 走 reader endpoint
  • 不同 SLO 的 read traffic 分流(high-priority vs batch)

Auto-scaling policy:

 1aws application-autoscaling register-scalable-target \
 2  --service-namespace rds \
 3  --resource-id cluster:my-cluster \
 4  --scalable-dimension rds:cluster:ReadReplicaCount \
 5  --min-capacity 2 \
 6  --max-capacity 10
 7
 8aws application-autoscaling put-scaling-policy \
 9  --service-namespace rds \
10  --resource-id cluster:my-cluster \
11  --scalable-dimension rds:cluster:ReadReplicaCount \
12  --policy-name my-cluster-cpu-scaling \
13  --policy-type TargetTrackingScaling \
14  --target-tracking-scaling-policy-configuration file://scaling-config.json

預配 vs auto-scale:

  • Peak workload 預知(賽事、促銷、季節事件)→ 提前 1 小時預配
  • Unpredictable burst → auto-scale(接受 2-5 分鐘 lead time)
  • 兩者混合:baseline 預配 + auto-scale 處理 baseline 之上的浮動

驗證點:

  • AuroraReplicaLag < 100ms(per replica)
  • Reader endpoint CPU 分布均勻(不是某 replica 過熱)
  • Application stale-read error rate < 0.1%

Rollback boundary:移除 replica 即時生效、無 data loss;但 reader endpoint DNS cache 仍可能短暫 routing 到已移除 replica(5-30 秒)。

故障模式 / 邊界 case

加 replica 後 primary CPU 沒降

徵兆:明明加了 3 個 read replica、primary CPU 仍然 90%、reader endpoint CPU 才 10%。

原因:application 沒把 read query routing 到 reader endpoint、所有 query 仍打 primary。Aurora reader endpoint 不會自動分流 — 必須 application 端拆 read / write data source。

修:

  • Application 端 ORM / data source layer 拆 read / write connection pool
  • 寫操作用 writer endpoint、純讀走 reader endpoint
  • 雙峰錯位是拆 read / write data source 的 driver(DraftKings case 揭露 讀寫資源規劃要分開)

Reader endpoint round-robin 推 stale read

徵兆:read-after-write 場景(用戶下注後立刻查 balance)打到 lagging replica、看到舊 balance、客訴。

原因:reader endpoint DNS-based round-robin、不感知 lag。Application 假設 read 永遠 fresh、但 typical 10-30ms lag 期間用戶操作就會踩到。

修:

  • Sticky session:寫操作後的一段時間 N 內同 session 走 primary(N 取 lag p99、typical 100ms)
  • Application 端做「下注後 N 內走 primary」邏輯(DraftKings「可預測 lag」frame 讓 N 可規劃)
  • RDS Proxy 的 reader endpoint 補不上 read-after-write 的缺口:截至 2026-09 的官方文件,它只避開不可用的 reader、不依 replica lag 挑 reader,寫入後的讀取仍要靠 sticky session 或 application 端的「下注後 N 內走 primary」邏輯

Auto-scaling 來不及接秒級尖峰 — headroom 預留判讀

徵兆:賽事開賽 30 秒內流量 +50%、auto-scaling 觸發但 2-5 分鐘後才有新 replica、開賽尖峰已過、用戶在最關鍵時段看到 timeout。

機制限制:replica creation 2-5 分鐘、秒級尖峰過去了 replica 才上線。

DraftKings「Super Bowl +50% no sweat」的工程意義(DraftKings case 的「判讀」段原文):「這句話的工程意義是 提前做好容量規劃、不是『Aurora 神奇』。寫 workload 預期可能 +50%、整個 system headroom 預留至少 50%、加上 read replica 動態加減、才能讓 50% 增幅變成『不流汗』」。

工程含義:

  • Peak workload 預知(賽事 / 促銷)用 headroom 預留 + scheduled scaling 提前預配、不靠 auto-scale 接秒級
  • Auto-scale 是 unpredictable burst 才用(突發新聞、KOL 推廣、未預期事件)
  • DraftKings 的「不流汗」是 系統設計 結果、不是 Aurora 特殊能力

修:

  • 賽事日曆建模:賽前 1 小時自動加 replica、賽後 2 小時減
  • Primary instance class 升級提前一週、不是賽前升(升級期間 failover 風險)
  • Headroom 預算:read replica 預留 50%、primary CPU baseline < 50%

15 replica 上限 — 拆 cluster 訊號

徵兆:read traffic 持續成長、加到 15 replica 仍接近 CPU 瓶頸、想加第 16 個被 API 拒絕。

原因:Aurora 硬上限 15 replica / cluster、超過要拆 cluster。但實務上更常在 5-10 replica 就遇到其他拆 cluster 訊號(blast radius、ownership boundary、業務 sharding)。

修:照下方〈何時拆 vs 加 replica 的判讀順序〉逐條判斷——超過 15 replica 的需求、blast radius 隔離需求、業務本身可切分、微服務私有 store 拓樸、合規禁止跨境複製,任一成立就拆 cluster,都不成立才加 replica。

Heavy write 期間 replica lag spike

徵兆:bulk insert / DDL 期間 replica lag 從 10-30ms 跳到 100-500ms、application 假設 typical lag 永遠成立、stale read 比例大幅上升。

原因:heavy write 期間 replica buffer cache invalidate 速度跟不上、lag 暫時拉大。Aurora 的「可預測 lag」不等於「lag 永遠 10-30ms」。

修:

  • bulk insert / DDL 期間 application 端切到全 primary 模式(避開 stale read 風險)
  • 要重寫整張表的 DDL 改用 logical migration 或分批執行、避免長時間 table lock;pg_repack 只移除表與索引的 bloat,不執行欄位變更這類 schema DDL,而且它重建整張表時本身就是一段 heavy write
  • 監測 AuroraReplicaLagMaximum、spike 超過 p99 threshold trigger application 端 fallback

FanDuel 雙 SLO 並行 — 不要壓成單一數字

徵兆:team 看 FanDuel「5-10x peak」直接套到自家 streaming workload、結果 Aurora 撐不住、發現 FanDuel streaming 根本不走 Aurora。

FanDuel case「判讀」段第 1 點原文:「直播跟投注是兩種完全不同 SLO:直播容忍秒級延遲(用 CDN + ABR 串流)、投注必須毫秒級成交。兩個服務必須各自獨立擴容、各自獨立 SLO」。

scope warning(必明示):

  • FanDuel 5-10x 是 betting 服務的 Aurora 擴容倍數、不是 streaming
  • Streaming 走 CDN、不走 Aurora
  • 不能把兩種 SLO 壓縮成「Aurora 撐 5-10x」單一數字

case 自承的進一步 scope warning:「AWS 案例 沒有 提具體 betting transaction TPS、concurrent streams、延遲分布」(case「需要警惕」段)。引用 FanDuel 時不能寫「Aurora 在 betting 路徑撐 X TPS」這類細節 — case 沒提的數字不能擴寫。

修:

  • 不同 SLO workload 拆獨立 cluster 或拆 read / write data source
  • 容量規劃看自家 workload TPS、不要套用未公開的 case 數字

事件型容量分級表

FanDuel 揭露事件型 scaling 不是一律 10x — 事件級別 是容量分級單位:

事件級別倍數來源
平日 baseline1xFanDuel case「判讀」段第 3 點
季後賽 playoff2-3xFanDuel case 揭露事件分級
季冠軍賽 championship4-5xFanDuel case 揭露事件分級
Super Bowl5-10xFanDuel case 揭露事件分級

跟 DynamoDB 事件型流量模式的對應:本表是 Aurora 從讀峰視角切入的事件分級。DynamoDB on-demand-vs-provisioned 把事件型流量分成 flash-sale spike、predictable peak、sustained growth、surge baseline permanent shift、B2B sustained + 高可用這幾種模式;FanDuel 的賽季 cycle 對應其中的 predictable peak——事件 tier 已知(賽季 → 季後賽 → 季冠軍賽 → Super Bowl)、峰值已知而且重複出現,所以能按 tier 預配 read replica 數量。

KV 層與 SQL 層的容量決策差異:DynamoDB 的容量決策是在 on-demand 與 provisioned 兩種 mode 之間選,判斷依據包括 peak/avg ratio 與 predictable-peak vs flash-sale,推導在 DynamoDB on-demand-vs-provisioned。Aurora 沒有對應的 mode 可切,對應的決策是 read replica 的數量,以及用 auto-scaling、scheduled scaling 還是 headroom 預留來調整它。

case 自帶警示(scope warning 必保留):

  • 「5-10x」是 峰值倍數、不是 peak 持續時間。Super Bowl 的關鍵 30 分鐘可能 8-10x、其他 3 小時可能 3-5x(case「需要警惕」段)
  • 分級 driver 是「同類事件中的最高倍率」、不是恆定數字 — 引用時要保留事件 tier 對應、不是一律「Super Bowl = 10x」單一閾值
  • 跨業務 transfer 判讀:本表 只代表體育博彩賽季 cycle、不能直接套到 e-commerce flash-sale(e-commerce flash-sale 的倍數結構是「秒級數千倍」、跟事件 tier 結構不同)

容量規劃做法:

  • 建立 event tier 體系、每 tier 對應不同 pre-scale 倍數跟 lead time(賽前 N 小時預配)
  • 事件型分級的關鍵是「峰值是已知的」、不是「峰值多大」
  • 對應 9.11 高峰事件準備 的容量分級

邊界與整合:Fleet 治理 SSoT — 何時拆 cluster vs 加 replica

本段回答 Aurora fleet 什麼條件下拆 cluster、什麼條件下加 replica。

跨 case 合成 frame:production scale 不是「單一巨型 cluster」而是 fleet of clusters、但 driver 各異。

DriverCase anchorFleet 規模拆分判讀
Business shardingDraftKings200 cluster業務本身可切分(每體育類別 / 每地理 / 每產品線各自 cluster)、blast radius 隔離
Microservice ownershipNetflix多 cluster每微服務私有 store、不共用 cluster — 容量規劃分散到 service owner
合規市場 boundaryStandard Chartered7 cluster受監管市場資料 不能跨境複製、每市場獨立 cluster — Global Database 在合規場景反指標

Business sharding(DraftKings 200 cluster)

DraftKings 不用一個巨型 cluster 撐 100 萬 ops/min、而是 按業務切 200 cluster。每體育類別、每地理、每產品線各自 cluster、blast radius 自然隔離。

工程含義:

  • 業務本身就有 sharding key(sport type / region / product line)— 拆 cluster 不需要 schema redesign
  • 單 cluster 故障只影響該業務、不影響全平台
  • 容量規劃變成「每 cluster 的容量規劃」、單機極限不重要

容易誤判的邊界:DraftKings 100 萬 ops/min ≈ 17K ops/sec 是 200 cluster 加總、平均每 cluster 約 80 ops/sec(case「需要警惕」段)— 不是「單一 cluster 撐 100 萬 ops」、案例對照不能擴寫成單 cluster 容量。

Microservice ownership(Netflix)

Netflix 每微服務各自有 private Aurora cluster、不共用 — 跟 monolith「一個大 DB 撐全部」相反。

工程含義:

  • DB 容量規劃變成「每微服務的容量規劃」、複雜度分散到 service owner
  • 跨服務 contention 變成 network 議題 而非 DB lock 議題
  • 每多一個微服務就多一個 cluster、operational surface area × N

case 自帶 scope 警示:Netflix 數據層遠不止 Aurora — 還有 Cassandra(playback metadata)、EVCache(cache layer)、Iceberg(data warehouse)。Aurora 主要是「需要 ACID 的 OLTP 工作負載」、不是「all-purpose store」(case「需要警惕」段第 2 點)。讀者引用 Netflix consolidation 時、不能誤推論「Aurora 可以替所有 store」。

合規市場 boundary(Standard Chartered 7 cluster)

Standard Chartered 7 個受監管市場 = 7 個獨立 cluster。Data Residency 規範資料 不能跨境複製、Aurora Global Database 在這種場景違反合規。

工程含義:

  • 容量規劃變成「7 個獨立規劃 × 各自合規門檻」
  • 跨市場 DR 不靠 Global Database、靠應用層市場切換
  • 合規 lead time 是時程主項(見 migration playbook 合規時程段)

case 自承 scope 警示:Standard Chartered case 未公開是 PostgreSQL 還是 MySQL、未公開具體 cost 數字、屬「相關 case study」匿名對照。

何時拆 vs 加 replica 的判讀順序

按以下順序判斷、第一個成立的就是拆 cluster 的訊號:

  1. > 15 replica 需求 → 拆 cluster(Aurora 硬上限)
  2. Blast radius 隔離需求 → 拆 cluster(單 cluster 故障影響範圍太大、業務不能接受)
  3. 業務本身可切分(user shard / 產品線 / 地理)→ 拆 cluster(DraftKings 拓樸)
  4. 微服務私有 store 拓樸 → 拆 cluster(Netflix 拓樸、跟服務生命週期綁定)
  5. 合規禁止跨境複製 → 拆 cluster(Standard Chartered 拓樸、Global Database 反指標)
  6. 以上都不成立 → 加 replica(最便宜的容量槓桿)

容易誤判的邊界:

  • Fleet 治理本身有 ops surface area 成本(parameter group / backup / IAM / observability fan-out × N cluster)— 不是免費;driver 不夠強時不該拆
  • 「fleet 看起來大」不是 driver — driver 是業務本身有 boundary、不是運維美觀
  • 拆 cluster 後再合併比拆更難(資料遷移成本高)— driver 不確定時先加 replica

容量與觀測

核心 metric:

1AuroraReplicaLag           # per replica lag
2AuroraReplicaLagMaximum    # cluster max lag
3CPUUtilization             # per replica CPU
4DatabaseConnections        # per replica connection

Application 端 metric:

1read_query_latency_p99       # per endpoint (writer vs reader)
2stale_read_error_count       # read-after-write 失敗訊號
3read_replica_routing_ratio   # writer vs reader 流量比例

容量上限:

容量公式:

1read replica count = (平日 read QPS / replica throughput) × (1 + lag buffer) × (1 + event tier headroom)
2
3lag buffer          = 30%(典型)
4event tier headroom = 事件倍數 − 1:0% (平日 1x) / 100-200% (playoff 2-3x) / 300-400% (championship 4-5x) / 400-900% (Super Bowl 5-10x)

回路徑:9.5 瓶頸定位流程 判斷 read-bound vs write-bound、9.6 容量規劃模型 peak workload 預配 vs auto-scale 決策。

邊界與整合 / 下一步

同 vendor 的其他文章:

Migration playbook:

1.x 章節互引:

RDS Proxy 整合:reader endpoint 避開不可用的 reader(截至 2026-09 的官方文件,不依 replica lag 挑 reader)、connection pool 共享、Lambda 場景;managed alternative。

何時不用本文:single replica + cross-AZ failover 已滿足、read traffic 不是 bottleneck 時可跳過。

相關連結