Requirement, SLO và ước lượng capacity
Tiếp đi: requirement và ước lượng traffic cho shop-app.
Ở bài trước, ta có khung 45 phút. Bài này đi sâu hai bước đầu: chốt requirement và ước lượng nhanh. Hai bước này quyết định gần như mọi lựa chọn phía sau.
1. Bài toán
Interviewer: "User có thể xem sản phẩm, thêm vào giỏ và checkout. Thiết kế shop-app."
Nếu không hỏi gì, ta không biết shop-app có 100 user hay 10 triệu user, có cần chịu flash sale không, có chấp nhận mất đơn hàng không.
2. Vấn đề
- Thiếu số liệu → không biết có cần cache, replica, sharding hay không.
- Không nói rõ "đủ tốt" là bao nhiêu → không biết thiết kế HA tới mức nào.
- Thiết kế quá to hoặc quá nhỏ so với nhu cầu thật.
3. Giải pháp: requirement hai loại
| Loại | Câu hỏi | shop-app |
|---|---|---|
| Functional | Hệ thống làm gì? | 1. Xem sản phẩm 2. Thêm vào giỏ 3. Checkout 4. Giữ hàng tồn kho 5. Thanh toán 6. Tạo order 7. Gửi notification |
| Non-functional | Hệ thống làm tốt tới mức nào? | High availability, scalable, không trừ tiền 2 lần, không oversell, latency hợp lý, reliable |
| Out of scope | Không làm gì (để tiết kiệm thời gian)? | Recommendation, review, chat với người bán |
Non-functional phải biến thành con số. Đó là việc của SLI/SLO/SLA.
| Khái niệm | Là gì | Ví dụ shop-app |
|---|---|---|
| SLI (Indicator) | Chỉ số đo được | Tỉ lệ request POST /checkout thành công; p99 latency |
| SLO (Objective) | Mục tiêu nội bộ cho SLI | 99.9% checkout thành công trong 30 ngày; p99 < 800 ms |
| SLA (Agreement) | Cam kết với khách, vi phạm thì có hậu quả (đền tiền) | 99.5%/tháng, vi phạm hoàn 10% phí |
SLA thường lỏng hơn SLO, để còn khoảng đệm trước khi phải đền.
4. Availability "mấy số 9"
| Availability | Downtime / năm | Downtime / tháng (30 ngày) |
|---|---|---|
| 99% | ~3.65 ngày | ~7.2 giờ |
| 99.9% | ~8.76 giờ | ~43 phút |
| 99.95% | ~4.38 giờ | ~22 phút |
| 99.99% | ~52.6 phút | ~4.3 phút |
| 99.999% | ~5.26 phút | ~26 giây |
Phần còn lại (100% − SLO) là error budget. SLO 99.9% cho phép ~43 phút lỗi/tháng; còn budget thì được deploy mạnh tay, hết budget thì dừng tính năng mới để tập trung ổn định.
Một điểm hay bị hỏi: các thành phần nối tiếp thì availability nhân với nhau.
Gateway 99.9% → Order 99.9% → DB 99.9%
Tổng ≈ 0.999 × 0.999 × 0.999 ≈ 99.7%
Hai instance song song, mỗi cái 99%:
Tổng ≈ 1 − (0.01 × 0.01) = 99.99% (nếu lỗi độc lập)
Vì vậy càng nhiều hop đồng bộ thì availability càng giảm; redundancy song song thì kéo nó lên. Chi tiết HA ở 15.6.
5. Back-of-envelope: ước lượng từng bước
Số nhớ nhanh: 1 ngày ≈ 86,400 giây ≈ 105 giây. Peak thường lấy 2–10 lần trung bình.
Bước 1: Giả định (nói to với interviewer)
DAU : 10 triệu
Mỗi user xem : 20 trang sản phẩm/ngày
Order : 1 triệu order/ngày
Kích thước 1 order : ~1 KB (cả order_items)
Response trang sản phẩm: ~20 KB JSON (ảnh đi CDN riêng)
Ảnh : 1 triệu sản phẩm × 5 ảnh × 200 KB
Bước 2: QPS
Read : 10M × 20 / 10^5 ≈ 2,000 req/s trung bình
peak ×5 ≈ 10,000 req/s
Write: 1M / 10^5 ≈ 10 order/s trung bình
peak (flash sale ×10) ≈ 100 order/s
Read : Write ≈ 200 : 1 → read-heavy
Bước 3: Storage
Order : 1M × 1 KB = 1 GB/ngày ≈ 365 GB/năm (+ index, replica ×3)
Ảnh : 1M × 5 × 200 KB = 1 TB → object storage (S3/Blob)
Bước 4: Bandwidth
Peak : 10,000 req/s × 20 KB = 200 MB/s ≈ 1.6 Gbps (chỉ API)
Ảnh : nặng hơn nhiều → bắt buộc CDN
Bước 5: Kết luận dẫn đường cho thiết kế
Read-heavy 10k req/s → cache (Redis), read replica, CDN
100 order/s peak → 1 PostgreSQL primary vẫn chịu được, chưa cần shard
365 GB/năm → partition orders theo tháng, archive dữ liệu cũ
Flash sale → rate limit, hàng đợi, chống oversell
Một ví dụ khác cùng tư duy: URL shortener có 10,000 redirect/s nhưng chỉ ~50 create/s. Thấy ngay READ >>> WRITE → cache là quyết định trung tâm.
6. Cách hoạt động: requirement chảy xuống kiến trúc
Requirement / SLO Estimate
│ │
└──────────┬────────────────┘
▼
Bottleneck dự đoán
(read? write? storage? latency?)
▼
Quyết định thiết kế
(cache, replica, shard, async, HA)
▼
Đo lại bằng SLI trên production
Để tính nhanh trong đầu, có thể viết một hàm nhỏ khi luyện tập:
record Estimate(long dau, int actionsPerUser, int peakFactor, int bytesPerItem) {
double avgQps() { return dau * actionsPerUser / 86_400.0; }
double peakQps() { return avgQps() * peakFactor; }
double gbPerDay(long itemsPerDay) { return itemsPerDay * bytesPerItem / 1e9; }
}
var reads = new Estimate(10_000_000, 20, 5, 20_000);
System.out.printf("avg=%.0f peak=%.0f%n", reads.avgQps(), reads.peakQps());
// avg=2315 peak=11574
7. So sánh nhanh
| SLI | SLO | SLA | |
|---|---|---|---|
| Bản chất | Số đo | Mục tiêu | Hợp đồng |
| Ai dùng | Monitoring | Team kỹ thuật | Business + khách hàng |
| Vi phạm thì | — | Hết error budget, dừng feature | Đền tiền/credit |
8. Khi nào nên / không nên
- Nên ước lượng khi số liệu thay đổi quyết định (cần shard hay chưa, cần CDN hay chưa).
- Không nên tính chính xác tới từng byte; làm tròn lũy thừa 10, ghi giả định rõ ràng.
- Không phải hệ thống nào cũng cần 99.99%. Internal tool 99.5% là đủ; checkout nên cao hơn trang "gợi ý sản phẩm".
SLO và SLA nghe giống nhau quá. Vậy chọn SLO 99.9% thì SLA nên để bao nhiêu?
Bạn hiểu gần đúng, chỉ cần chỉnh một điểm: SLO là mục tiêu nội bộ, SLA là lời hứa có hậu quả pháp lý/tiền bạc. Vì vậy SLA phải lỏng hơn SLO:
SLO nội bộ : 99.9% (~43 phút lỗi/tháng)
SLA với KH : 99.5% (~3.6 giờ lỗi/tháng)
└── khoảng đệm để kịp phát hiện và sửa trước khi phải đền
Và SLO nên đặt theo trải nghiệm người dùng, không theo máy: "99.9% checkout thành công" có ý nghĩa hơn "CPU dưới 70%". CPU chỉ là tín hiệu để điều tra.
Nếu mình ước lượng sai, ví dụ lệch 3–4 lần, thì có bị đánh giá thấp không?
Thường là không. Interviewer quan tâm bậc độ lớn (100 hay 10,000 req/s) và việc bạn dùng con số để ra quyết định. Lệch 3 lần không đổi kết luận "read-heavy, cần cache". Lệch 100 lần mới đổi kiến trúc (một DB vs sharding).
Điều bị đánh giá thấp là: tính xong rồi bỏ đó, không dùng con số vào thiết kế. Luôn kết bằng câu "Vì vậy...".
Phỏng vấn hỏi về non-functional requirement, SLO và ước lượng capacity thì trả lời sao?
Q1. Functional và non-functional requirement khác nhau thế nào?
🇻🇳 Tiếng Việt:
Functional mô tả hệ thống làm gì, ví dụ xem sản phẩm, checkout. Non-functional mô tả hệ thống làm tốt tới mức nào: availability, latency, scalability, consistency, security. Non-functional thường quyết định kiến trúc nhiều hơn, nên em luôn cố biến chúng thành con số như SLO.
🇬🇧 English:
Functional requirements describe what the system does, such as viewing products or checking out. Non-functional requirements describe how well it does it: availability, latency, scalability, consistency and security. Non-functional requirements usually drive the architecture more, so I try to turn them into numbers such as SLOs.
Q2. SLI, SLO, SLA là gì?
🇻🇳 Tiếng Việt:
SLI là chỉ số đo được, ví dụ tỉ lệ request thành công hay p99 latency. SLO là mục tiêu nội bộ cho SLI, ví dụ 99.9% trong 30 ngày. SLA là cam kết với khách hàng, vi phạm sẽ có đền bù, nên thường lỏng hơn SLO. Phần còn lại của SLO là error budget, dùng để cân bằng giữa tốc độ release và độ ổn định.
🇬🇧 English:
An SLI is a measured indicator, such as the success rate or p99 latency. An SLO is the internal target for that indicator, for example 99.9% over 30 days. An SLA is a contract with customers with penalties if violated, so it is usually looser than the SLO. The gap below 100% is the error budget, which balances release speed against stability.
Q3. Ước lượng QPS và storage cho một hệ thống thế nào?
🇻🇳 Tiếng Việt:
Em bắt đầu từ DAU và số hành động mỗi user, chia cho khoảng 10 mũ 5 giây mỗi ngày để ra QPS trung bình, rồi nhân hệ số peak. Storage bằng số bản ghi mỗi ngày nhân kích thước, nhân số năm lưu và số replica. Ví dụ 10 triệu DAU, 20 lượt xem mỗi người là khoảng 2 nghìn req/s, peak 10 nghìn; 1 triệu order 1 KB là khoảng 365 GB mỗi năm. Từ đó em kết luận hệ thống read-heavy, cần cache và CDN nhưng chưa cần sharding.
🇬🇧 English:
I start from daily active users and actions per user, divide by roughly 10 to the 5 seconds per day to get average QPS, then apply a peak factor. Storage is records per day times record size, times retention and replication factor. For example, 10 million DAU with 20 views each is about 2,000 requests per second, around 10,000 at peak; 1 million 1 KB orders a day is about 365 GB a year. So the system is read-heavy and needs caching and a CDN, but not sharding yet.
Cách nhớ ngắn gọn
- Functional = làm gì; non-functional = làm tốt tới đâu → biến thành SLO.
- SLI đo, SLO mục tiêu, SLA hợp đồng (lỏng hơn SLO).
- 99.9% ≈ 43 phút/tháng; 99.99% ≈ 4 phút/tháng; nối tiếp thì nhân.
- 1 ngày ≈ 105 giây; peak ×2–10; kết luận luôn bằng "Vì vậy...".
Tự kiểm tra
"Không oversell" là functional hay non-functional?
Thường xếp vào non-functional (correctness/consistency), vì nó nói hệ thống phải đúng tới mức nào, không phải một tính năng mới.
99.9% availability cho phép bao nhiêu downtime mỗi tháng?
Khoảng 43 phút (30 ngày × 24 × 60 × 0.001).
Ba service nối tiếp, mỗi cái 99.9%, tổng là bao nhiêu?
Khoảng 99.7%, vì availability nối tiếp nhân với nhau.
10 triệu DAU, mỗi người 20 request/ngày, peak ×5: peak QPS khoảng bao nhiêu?
10M × 20 / 105 ≈ 2,000 trung bình, peak ≈ 10,000 req/s.
Vì sao SLA thường lỏng hơn SLO?
Để có khoảng đệm: team phát hiện và sửa khi vi phạm SLO nội bộ trước khi chạm tới cam kết có đền bù.