Amazon SAA-C03: 資料庫與快取 — 學習指南
屬於 AWS SAA-C03 — 完整學習指南. 使用經過驗證的解答練習: Amazon 考試中心, 或參加限時模擬考試: ExamRoll.io.
Amazon Aurora:架構與端點
Aurora 將 MySQL 和 PostgreSQL 底下的儲存層重新實作為一個分散式、日誌結構化、六向複寫的磁碟區,橫跨三個 AZ。運算節點相對於儲存是無狀態的 (stateless),因此 Aurora Replica 是從與寫入器相同的底層磁碟區讀取,而不是重播日誌。複寫延遲通常為 10-20 毫秒,而標準 RDS 複本則需要數秒鐘。一個叢集支援多達 15 個複本,這些複本可以在大約 30 秒內提升為寫入器。
Aurora 提供四種端點類型:
| 端點 | 用途 |
|---|---|
| 叢集 (寫入器) 端點 | 永遠指向目前的主資料庫 |
| 讀取器端點 | 在所有複本之間對連線進行負載平衡 |
| 自訂端點 | 將流量路由到您選擇的特定執行個體子集 |
| 執行個體端點 | 直接存取單一節點 |
當複本是異質的 (heterogeneous) 時,自訂端點就顯得格外重要。假設六個複本中有三個是 db.r6g.8xlarge 用於分析報告,而其餘的則用於 OLTP 讀取,那麼通用的讀取器端點偶爾會將報告工作負載路由到較小的節點,從而影響可預測性。一個僅限於大型複本的自訂端點可以提供確定性的工作負載隔離:
aws rds create-db-cluster-endpoint \
--db-cluster-identifier prod-aurora \
--db-cluster-endpoint-identifier reporting \
--endpoint-type READER \
--static-members reporting-node-1 reporting-node-2 reporting-node-3
請注意,Aurora 端點的 DNS TTL 為 5 秒;快取連線字串超過此時間會破壞容錯移轉行為。
Aurora Auto Scaling 會根據目標 CPU 或連線指標來新增和移除讀取器,這對於必須保持高可用性且無法預測的讀取密集型工作負載來說,是標準的解法:
TargetTrackingScalingPolicyConfiguration:
PredefinedMetricSpecification:
PredefinedMetricType: RDSReaderAverageCPUUtilization
TargetValue: 60.0
ScaleInCooldown: 300
ScaleOutCooldown: 60
當 RDS MySQL 讀取複本在尖峰時段無法將複寫延遲維持在一秒以下時,低程式碼的解決方案是遷移至 Aurora MySQL——連線字串幾乎不需要更改,而且儲存層級的複寫消除了延遲。
Aurora Serverless v2 與複製
Aurora Serverless v2 能以細微的 Aurora 容量單位 (ACU,每個單位為 2 GiB 記憶體) 在大約半秒內進行垂直擴展運算能力,且不會中斷連線。它適用於具有已知基線記憶體使用量的變動性工作負載——例如,一個地端 MySQL 遷移專案,其記憶體消耗總是至少 2 GiB。將最小值設為 1 ACU,最大值設為 32 ACU,叢集就能無需管理即可彈性伸縮。當負載穩定且可預測時,預配置的 Aurora 仍然是更好的選擇,因為 Serverless v2 每個 ACU 會有額外費用。
Aurora 複製 (cloning) 會透過寫入時複製 (copy-on-write) 的方式,建立一個與來源共用儲存頁面的新叢集。複製體在幾秒鐘內即可建立,且在資料開始分歧前不產生任何費用,使其成為測試環境、高風險的遷移,或讓分析師對生產環境的複本進行高強度測試的理想選擇。快照還原則是實體地重新還原資料,可能需要數小時;當速度至關重要時,複製是更好的選擇。
Aurora Global Database
Aurora Global Database 將一個叢集擴展到最多五個次要區域,使用專用的儲存層複寫基礎設施——而非 binlog 傳輸。典型的複寫延遲低於一秒,RPO 低於一秒,而受管的容錯移轉可在不到一分鐘內將次要區域提升為主區域。
| 功能 | 跨區域讀取複本 | Aurora Global Database |
|---|---|---|
| 典型 RPO | 約 1 分鐘 | < 1 秒 |
| 典型 RTO | 15–60 分鐘 | < 1 分鐘 (受管的容錯移轉) |
| 複寫路徑 | 透過網路傳輸二進位日誌 (Binary log) | 專用的儲存層基礎設施 |
| 受管的容錯移轉 | 否 | 是 |
兩個關鍵的語意:在正常操作期間,次要區域是唯讀的,且 Global Database 是為低 RPO 的災難復原和低延遲的遠端讀取而設計,而非主動-主動 (active-active) 的多主資料庫。認為全域資料庫「會自動處理次要區域的寫入」是錯誤的——在次要區域進行寫入需要明確的受管容錯移轉或分離並提升 (detach-and-promote)。對於要求跨區域 RPO 為 5 分鐘、RTO 為 20 分鐘,且營運開銷最小的需求,Global Database 是標準解法。
RDS Proxy 與連線管理
無伺服器和高並行性的工作負載加劇了一個經典問題:連線風暴 (connection storms)。一個擴展到 3,000 個並行執行的 Lambda 函數會開啟 3,000 個通訊端 (sockets),耗盡 max_connections 並導致連鎖故障——而這恰好發生在系統處於高負載時。在函數內部的連線池沒有幫助,因為每個並行執行環境都是隔離的。
RDS Proxy 位於用戶端和資料庫之間,維護一個暖連線池 (warm pool),並將用戶端的工作階段多工複用 (multiplexing) 到這些連線上。它解決了兩個問題:
- 連線風暴。 數千個用戶端工作階段被多工複用到一個小的後端連線池上。
- 容錯移轉時間。 代理程式在重新建立後端連結時會保持用戶端連線開啟,將感知的容錯移轉時間縮短高達 66%,並消除了用戶端重新建立 TCP/TLS 連線和重新解析 DNS 的需要。
它與 IAM 和 Secrets Manager 整合以處理憑證,從而將寫死在應用程式碼中的密碼移除。
DBProxy:
Type: AWS::RDS::DBProxy
Properties:
EngineFamily: POSTGRESQL
RequireTLS: true
IdleClientTimeout: 1800
Auth:
- AuthScheme: SECRETS
SecretArn: !Ref DBSecret
IAMAuth: REQUIRED
應用程式應連線到代理程式的端點,而不是叢集端點。任何 Lambda-to-RDS 或高扇出 (high-fan-out) 的架構都應該使用 RDS Proxy,除非有特殊理由不這麼做。在 EC2 上自行運行連線池程式 (如 PgBouncer、ProxySQL) 是可行的,但這會增加營運開銷,而 RDS Proxy 的存在正是為了消除這些開銷。
DynamoDB:容量模式
DynamoDB 是一個託管的鍵值/文件儲存庫,無論規模大小,都能提供個位數毫秒的延遲,並透過雜湊鍵進行水平分割。它提供兩種容量模式:
| 模式 | 最適合 | 計費方式 | 流量高峰下的行為 |
|---|---|---|---|
| 佈建模式 | 可預測、穩定的流量 | 每小時 RCU/WCU | 除非設定自動擴展,否則會進行節流 |
| 隨需模式 | 未知、突發或新的工作負載 | 按請求計費 | 立即吸收流量,直到資料表上限 |
隨需模式顯著簡化了操作,但每個請求的成本比充分利用的佈建容量高出約 6-7 倍。對於一個每晚 4 小時、500 WCU 的批次處理,隨需模式會支付過高的費用——採用排程擴展或預留容量的佈建模式會便宜得多。反之,若為一個不可預測的公開發布工作負載使用佈建模式,則會導致節流。對於具有中度變化的穩定工作負載,使用目標追蹤自動擴展並將使用率維持在 70% 左右的佈建模式,會比隨需模式便宜得多——通常可節省 50-70%:
TargetTrackingScalingPolicyConfiguration:
TargetValue: 70.0
PredefinedMetricSpecification:
PredefinedMetricType: DynamoDBReadCapacityUtilization
ScaleInCooldown: 60
ScaleOutCooldown: 60
您每 24 小時可以切換一次模式。認為隨需模式在任何情況下都比較便宜是一個代價高昂的錯誤;同樣地,認為佈建模式永遠適合突發流量也是錯誤的。
DynamoDB:一致性、串流、全域資料表
讀取預設為最終一致性(可能在約 1 秒內回傳過時資料,成本為 0.5 RCU)。設定 ConsistentRead=true 會回傳最新提交的值,但成本加倍。全域次要索引或 DAX 不支援強力一致性讀取——這些路徑總是回傳最終一致性的資料。
DynamoDB Streams 以有序日誌的形式擷取項目層級的變更,並保留 24 小時,可觸發 Lambda 進行下游處理(如搜尋索引、通知、跨資料表反正規化),無需輪詢。
Global Tables(全域資料表)建立在 Streams 之上,提供多活、多區域的複寫,並採用「最後寫入者獲勝」的衝突解決機制。當讀寫必須在多個區域中保持本地化時,這是正確的選擇。但它們會使儲存和寫入成本大約增加一倍——每次寫入都會在每個複本區域消耗一個 WCU——並削弱了跨區域的一致性。一個常見的陷阱是,在單一區域已能滿足可用性需求時仍啟用 Global Tables:單一區域中的 DynamoDB 已經在三個可用區之間進行複寫,可用性高達 99.99%。具成本效益的單一區域高可用性方案是:一個啟用 PITR 的單一區域資料表,並視需求搭配自動擴展的佈建容量。
Point-in-Time Recovery (PITR)(時間點復原)提供連續備份,可在過去 35 天內以秒級的精細度進行還原,且額外開銷可忽略不計。應在任何生產環境的資料表上啟用它——它能滿足典型的 RPO(復原點目標)要求,將時間從數小時縮短到數分鐘。若需更長的保留時間(例如法規遵循),可整合 AWS Backup 進行排程、生命週期管理且可跨區域複製的備份。
TTL(存留時間)讓您指定一個包含 Unix epoch 到期時間的屬性;DynamoDB 會非同步地免費刪除過期的項目,非常適合用於會話儲存、臨時權杖或事件快取。TTL 的刪除操作會流經 Streams 以供下游封存:
TTLSpecification:
AttributeName: expireAt
Enabled: true
對於分析需求,匯出至 S3 會產生一個時間點快照,可供 Athena、Redshift Spectrum 或 EMR 讀取,而不會消耗資料表的容量——這是一個比掃描整個資料表好得多的模式。
DAX:DynamoDB 加速器
DAX 是一個專為 DynamoDB 設計的全託管、記憶體內、寫入穿透的快取,可提供微秒級的讀取延遲,遠優於 DynamoDB 的個位數毫秒基準。其顯著特點是 API 相容性:DAX 用戶端是 DynamoDB SDK 用戶端的直接替代品,因此應用程式只需更改端點設定即可採用,而無需重寫查詢邏輯:
import amazondax
dax = amazondax.AmazonDaxClient(
endpoint_url='dax://cluster.abc.dax-clusters.us-east-1.amazonaws.com')
table = dax.Table('Products')
resp = table.get_item(Key={'sku': '1234'}) # microsecond hit path
DAX 維護兩種快取:用於 GetItem/BatchGetItem 結果的項目快取,以及用於 Query/Scan 結果的查詢快取。寫入是寫入穿透模式——DAX 會代理請求至 DynamoDB,並在成功後更新其項目快取——但查詢快取依賴 TTL,因此即使對於剛寫入的項目,查詢結果也可能變得過時。
有兩個限制很重要。首先,DAX 只加速最終一致性讀取;強力一致性讀取會繞過快取。其次,其他寫入者若繞過 DAX 會導致資料過時。對於一個每天有數百萬次點擊的產品詳細資訊頁面,DAX 是操作開銷最小的加速器——無需快取失效程式碼,也無需單獨管理叢集。在 DynamoDB 前面放置 ElastiCache 也能運作,但需要實作旁路快取邏輯,而 DAX 讓這一步驟變得多餘。
ElastiCache: Redis 與 Memcached
ElastiCache 作為執行 Redis 或 Memcached 的託管服務,提供亞毫秒級的記憶體內資料存取。引擎的選擇取決於功能需求:
- Memcached — 純粹的多執行緒鍵值快取,具備水平分片功能,但不支援持久化、複寫或發布/訂閱。僅適用於可接受整個快取遺失的暫時性快取情境。
- Redis — 支援複寫、具備自動容錯移轉的多可用區 (Multi-AZ)、用於分片的叢集模式、持久化、發布/訂閱、排序集合、交易,以及傳輸中和靜態加密。對於任何需要持久性或複雜資料類型的應用都是必要的。
主要有兩種典型模式。
集中式會話儲存。 當 ALB 將流量分散到無狀態的 EC2 或 ECS 執行個體時,本機會話儲存會強制使用黏性會話,這會導致負載不均,並在縮減規模、部署和可用區 (AZ) 故障期間中斷服務。將會話外部化到 Redis,可讓任何執行個體處理任何請求,且會話能在主機故障後存活:
import redis, json
r = redis.Redis(host='sessions.abc123.ng.0001.use1.cache.amazonaws.com',
port=6379, ssl=True)
def save_session(sid, data, ttl=1800):
r.setex(f"sess:{sid}", ttl, json.dumps(data))
昂貴查詢的讀取卸載 — 例如排行榜 (透過 Redis 的排序集合 ZADD/ZREVRANGE 實現)、目錄查詢、彙總。快取策略必須符合一致性需求:
- 延遲載入 (cache-aside): 應用程式先讀取快取;若未命中,則讀取資料庫並將資料填入快取,同時設定 TTL。此法簡單,但冷啟動時的未命中會影響效能,且資料可能過時。
- 寫入穿透 (write-through): 應用程式在同一個操作中同時寫入快取和資料庫。快取能保持最新,但寫入速度較慢,且未使用的資料仍會佔用記憶體。
- 回寫 (write-behind): 先寫入快取,再非同步地刷回資料庫。寫入速度最快,但快取若故障會導致資料遺失。
data = r.get(f"product:{sku}")
if data is None:
data = db.query("SELECT * FROM products WHERE sku=%s", sku)
r.setex(f"product:{sku}", 300, serialize(data))
若依賴任何快取層卻沒有失效策略 — 例如 TTL、更新時明確執行 DEL、或寫入穿透 — 將會導致過時讀取。這種失敗模式是無聲的:應用程式看起來運作正常,直到使用者注意到資料不一致。快取也通常是將讀取擴展到唯讀複本所能輕鬆支援的範圍之外最便宜的方法,並能在流量突增時保護主資料庫。
與 DAX 不同,ElastiCache 是引擎無關的 — 您需要自己負責失效邏輯 — 這就是為什麼當後端儲存是 DynamoDB 時,DAX 在操作簡易性上勝出的原因。
遷移:DMS 與 SCT
AWS Database Migration Service (DMS) 可在同質引擎 (如 Oracle→Oracle、MySQL→Aurora MySQL) 或異質引擎 (如 Oracle→Aurora PostgreSQL、SQL Server→RDS MySQL、本地→DynamoDB) 之間複寫資料。一個 DMS 任務包含三個階段:
- 完整載入 — 大量複製現有資料列。
- CDC (變更資料擷取) — 追蹤來源端的交易日誌並套用持續的變更。
- 完整載入 + CDC — 常見的最短停機時間模式:來源端保持線上,DMS 讓目標端保持同步,最後的切換只是一個短暫的 DNS 切換。
aws dms create-replication-task \
--replication-task-identifier ora-to-aurora \
--source-endpoint-arn $SRC --target-endpoint-arn $TGT \
--migration-type full-load-and-cdc \
--table-mappings file://mappings.json \
--replication-instance-arn $RI
DMS Serverless 無需規劃和管理複寫執行個體 — 容量會根據工作負載自動配置,適合變動性或長時間執行的 CDC。來源引擎必須啟用補充日誌記錄 (Oracle) 或 ROW 格式的二進位日誌記錄 (MySQL)。對於非常大量的初始資料,DMS 可與 Snowball Edge 整合進行離線載入。
DMS 遷移的是資料,而非結構描述 (schema)。對於異質遷移,您需要將其與 AWS Schema Conversion Tool (SCT) 搭配使用。SCT 能轉換預存程序、檢視表、觸發器、序列和特定方言的類型 — 例如,將 Oracle PL/SQL 轉換為 PostgreSQL PL/pgSQL,或將 T-SQL 轉換為 Aurora MySQL。SCT 會產生一份評估報告,標示出需要手動重工的物件 (對於複雜的程式碼庫,通常佔 5–20%)。在跨引擎遷移中單獨使用 DMS 是一個常見的錯誤:雖然 DMS 可以建立基本的目標資料表,但它無法正確轉換預存程序或專有類型。對於同質遷移,則不需要 SCT — 使用原生工具 (mysqldump, pg_dump, RMAN) 加上 DMS CDC 就足夠了。
完整的跨引擎模式如下:
1. SCT: convert schema, apply to target RDS/Aurora
2. DMS full-load task: bulk copy existing data
3. DMS CDC task: capture ongoing changes from source
4. Cutover: stop writes at source, wait for CDC lag = 0, redirect app
備份與時間點復原
RDS 自動備份結合了每日快照與每 5 分鐘的交易日誌備份,可在保留期間 (1–35 天,預設 7 天) 內實現到任何一秒的時間點復原 (PITR)。還原操作會建立一個新的執行個體 — 您無法就地還原 — 因此必須更新應用程式的端點或 CNAME。手動快照的生命週期不受保留期間限制,且在執行個體刪除後仍會存在 (取決於最終快照的設定),可以跨區域複製以進行災難復原 (DR),也可以跨帳戶共享。
快速快照還原 (FSR) 適用於 EBS-backed 的快照,可消除延遲載入造成的效能損失,讓還原的磁碟區立即擁有完整效能 — 這在時間緊迫下,需要從一個快照啟動多個環境時非常有用。Aurora cloning 在同一區域內複製時完全繞過快照。DynamoDB PITR 是一項對應的功能,必須為每個資料表啟用,並在還原時產生一個新的資料表。
專用資料庫
當存取模式有特殊需求時,選擇專用引擎可以避免日後昂貴的架構重構。Amazon Neptune 是一個支援 Gremlin、openCypher 和 SPARQL 的託管圖形資料庫 — 適用於需要遍歷關係的查詢 (如詐騙集團、社交圖譜、知識圖譜),在這些情境下,關聯式引擎中的遞迴性 join 會變得極其昂貴。Amazon QLDB 是一個不可變、可透過密碼學驗證的分類帳資料庫,擁有一個僅供附加的日誌,適用於需要防竄改稽核的紀錄系統 — 如供應鏈溯源、金融交易、監理所記錄。DynamoDB 是任何規模下,需要個位數毫秒級延遲的鍵值或文件存取的預設選擇,可使用單一資料表設計、用於階層式存取的複合排序鍵,以及用於替代存取路徑的 GSI 等模式。將這些工作負載強行塞入 RDS 會產生鎖定競爭 (分類帳寫入)、查詢複雜性 (圖形遍歷) 或擴展上限 (高吞吐量鍵值) — 每一個問題在事後補救的成本都遠高於在設計之初就做出正確的選擇。
陷阱總結
- 將 Read Replica 當作 HA (高可用性)。 這是非同步的、沒有自動晉升機制、晉升時端點會變更、進行中的交易會遺失。Multi-AZ 才是 HA 的解決方案。
- 使用 Multi-AZ 進行讀取擴展。 在標準的 RDS Multi-AZ 中,備用 (Standby) 執行個體是不可讀取的。請使用 Read Replica 或 Aurora Replica。
- 在生產環境中使用 Single-AZ。 沒有容錯移轉目標;任何 AZ 事件或執行個體重啟都會導致服務中斷。Multi-AZ 的成本大約是兩倍,但能帶來質的可用性躍升。
- 預設將 Replica 的大小設定得與 Primary 相同。 Replica 通常需要較少的資源;除非 Replica 是晉升目標,否則應根據測量的工作負載來調整其大小。
- 認為 On-demand DynamoDB 總是比較便宜。 它的每次請求成本大約是 6-7 倍;對於穩定的工作負載,Provisioned + Auto-scaling 的組合更具優勢。
- 針對單一區域的需求使用 Global Tables。 除非需要多區域使用者鄰近性或災難復原 (DR),否則這會使成本加倍並削弱一致性,卻沒有帶來好處。
- 認為 Aurora Global Database 的次要資料庫 (secondaries) 可以處理寫入。 它們是唯讀的,直到透過受控的容錯移轉將其晉升為主資料庫。
- Lambda 直接連接 RDS,未使用 RDS Proxy。 連線風暴會耗盡
max_connections;函式內的連線池在跨並行執行環境時沒有幫助。 - 單獨使用 DMS 進行異質遷移。 DMS 只移動資料,不移動結構 (schema)。請與 SCT 搭配使用。
- 使用固定的 RDS 儲存空間,且未啟用自動擴展或設定
FreeStorageSpace警報。 這是潛在的服務中斷——storage-full狀態會拒絕所有寫入操作。 - 使用快取卻沒有失效策略。 會造成無聲的資料過時 (silent staleness)。TTL、穿透寫入 (write-through) 或明確的失效機制是不可或缺的。
- 試圖透過 DAX 或 GSI 實現強一致性讀取。 這兩種路徑都只提供最終一致性的資料。
← 內容交付、邊緣與效能最佳化 · 所有領域 · 分析、資料湖、ML 與特殊工作負載 →
練習這些題目 → · 在 ExamRoll.io 上限時練習 →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
通過考試 →