RDS / ElastiCache / DynamoDB:你的資料該託管還是自管?

你有一個 PostgreSQL 跑在 EC2 上,半夜三點 disk full 你被叫起來修。或者你的 Redis 掛了整個 App 跟著掛。託管資料庫能救你的睡眠,但要先搞懂差異和成本。

先講結論

RDS 是託管的關聯式資料庫,支援 PostgreSQL、MySQL、MariaDB、Oracle、SQL Server。它幫你處理 patch、備份、failover,讓你專心寫 SQL。ElastiCache 是託管的 Redis/Memcached,適合 session、cache、排行榜。DynamoDB 是 NoSQL(Key-Value),毫秒級延遲、自動擴展,適合高流量但查詢模式固定的場景。大多數 App 的最佳起點是 RDS PostgreSQL + ElastiCache Redis


RDS:託管的關聯式資料庫

為什麼不自己裝 PostgreSQL?

你自己管RDS 幫你管
OS patch自動
備份自動每日 snapshot、最多 35 天保留
FailoverMulti-AZ 自動切換
Read Replica一鍵建立
監控Performance Insights 內建
版本升級排程自動升級

你省下來的時間,拿去優化 SQL query 更有價值。

建立 RDS PostgreSQL

# 建立 Subnet Group(RDS 需要至少兩個 AZ 的 subnet)
aws rds create-db-subnet-group --db-subnet-group-name prod-db-subnet \
  --db-subnet-group-description "Production DB subnets" \
  --subnet-ids subnet-private-1a subnet-private-1c
 
# 建立 RDS Instance
aws rds create-db-instance \
  --db-instance-identifier prod-postgres \
  --db-instance-class db.t3.medium \
  --engine postgres \
  --engine-version 16.4 \
  --master-username dbadmin \
  --master-user-password 'YourSecurePassword!' \
  --allocated-storage 100 \
  --storage-type gp3 \
  --vpc-security-group-ids sg-db \
  --db-subnet-group-name prod-db-subnet \
  --multi-az \
  --backup-retention-period 14 \
  --storage-encrypted \
  --performance-insights-enabled \
  --monitoring-interval 60 \
  --monitoring-role-arn arn:aws:iam::123456789012:role/rds-monitoring-role

Multi-AZ:高可用的關鍵

Multi-AZ 會在另一個 AZ 建立一個 Standby replica。主庫掛了,AWS 自動在 60-120 秒內切換到 Standby。你的 App 不用改 connection string——DNS 會自動指向新的主庫。

# 確認 Multi-AZ 狀態
aws rds describe-db-instances --db-instance-identifier prod-postgres \
  --query "DBInstances[0].MultiAZ"

踩坑:Multi-AZ failover 的時候,你的 App 會看到約 60 秒的 connection error。所以 App 的 DB driver 一定要設好 retry 和 connection pool 的重連機制。

Read Replica

讀多寫少的場景(報表、搜尋),把讀流量分到 Read Replica:

# 建立 Read Replica
aws rds create-db-instance-read-replica \
  --db-instance-identifier prod-postgres-read \
  --source-db-instance-identifier prod-postgres \
  --db-instance-class db.t3.medium
 
# App 端設定(以 Node.js pg 為例)
# 寫入用主庫 endpoint,讀取用 Read Replica endpoint

Aurora:RDS 的進化版

Aurora 是 AWS 自研的 DB engine,相容 PostgreSQL/MySQL,但底層儲存架構完全不同:

  • 效能比標準 RDS PostgreSQL 快 3 倍(官方說法,實測約 1.5-2 倍)
  • 儲存自動擴展到 128 TB
  • 6 份 replica 跨 3 個 AZ
  • 更貴(約比 RDS 貴 20-30%)

什麼時候選 Aurora? 當你的 DB 超過 1 TB、或需要超過 5 個 Read Replica 的時候。


ElastiCache:託管的 Redis

自架 Redis vs ElastiCache

面向自架 RedisElastiCache Redis
安裝自己裝一鍵
Cluster Mode自己設內建
FailoverSentinel 自己設自動
備份自己 RDB/AOF自動 snapshot
監控自己接 PrometheusCloudWatch 內建
版本升級自己來排程升級
# 建立 ElastiCache Subnet Group
aws elasticache create-cache-subnet-group \
  --cache-subnet-group-name prod-redis-subnet \
  --cache-subnet-group-description "Production Redis subnets" \
  --subnet-ids subnet-private-1a subnet-private-1c
 
# 建立 Redis Cluster(Cluster Mode Disabled,適合大多數場景)
aws elasticache create-replication-group \
  --replication-group-id prod-redis \
  --replication-group-description "Production Redis" \
  --engine redis \
  --engine-version 7.1 \
  --cache-node-type cache.t3.medium \
  --num-cache-clusters 2 \
  --automatic-failover-enabled \
  --cache-subnet-group-name prod-redis-subnet \
  --security-group-ids sg-redis \
  --at-rest-encryption-enabled \
  --transit-encryption-enabled

常見用途

  • Session Store:使用者登入 session 放 Redis,多台 App Server 共享
  • Cache:DB query 結果快取,TTL 設 5 分鐘
  • Rate Limiting:用 INCR + EXPIRE 做 API 限流
  • 排行榜:Sorted Set 天生適合

DynamoDB:高流量的 NoSQL 選擇

DynamoDB 適合:查詢模式固定、流量高、需要自動擴展。不適合:需要複雜 JOIN、查詢模式不確定、需要事後 ad-hoc 分析。

# 建立 DynamoDB Table
aws dynamodb create-table \
  --table-name UserSessions \
  --attribute-definitions \
    AttributeName=userId,AttributeType=S \
    AttributeName=sessionId,AttributeType=S \
  --key-schema \
    AttributeName=userId,KeyType=HASH \
    AttributeName=sessionId,KeyType=RANGE \
  --billing-mode PAY_PER_REQUEST \
  --tags Key=Environment,Value=production
 
# 寫入
aws dynamodb put-item --table-name UserSessions \
  --item '{"userId": {"S": "user-123"}, "sessionId": {"S": "sess-abc"}, "ttl": {"N": "1700000000"}}'
 
# 查詢
aws dynamodb query --table-name UserSessions \
  --key-condition-expression "userId = :uid" \
  --expression-attribute-values '{":uid": {"S": "user-123"}}'

DynamoDB 計費模式

模式適合費用
On-Demand流量不穩定按讀寫次數計費
Provisioned流量穩定預設 RCU/WCU + Auto Scaling

大多數新專案選 On-Demand,等流量穩定後再切 Provisioned 省錢。


選型決策框架

你的資料需要 JOIN / 複雜查詢嗎?
├─ 是 → RDS(PostgreSQL 或 MySQL)
│  └─ 超過 1TB / 需要多 Read Replica? → Aurora
├─ 否 → 查詢模式固定嗎?
│  ├─ 是 → DynamoDB
│  └─ 否 → 還是 RDS(彈性最大)
│
另外,你需要 Cache 嗎?
├─ Session / 快取 / 限流 → ElastiCache Redis
└─ 全文搜尋 → OpenSearch Service

自架 vs AWS

面向自架AWS 託管
PostgreSQL自己裝 + pgbouncer + barmanRDS + 內建連線池 + 自動備份
Redis自己裝 + SentinelElastiCache + 自動 failover
備份cron + pg_dump + S3自動每日 snapshot
升版自己停機升級排程、零停機(Read Replica 先升)
費用EC2 費用RDS 溢價 20-40%
DBA 時間少很多

如果你讀過 Infra 系列的 PostgreSQLPostgreSQL Advanced,RDS 就是幫你把那些 WAL 歸檔、replication、vacuum 的事都自動化了。Database Landscape 裡的選型框架在這裡依然適用。


K8s 映射

AWS DBK8s 對應
RDSStatefulSet + PVC(但不推薦,用託管 DB 吧)
ElastiCacheRedis Helm Chart / Redis Operator
DynamoDB沒有直接對應(K8s 上用 CockroachDB/TiDB)
Multi-AZ failoverPod anti-affinity + PDB
Read Replica應用層讀寫分離

認真建議:在 K8s 上跑 StatefulSet PostgreSQL 可以,但你得自己處理備份、failover、升版。如果你在 AWS 上,用 RDS 然後讓 K8s Pod 連 RDS endpoint 是最省心的做法。


系列導覽

上一篇下一篇
S3 Container Insights

資料庫是你的 App 最值錢的部分——省什麼都不要省 DB 的穩定性。