Multi-region: khi cả một region chết
Tiếp đi: multi-region và disaster recovery.
Đây là bài cuối của chương. Kiến trúc hiện tại có thể rất tốt: Gateway, services, Redis, DB, Kafka, tất cả chạy nhiều instance trong Region Singapore. Nhưng nếu cả region chết thì sao?
Region Singapore 💀 → hệ thống 💀
Nhiều instance trong cùng region không cứu được lỗi cấp region.
1. Failure domain
A1, A2, A3 cùng một máy → máy chết → cả ba chết
rải ra nhiều máy → chịu được máy chết
rải ra nhiều AZ (zone) → chịu được mất một datacenter (xem bài 14.6)
rải ra nhiều region → chịu được mất cả vùng
Multi-AZ là mặc định cho production. Multi-region chỉ khi business thật sự yêu cầu, vì đắt và phức tạp hơn rất nhiều.
2. Requirements: RTO và RPO
RTO (Recovery Time Objective) → TIME : được phép down bao lâu?
RTO = 30 phút: region chết 10:00 → phục vụ lại trước ~10:30
RPO (Recovery Point Objective) → DATA : chấp nhận mất bao nhiêu dữ liệu?
RPO = 5 phút: thảm hoạ có thể mất tối đa ~5 phút dữ liệu
Câu đầu tiên trong phỏng vấn: "RTO và RPO mục tiêu là bao nhiêu?". Mọi lựa chọn sau đó đi ra từ hai con số này. Một hệ thống cũng không cần cùng RPO cho mọi loại dữ liệu: ảnh đại diện thì nới, sổ cái tài chính thì rất chặt.
3. Bốn chiến lược DR
Backup/Restore : Region A ──backup──► Object Storage (region khác)
thảm hoạ → dựng hạ tầng (Terraform), restore DB, deploy, chạy
Pilot Light : Region B có DB replica + hạ tầng tối thiểu, compute tắt
thảm hoạ → bật/scale compute, promote DB, chuyển traffic
Warm Standby : Region B chạy đủ stack ở 20% capacity
thảm hoạ → scale 20% → 100%, chuyển traffic
Active-Active : Global routing
/ \
Region A 50% Region B 50%
thảm hoạ → toàn bộ traffic sang B
| Chiến lược | RTO | RPO | Chi phí | Độ phức tạp |
|---|---|---|---|---|
| Backup/Restore | Giờ | Giờ (theo chu kỳ backup) | Thấp | Thấp |
| Pilot Light | Hàng chục phút | Giây–phút | Thấp–vừa | Vừa |
| Warm Standby | Phút | Giây–phút | Vừa–cao | Vừa |
| Active-Active | Gần 0 | Gần 0 (nếu xử lý được conflict) | Cao | Rất cao |
Không phải hệ thống nào cũng cần active-active. Hệ thống nội bộ chấp nhận RTO vài giờ thì backup/restore là đủ.
4. Kiến trúc warm standby (lựa chọn phổ biến)
Users
│
Global DNS / Traffic routing (health check)
/ \
▼ (100%) ▼ (0%, sẵn sàng)
┌─────────── Region A ──────────┐ ┌────────── Region B ──────────┐
│ Gateway → Services (N) │ │ Gateway → Services (N/5) │
│ Redis (cache, rebuild được) │ │ Redis (trống) │
│ DB primary ───────────────────┼──►│ DB replica (async) │
│ Kafka ────── MirrorMaker ─────┼──►│ Kafka │
│ Object storage ── CRR ────────┼──►│ Object storage │
└───────────────────────────────┘ └──────────────────────────────┘
+ secrets/config replicate, IaC giống nhau, runbook failover, diễn tập định kỳ
5. Global routing
DNS hoặc edge (Route 53, Azure Front Door/Traffic Manager, Cloudflare) kiểm tra health của mỗi region. Region A không khoẻ thì trả về địa chỉ region B.
- DNS có TTL: client cache bản ghi cũ, nên đặt TTL thấp (30–60s) và chấp nhận vài phút để traffic chuyển hết.
- Routing chỉ trả lời "request đi đâu?". Nó không giải quyết dữ liệu có nhất quán không.
- App phải stateless: session nằm trong RAM của region A thì sang B sẽ mất. Dùng token hoặc state bền vững.
6. Không chỉ DB cần DR
| Thành phần | Cách DR | Ghi chú |
|---|---|---|
| DB | Cross-region replica / global database | Phần khó nhất |
| Redis cache | Không cần, rebuild từ DB | Nếu đúng chỉ là cache |
| Kafka | MirrorMaker 2 / cluster linking | Offset khác nhau → consumer phải idempotent, chấp nhận replay |
| Object storage | Cross-region replication | RPO theo mức quan trọng |
| Secrets, config, IaC | Replicate, deploy được ở cả hai nơi | Hay bị quên nhất |
Chạy thêm Spring Boot ở region khác thì dễ rồi. Vậy cái khó của multi-region nằm ở đâu?
Đúng, khó nhất là dữ liệu: replication, consistency, conflict, latency.
1. Single-writer (primary ở một region)
Region A: primary (WRITE) ──async──► Region B: replica (READ)
A chết → promote B thành primary
Ưu: nhất quán đơn giản, không có conflict. Nhược: thời gian failover, user ở xa ghi chậm (phải đi về region A), và replication lag.
2. Replication lag chính là RPO
Region A: X = 100 ──(chưa kịp replicate)── Region B: X = 90
A chết → promote B → X = 90 → mất cập nhật cuối = data loss
| Replication | RPO | Đổi lại |
|---|---|---|
| Async | > 0 (bằng lag, thường giây) | Ghi nhanh, region B chết không ảnh hưởng A |
| Sync cross-region | ≈ 0 | Mỗi lần ghi chờ thêm một vòng RTT (~50–200ms); B chậm thì A cũng chậm |
Không có free lunch. Xem lại Replication.
3. Multi-writer (active-active ghi cả hai nơi)
User 1 sửa X ở Region A: X = "a"
User 2 sửa X ở Region B: X = "b" (cùng lúc)
→ replicate chéo → X = ? ⚠️ conflict
Các cách giải conflict:
- Tránh conflict (tốt nhất): mỗi user có "home region", chỉ ghi dữ liệu của mình ở region đó. Partition dữ liệu theo region.
- Last-writer-wins: theo timestamp. Đơn giản nhưng âm thầm mất bản ghi.
- Merge: CRDT (counter, set), hoặc logic nghiệp vụ tự gộp.
- Dữ liệu cần nhất quán mạnh (số dư tiền): chỉ một region được ghi, hoặc dùng DB consensus toàn cầu (Spanner, CockroachDB) và chấp nhận latency.
4. CAP trong thực tế
Network partition: Region A ✂ Region B
Cả hai vẫn nhận ghi → availability ↑, conflict ↑ (AP)
Một bên dừng ghi → consistency ↑, availability ↓ (CP)
Thực tế chọn theo từng loại dữ liệu: giỏ hàng, like, feed chọn AP; số dư, tồn kho chọn CP. Chi tiết ở Consistency & CAP.
Active-active RTO gần bằng 0, vậy sao không làm active-active cho mọi hệ thống luôn?
Vì nó tăng độ phức tạp rất nhiều, nhất là ở dữ liệu, và chi phí gần như gấp đôi. Câu trả lời tốt trong phỏng vấn:
Em sẽ hỏi RTO/RPO và chi phí chấp nhận được trước. Active-active chỉ đáng khi business thật sự cần downtime gần 0 và dữ liệu chia được theo region hoặc chịu được eventual consistency.
1. Failover phải làm gì (runbook warm standby)
1. Phát hiện: health check region A fail liên tục N phút, người trực xác nhận
2. Chặn ghi ở A (nếu A còn sống một phần) → tránh split-brain
3. Promote DB replica ở B thành primary
4. Scale compute B 20% → 100%
5. Chuyển DNS/traffic sang B
6. Kiểm tra: smoke test, metric lỗi, độ trễ
7. Sau sự cố: đối soát dữ liệu chưa kịp replicate, dựng lại A thành replica
Bước 2 rất quan trọng: nếu A chỉ mất kết nối chứ chưa chết, hai primary cùng nhận ghi gọi là split-brain.
2. DR chưa diễn tập = chưa có DR
Diễn tập failover định kỳ (game day), đo RTO/RPO thực tế. Backup chưa từng restore thử thì không biết có dùng được không (xem Backup & restore).
Phỏng vấn hỏi "hệ thống của bạn chịu được mất cả một region không" thì trả lời sao?
Q1. RTO và RPO là gì?
🇻🇳 Tiếng Việt:
RTO là thời gian tối đa được phép down khi có sự cố. RPO là lượng dữ liệu tối đa được phép mất, tính theo thời gian. Hai con số này do business quyết định và chúng chọn ra chiến lược DR.
🇬🇧 English:
RTO is the maximum acceptable downtime after a disaster. RPO is the maximum acceptable data loss, measured in time. The business sets both numbers, and they drive the choice of DR strategy.
Q2. So sánh các chiến lược DR?
🇻🇳 Tiếng Việt:
Backup/restore rẻ nhất nhưng RTO tính bằng giờ. Pilot light giữ DB replica và hạ tầng tối thiểu ở region khác. Warm standby chạy sẵn bản thu nhỏ, failover trong vài phút. Active-active phục vụ ở cả hai region, RTO gần 0 nhưng đắt và phải xử lý write conflict. Em thường chọn warm standby với single writer, trừ khi requirement đòi hỏi hơn.
🇬🇧 English:
Backup and restore is the cheapest but has an RTO of hours. Pilot light keeps a database replica and minimal infrastructure in another region. Warm standby runs a scaled-down copy and fails over in minutes. Active-active serves traffic from both regions with near-zero RTO, but it is expensive and must handle write conflicts. I usually choose warm standby with a single writer unless the requirements demand more.
Q3. Multi-region khó nhất ở đâu?
🇻🇳 Tiếng Việt:
Ở dữ liệu. Replication async thì lag chính là RPO; replication sync thì mỗi lần ghi chậm thêm một vòng cross-region. Ghi ở nhiều region thì có conflict, nên em ưu tiên chia dữ liệu theo home region, và chỉ cho dữ liệu cần nhất quán mạnh được ghi ở một nơi. Routing failover chỉ quyết định request đi đâu, không giải quyết consistency.
🇬🇧 English:
The data. With asynchronous replication, the lag is your RPO; with synchronous replication, every write pays a cross-region round trip. Writing in multiple regions causes conflicts, so I prefer partitioning data by home region and keeping strongly consistent data single-writer. Routing failover only decides where requests go; it doesn't solve consistency.
Cách nhớ ngắn gọn
- RTO → TIME, RPO → DATA. Hỏi hai con số trước khi thiết kế.
- Backup → Pilot Light → Warm Standby → Active-Active: rẻ/chậm → đắt/nhanh.
- App dễ, data khó: lag = RPO, multi-writer = conflict.
- Routing ≠ consistency. Chặn split-brain. DR chưa diễn tập = chưa có DR.
Tổng kết chương 14: System Design
| Bài | Đề | Concept chính |
|---|---|---|
| 15.1 | Khung trả lời phỏng vấn | Requirements → scale → API → data → kiến trúc → deep dive → trade-off |
| 15.2 | Requirement, SLO, capacity | Functional/non-functional, SLO, ước lượng QPS và storage |
| 15.3 | Scale app, scale DB | Stateless, load balancer, cache, read replica, sharding |
| 15.4 | Rate limiting | Token bucket, sliding window, Redis |
| 15.5 | API Gateway | Một cửa vào, auth, routing |
| 15.6 | High Availability | Redundancy, health check, failover, multi-AZ |
| 15.7 | URL Shortener | Sinh ID, cache, read-heavy, sharding |
| 15.8 | File Upload | Object storage, signed URL, CDN |
| 15.9 | Notification | Queue, retry, DLQ, priority |
| 15.10 | Ticket Booking | Race condition, locking, hold/expire |
| 15.11 | Payment | Idempotency, UNKNOWN, webhook, reconciliation |
| 15.12 | Flash sale | Atomic claim, Redis Lua, waiting room, oversell |
| 15.13 | Chat | WebSocket, presence, ordering per conversation, dedup |
| 15.14 | News Feed | Fan-out write/read, celebrity, hybrid |
| 15.15 | Banking transfer | Double-entry ledger, lock ordering, saga, đối soát |
| 15.16 | Multi-region | RTO/RPO, DR strategy, replication, CAP |
Tự kiểm tra
RTO và RPO khác nhau thế nào?
RTO là thời gian được phép down. RPO là lượng dữ liệu được phép mất (tính theo thời gian).
Pilot light khác warm standby chỗ nào?
Pilot light chỉ có dữ liệu replicate và hạ tầng tối thiểu, compute chưa chạy. Warm standby chạy sẵn cả stack ở capacity nhỏ, nên failover nhanh hơn.
Vì sao replication lag liên quan RPO?
Region primary chết thì phần dữ liệu chưa kịp replicate sẽ mất. Lag càng lớn, RPO thực tế càng lớn.
DNS failover có giải quyết consistency không?
Không. Nó chỉ quyết định request đi tới region nào. Dữ liệu nhất quán phụ thuộc replication và chiến lược ghi.
Split-brain là gì, tránh thế nào?
Hai region cùng nghĩ mình là primary và cùng nhận ghi. Tránh bằng cách chặn ghi ở region cũ (fencing) trước khi promote region mới.