Thiết kế hệ thống ngân hàng bằng Java microservices trên AWS
Bám theo bài toán chuyển tiền đã học ở Java concurrency, nhưng mở rộng từ một process thành hệ thống production: ledger đúng, API retry-safe, workflow phục hồi được và Auto Scaling không phá capacity của database.
1. Scope và invariant trước công nghệ
Critical journey: xem số dư, chuyển tiền nội bộ và tra trạng thái giao dịch. Invariant quan trọng nhất là tiền không tự sinh/mất; một transfer chỉ được post một lần; ledger đã post là immutable và mọi correction tạo entry mới. Tách
available balance
,
book balance
và trạng thái
PENDING/POSTED/FAILED/REVERSED/MANUAL_REVIEW
.
2. Boundary đề xuất
| Component | Ownership | Ghi chú |
|---|---|---|
| Transfer Service | Transfer intent, state machine, idempotency | Orchestrate workflow; không tự sửa ledger của service khác. |
| Ledger Service | Accounts, immutable debit/credit entries, balance projection | Strong invariant; double-entry trong một local transaction. |
| Risk/Limits | Velocity, daily limit, fraud decision | Đồng bộ nếu quyết định bắt buộc trước post; optional signal có thể async. |
| Notification | Email/SMS/push delivery | Async, không nằm trên critical correctness path. |
| Audit/Reconciliation | Evidence và mismatch repair workflow | Không thay source-of-truth ledger. |
Ban đầu có thể triển khai Transfer + Ledger trong modular monolith để giữ transaction đơn giản. Chỉ tách khi ownership, scale hoặc release cadence thực sự khác; không tạo microservice theo từng table.
3. API retry-safe
POST /transfers
Idempotency-Key: 2e9...
{
"fromAccountId": "A1",
"toAccountId": "A2",
"amount": 100000,
"currency": "VND"
}
Lưu key + request fingerprint + trạng thái/kết quả trong cùng transaction với transfer intent. Cùng key/cùng payload trả outcome cũ; cùng key/khác payload trả conflict. Client timeout không được suy ra thất bại: query
GET /transfers/{id}
. Authentication không thay object-level authorization; account phải thuộc principal và policy cho phép operation.
4. Ledger và concurrency
Post debit và credit bằng double-entry trong cùng local ACID transaction; tổng entry theo transaction bằng zero. Dùng row lock theo thứ tự ổn định hoặc optimistic version + bounded retry tùy contention. Unique constraint trên business transaction/idempotency key là hàng rào cuối chống double posting. Không dùng floating point cho tiền; lưu minor unit integer hoặc decimal với currency/scale rõ.
synchronized
/
AtomicLong
bảo vệ được nhiều instance.
5. Distributed workflow
- Nhận request, validate và persist transfer intent/idempotency.
- Risk/limit decision có deadline và result audit.
- Gửi command post ledger qua local call hoặc durable message.
- Ledger post debit/credit atomically và ghi Outbox.
- Consumer cập nhật transfer state idempotently; notification chạy async.
- Reconciliation tìm transfer stuck, duplicate/missing effect và đưa case bất định sang manual review.
Outbox đóng atomicity gap DB + broker nhưng không tạo exactly-once end-to-end. Consumer cần Inbox/unique event ID; retries có backoff, jitter, DLQ và owner. Reversal là business transaction mới, không xóa/sửa lịch sử ledger.
6. Reference architecture trên AWS
Route 53 -> CloudFront/WAF -> ALB/API Gateway
|
Java Transfer/Ledger services
ECS/Fargate | EKS | EC2 ASG
| | |
Aurora/RDS ElastiCache SQS/MSK
| |
PITR/backups async consumers
CloudWatch + OpenTelemetry | Secrets Manager/KMS | IAM roles
Compute chạy ít nhất hai AZ; data store chọn Multi-AZ theo RTO/RPO. Private subnet cho application/data, IAM role ngắn hạn, encryption in transit/at rest và audit log không chứa credential/PII nhạy cảm. Multi-Region chỉ khi requirement biện minh consistency, failover và operational cost.
7. Auto Scaling đúng cách
| Workload | Signal tốt | Guardrail |
|---|---|---|
| Transfer HTTP | Request count/target, concurrency, p95 latency | Min/max, warmup, scale-in stabilization, ALB drain. |
| SQS consumer | Backlog age và messages/worker | Visibility timeout, idempotency, downstream capacity. |
| EKS pods | HPA theo CPU/concurrency/custom metric | Requests/limits đúng; node autoscaler phải kịp cấp capacity. |
| EC2/ECS | Target tracking hoặc step scaling | Multi-AZ, health grace period, lifecycle hooks. |
CPU không phải metric mặc định cho mọi service. Auto Scaling có detection + provisioning + JVM/Spring warmup lag; flash burst cần headroom, scheduled scaling hoặc queue. Scale-out caller không làm RDS mạnh hơn và có thể gây connection storm.
8. Capacity contract cho Java/JVM
-
max DB connections ≥ replicas × Hikari maximumPoolSize + operational headroom; giới hạn replica theo DB budget. -
Đặt container memory với headroom cho heap, metaspace, direct buffers, thread stacks và native memory; không đặt
-Xmxbằng toàn bộ limit. - Bound executor queue/concurrency theo downstream; virtual threads không xóa DB connection limit.
- Readiness chỉ true sau startup dependency tối thiểu; liveness không fail chỉ vì RDS chập chờn để tránh restart cascade.
- Graceful shutdown: deregister/drain, ngừng nhận request/message, hoàn tất hoặc trả work an toàn, đóng pool trong deadline.
9. Availability, security và operations
Định nghĩa SLI theo tỷ lệ transfer đạt terminal outcome đúng trong latency mục tiêu, không chỉ HTTP 200. Alarm error rate, p95/p99, stuck-transfer age, reconciliation mismatch, queue age, pool wait, DB saturation và Auto Scaling không đạt desired capacity. Deployment canary/blue-green phải hỗ trợ mixed versions và expand-migrate-contract. Dùng least privilege, maker-checker cho operation nhạy cảm, immutable audit, rate/amount limits và tested break-glass procedure.
10. Failure matrix cần nói trong interview
- Client timeout sau commit: trả/query outcome bằng idempotency key, không post lại.
- Service crash sau DB commit trước publish: Outbox relay publish sau restart.
- Duplicate event: Inbox/unique transaction key bỏ effect lặp.
- RDS saturated: shed/reject sớm, giới hạn concurrency/retry, không scale compute vô hạn.
- AZ failure: load balancer route sang AZ còn lại; capacity còn lại phải chịu được traffic.
- Scale-in giữa transaction/message: connection draining và consumer termination protocol.
- Unknown external-bank outcome: trạng thái UNKNOWN/PENDING, reconciliation và manual review; không báo success giả.
11. Design review checklist
- Money invariant và source of truth được phát biểu rõ.
- Idempotency có durable uniqueness và payload fingerprint.
- Ledger immutable, double-entry và correction bằng reversal.
- Mỗi timeout/duplicate/crash có observable state và recovery path.
- Scaling metric gần bottleneck và đã load test qua warmup lag.
- Replica × pool size nằm trong DB/downstream budget.
- Readiness, drain, scale-in và AZ failure đã diễn tập.
- SLO, security, audit, reconciliation, RPO/RTO và cost có owner.