Quy mô và hiệu năng
Chất lượng ở quy mô 500.000 người dùng
Alliance App hướng tới 500.000 người dùng. Ở quy mô đó, một lỗi hiếm vẫn là hàng trăm người, và một bản release xấu lan nhanh hơn khả năng phản ứng thủ công. Bài này nói cách QC phải đổi theo.
Nội dung bài
Thuật ngữ trong bài (12)
- quality gate · cổng chất lượng
- sprint · chu kỳ làm việc
- pipeline · dây chuyền tự động
- feature flag · công tắc tính năng
- release · bản phát hành
- rollback · quay về bản cũ
- alerting · cảnh báo tự động
- incident · sự cố
- low-end · máy cấu hình thấp
- API · giao diện lập trình
- migration · chuyển đổi dữ liệu
- timeout · hạn chờ
Con số phải nhớ
Mục tiêu quy mô của Alliance App là 500.000 người dùng. Hãy đổi mọi tỷ lệ phần trăm ra số người thật trước khi nói "chấp nhận được":
| Tỷ lệ nghe có vẻ nhỏ | Số người dùng bị ảnh hưởng |
|---|---|
| 5% | 25.000 |
| 1% | 5.000 |
| 0,5% | 2.500 |
| 0,1% | 500 |
| 0,01% | 50 |
Luật viết báo cáo: mọi lỗi đều báo kèm số người, không chỉ báo tỷ lệ. "Tỷ lệ lỗi 0,3%" nghe như chuyện nhỏ. "1.500 người không gửi được tin nhắn" thì không ai nhầm lẫn về mức độ.
Hệ quả trực tiếp với module Bán hàng: 0,1% đơn bị trùng, với 20.000 đơn một ngày, là 20 đơn sai mỗi ngày — mỗi đơn là một cuộc gọi khiếu nại và một lần hoàn tiền. Đó là lý do chuẩn riêng từng module đặt mức dung sai cho tiền bằng không.
Ba thứ đổi hẳn khi vượt mốc
1. Lỗi hiếm trở thành lỗi thường xuyên
Ở 500 người dùng, một lỗi chỉ xảy ra khi "mất mạng đúng lúc bấm nút" gần như không bao giờ thấy. Ở 500.000 người dùng, nó xảy ra mỗi ngày, nhiều lần.
Nghĩa là mọi trường hợp biên trong bài những điều bắt buộc với dev chuyển từ lý thuyết sang chắc chắn sẽ xảy ra. Race condition, timeout, bấm hai lần, xoay màn hình giữa chừng, app bị hệ điều hành kill khi đang gửi — tất cả đều sẽ được nghiệm thu bởi người dùng thật nếu ta không chặn trước.
2. Phát hiện thủ công không còn kịp
Một bản release xấu bật 100% có thể chạm 500.000 người trong vài giờ. Không có đội hỗ trợ nào phản ứng kịp bằng tay.
Nghĩa là phát hiện phải tự động và rollback phải nhanh hơn tốc độ lan. Toàn bộ cơ chế ở release từng phần và feature flag và giám sát và cảnh báo không phải là thứ "làm cho đẹp" — ở quy mô này chúng là điều kiện sống còn.
3. Tải trở thành một loại lỗi riêng
Code đúng về logic vẫn có thể hỏng vì tải: truy vấn không có chỉ mục, vòng lặp gọi cơ sở dữ liệu, kết nối thời gian thực giữ quá lâu, bộ nhớ rò rỉ chậm. Những lỗi này không xuất hiện ở môi trường test với 10 người dùng.
Nên phải có một loại quality gate riêng cho hiệu năng — xem test tải và hiệu năng.
Ngân sách lỗi
Không có hệ thống nào đạt 100%. Cách quản lý đúng là định trước mức hỏng được phép, rồi dùng nó để quyết định làm tính năng hay làm ổn định.
| Mức sẵn sàng mục tiêu | Thời gian hỏng cho phép mỗi tháng | Với 500.000 người |
|---|---|---|
| 99,9% | 43 phút | Khoảng 22.000 người bị ảnh hưởng mỗi lần hỏng 1 giờ |
| 99,5% | 3 giờ 39 phút | Quá lỏng cho module Bán hàng |
| 99,95% | 21 phút | Mức nên hướng tới cho Bán hàng |
Cách dùng ngân sách lỗi:
- Còn ngân sách: được phép release nhanh, được phép thử nghiệm.
- Hết ngân sách trong tháng: dừng phát hành tính năng mới, cả đội chuyển sang làm ổn định cho tới đầu tháng sau.
Luật này quan trọng ở chỗ nó tự động chuyển ưu tiên, không cần ai đi thuyết phục ai. Nó cũng chấm dứt tranh cãi muôn thuở giữa "làm thêm tính năng" và "sửa cho chắc".
Thang release đã tính lại theo quy mô
Các nấc phần trăm nhỏ ở quy mô này vẫn là nhóm người đủ lớn để đọc được số liệu:
| Nấc | Tỷ lệ | Số người | Chờ tối thiểu | Vì sao đủ |
|---|---|---|---|---|
| 0 | Nội bộ | ~50 | 1 ngày | Bắt lỗi thô |
| 1 | 0,5% | 2.500 | 1 ngày | Đủ để thấy crash và lỗi API |
| 2 | 2% | 10.000 | 1 ngày | Đủ để thấy chỉ số hành vi |
| 3 | 10% | 50.000 | 2 ngày | Đủ để thấy tác động nghiệp vụ |
| 4 | 50% | 250.000 | 2 ngày | Kiểm tra tải một nửa |
| 5 | 100% | 500.000 | — | Xoá cờ trong 2 sprint |
Tính năng chạm tới tiền, quyền hoặc dữ liệu cá nhân thì bắt đầu từ nấc 1 ở mức 0,1% và gấp đôi thời gian chờ ở mỗi nấc.
Điểm mấu chốt: nấc 1 và 2 tồn tại vì ở đó thiệt hại còn sửa được. Nhảy thẳng lên 100% là đánh cược toàn bộ tập người dùng vào chất lượng của một lần review.
Dữ liệu lớn lên cũng gây lỗi
Phần lớn lỗi quy mô không nằm ở số người đồng thời, mà ở lượng dữ liệu tích lại:
| Chỗ hay vỡ | Biểu hiện | Chặn bằng cách nào |
|---|---|---|
| Danh sách không phân trang | App chậm dần rồi treo với người dùng cũ | Bắt buộc phân trang bằng con trỏ, không dùng offset |
| Truy vấn thiếu chỉ mục | Nhanh ở test, chậm chết ở production | Review kế hoạch truy vấn cho mọi truy vấn mới |
| Tải hết lịch sử chat | Tốn bộ nhớ, crash máy yếu | Chỉ tải cửa sổ gần nhất |
| Báo cáo doanh số quét toàn bảng | Timeout khi dữ liệu lớn | Bảng tổng hợp sẵn, tính theo lô |
| Migration khoá bảng | Ngừng dịch vụ khi triển khai | Migration phải chạy được trên bảng lớn, có bước quay lui |
Quy tắc bắt buộc: mọi truy vấn mới phải được thử trên tập dữ liệu cỡ production, không phải trên vài chục dòng dữ liệu mẫu. Có một bộ dữ liệu giả cỡ lớn là hạ tầng test bắt buộc, không phải thứ tuỳ chọn.
Đây đúng là shift left: tìm ra truy vấn chậm lúc viết code tốn 10 phút, tìm ra lúc người dùng thứ 300.000 đăng ký tốn một đêm mất ngủ.
Ba lớp bảo vệ, xếp theo thứ tự
| Lớp | Chặn cái gì | Ở đâu |
|---|---|---|
| Ngăn lỗi sinh ra | Lỗi logic, lỗi biên, truy vấn chậm | Yêu cầu rõ, review, test, quality gate |
| Giới hạn thiệt hại | Lỗi đã lọt ra | Feature flag, release từng phần, giới hạn tần suất |
| Phục hồi nhanh | Lỗi đã ảnh hưởng người dùng | Cảnh báo tự động, rollback, quy trình sự cố |
Ở quy mô nhỏ, chỉ lớp một là đủ sống. Ở 500.000 người dùng, thiếu lớp hai là cá cược, và thiếu lớp ba là tự sát. Một đội tốt đầu tư đều cả ba, và biết rằng lớp một không bao giờ đạt 100%.
Những gì phải có trước khi mở rộng
Danh sách này là điều kiện để đi từ quy mô hiện tại lên mục tiêu. Thiếu mục nào thì chưa mở rộng người dùng.
- Feature flag chạy được và tắt được trong 30 giây, có người trực biết cách tắt.
- Cảnh báo tự động cho mọi chỉ số trong giám sát và cảnh báo.
- Test tải đạt mục tiêu ở mức gấp đôi tải dự kiến.
- Bộ dữ liệu thử cỡ lớn, dùng trong pipeline.
- Quy trình sự cố có người trực và đã diễn tập ít nhất một lần.
- Đối soát tự động cho module Bán hàng, chạy hằng ngày.
- Migration đã thử trên bản sao dữ liệu cỡ production.
- Ngân sách lỗi được đặt và được theo dõi hằng tháng.
Diễn tập ở mục 5 hay bị bỏ nhất. Quy trình sự cố chưa từng chạy thử thì lúc cần sẽ không chạy được — người ta sẽ không nhớ ai gọi ai, tắt cờ ở đâu, rollback bằng lệnh gì.

