Files
sys-analysis-design/sa-output/e-commerce/02-architecture/adr/ADR-005_message-backbone-sqs-fifo-eventbridge.md
Canhchimlac 343ad8bbbc save
2026-09-15 16:02:30 +07:00

177 lines
12 KiB
Markdown

# ADR-005 — Message backbone cho luồng đặt hàng là SQS FIFO (per-seller group) + EventBridge, không phải Kafka/MSK
*Tên file: `adr/ADR-005_message-backbone-sqs-fifo-eventbridge.md`*
| | |
|---|---|
| **Status** | `Proposed` *(🔴 radar ≥8 — theo `decision-radar.md §2`/§6, **không được chuyển `Accepted` khi chưa có `POC-01` PASS**)* |
| **Date** | 2026-09-15 |
| **Người quyết** | SA + Tech Lead (tích hợp/hạ tầng — `decision-radar.md §5`) |
| **Người đề xuất** | SA (qua skill `sa-2-architecture`, hoạt động `adr`) |
| **Điểm radar** | **~8/10** — 🔴 bắt buộc POC trước `Accepted` |
| **Supersedes** | — |
| **Superseded by** | — |
| **Liên quan** | `ASR-005` · `QAS-005` · `QAS-009` (A4 xung đột dòng 2) · `ARISK-01` · `POC-01` · `ADR-001` |
> ⚠️ **ADR bất biến sau khi `Accepted`.** Muốn đổi quyết định thì viết ADR mới có
> `Supersedes: ADR-005` và đổi trạng thái bản cũ thành `Superseded by`.
---
## 1. Bối cảnh
Luồng sự kiện `OrderPlaced`/`PaymentConfirmed` phải truyền tới ≥5 consumer (Commission & Payout,
Promotion & Loyalty, Review, Notification, Shipping & Fulfillment) sau khi đặt hàng, đồng thời
phải giữ đúng thứ tự xử lý trong cùng một seller (liên quan `DRV-06` — tính nhất quán dữ liệu tài
chính). `ASR-001`/`ADR-001` đã chọn hướng managed service (SQS/EventBridge) thay vì tự vận hành
Kafka/MSK — ADR này hình thức hoá cụ thể lựa chọn message backbone và **là quyết định đạt ngưỡng
radar ≥8** vì chưa có bài đo throughput thật trong ngữ cảnh này (`ASM-07`).
**Ràng buộc đang chi phối:**
| Nguồn | Nội dung |
|---|---|
| `ASR-005` | SQS FIFO (message group = `seller_id`) + EventBridge fan-out ≥5 consumer |
| `QAS-005` | Thông lượng sustained ≥100 msg/s, p99 publish→consume ≤2s, 0 mất message, fan-out lag ≤5s |
| `QAS-009` A4 dòng 2 | Xung đột: AWS giới hạn throughput **cứng cho một message group** SQS FIFO — seller volume cao có thể chạm trần group dù tổng hệ thống chưa chạm 100 msg/s |
| `CON-05` | Team chưa xác nhận kinh nghiệm vận hành Kafka/MSK production (`CTX §4.4`) |
**Cái đã biết chắc / cái còn là giả định:**
| Điều | 🟢 Đã kiểm chứng / 🔴 Giả định | Bằng chứng |
|---|---|---|
| SQS FIFO hỗ trợ message group theo key tuỳ chọn (`seller_id`) | 🟢 Đã kiểm chứng | Tài liệu AWS công khai |
| SQS FIFO + EventBridge đạt ≥100 msg/s sustained, p99 ≤2s trong ngữ cảnh payload `OrderPlaced` ~2KB tại `ap-southeast-1` | 🔴 Giả định (`ASM-07`) | `POC-01` — **chưa chạy** |
| Một seller volume rất cao không làm nghẽn message group riêng của seller đó tới mức ảnh hưởng SLA | 🔴 Giả định | Chưa có POC riêng cho kịch bản seller lệch tải — ghi nhận ở §7 |
## 2. Phương án đã cân nhắc
### PA-1 — Kafka / Amazon MSK tự quản lý
| | |
|---|---|
| **Mô tả** | Cụm Kafka/MSK làm xương sống bất đồng bộ, theo `SAD.md`/hồ sơ thầu (P1) |
| **Ưu** | Throughput cao, kiểm soát partition/consumer group linh hoạt hơn; công nghệ phổ biến cho hệ thống lớn |
| **Nhược** | Không có bằng chứng team từng vận hành Kafka/MSK production (`CTX §4.4`, `OQ-010` mở); effort dựng cụm riêng đã ước 70,2 MD (XL, +35% contingency, `WBS-03`); thêm một cụm phải patch/scale thủ công |
| **Chi phí đảo ngược** | Cao — bỏ Kafka/MSK sau khi đã có producer/consumer thật cần viết lại toàn bộ tầng tích hợp bất đồng bộ |
### PA-2 — SQS Standard + SNS fan-out (không FIFO)
| | |
|---|---|
| **Mô tả** | Dùng SQS Standard (at-least-once, không đảm bảo thứ tự) + SNS để fan-out cho nhiều consumer |
| **Ưu** | Throughput lý thuyết cao hơn FIFO (không giới hạn theo message group), chi phí thấp |
| **Nhược** | **Không đảm bảo thứ tự xử lý trong cùng seller** — vi phạm trực tiếp yêu cầu tính nhất quán tài chính của `DRV-06` (VD 2 sự kiện `OrderPlaced`/`PaymentConfirmed` cùng seller có thể xử lý sai thứ tự, gây sai lệch đối soát) |
| **Chi phí đảo ngược** | Trung bình — chuyển sang FIFO sau này cần viết lại consumer để xử lý idempotent/thứ tự, nhưng không cần đổi hạ tầng lớn |
### PA-3 — SQS FIFO (per-seller message group) + EventBridge fan-out *(chọn)*
| | |
|---|---|
| **Mô tả** | SQS FIFO với message group key = `seller_id` (đảm bảo thứ tự trong cùng seller), EventBridge rule fan-out tới ≥5 consumer |
| **Ưu** | Managed hoàn toàn (không cụm phải patch/scale thủ công); đảm bảo thứ tự đúng phạm vi cần (trong seller, không cần thứ tự toàn cục); khớp năng lực team hiện tại (không cần kinh nghiệm Kafka) |
| **Nhược** | Giới hạn throughput cứng theo **một** message group — seller volume rất cao có thể chạm trần riêng của seller đó (`QAS-009` A4); FIFO có overhead cao hơn Standard |
| **Chi phí đảo ngược** | Trung bình — nếu cần chuyển sang Kafka/MSK sau này (do `POC-01` fail hoặc traffic vượt xa dự kiến), phải viết lại toàn bộ tầng publish/consume |
### Bảng so sánh
| Tiêu chí | PA-1 (Kafka/MSK) | PA-2 (SQS Standard+SNS) | PA-3 (SQS FIFO+EventBridge) |
|---|---|---|---|
| Đảm bảo thứ tự trong seller (`DRV-06`) | ✅ (tự cấu hình partition key) | ❌ | ✅ |
| Rủi ro năng lực team (`CON-05`) | 🔴 Cao — chưa có kinh nghiệm | 🟢 Thấp | 🟢 Thấp |
| Chi phí vận hành (cụm tự quản lý) | 🔴 Cao | 🟢 Thấp | 🟢 Thấp |
| Rủi ro trần throughput 1 seller lớn | 🟢 Thấp (partition linh hoạt) | 🟢 Thấp | 🟠 Có (per-group limit) |
## 3. Quyết định
> **Chọn PA-3 — SQS FIFO (message group = `seller_id`) + EventBridge fan-out ≥5 consumer.**
**Vì sao:** Đây là phương án duy nhất vừa đảm bảo thứ tự trong phạm vi cần (theo seller, khớp
`DRV-06`) vừa khớp năng lực team hiện tại (`CON-05`, không cần vận hành cụm Kafka/MSK) — nhất
quán với hướng đi đã chọn ở `ADR-001`.
**Phạm vi áp dụng:** Toàn bộ luồng sự kiện `OrderPlaced`/`PaymentConfirmed` và các sự kiện tương
tự phát sinh sau đặt hàng.
### Điều kiện chuyển `Proposed → Accepted`
| Điều kiện | Ai xác nhận | Trạng thái hiện tại |
|---|---|---|
| **`POC-01` PASS** — sustained ≥100 msg/s/30 phút, p99 ≤2s, 0 mất message, fan-out lag ≤5s | Tech Lead + 1 DevOps | 🔴 **Chưa chạy** (`ARISK-01`, `OQ-012`) |
| Có phương án theo dõi/cảnh báo riêng cho seller volume cao (giảm rủi ro trần message group) | Tech Lead | Chưa thiết kế — xem §5 "Việc phát sinh" |
🔴 **Bắt buộc theo `decision-radar.md §2`/§6** — điểm radar ~8 (≥8) đồng nghĩa ADR này **không
được chuyển `Accepted`** cho tới khi `POC-01` chạy xong và PASS. Nếu `POC-01` FAIL: bổ sung
Kafka/MSK riêng cho hot-path đặt hàng (kiến trúc lai, theo điều kiện đã nêu ở `OPT §1`), không
Supersede toàn bộ `ADR-001`.
## 4. Phương án bị loại và lý do
| Phương án | Loại vì | Gắn với | Điều kiện nào thì xét lại |
|---|---|---|---|
| PA-1 — Kafka/MSK | Không có bằng chứng team vận hành production; effort dựng nền tảng lớn hơn đáng kể | `CON-05`, `OQ-010` | Nếu `POC-01` FAIL **và** `OQ-010` xác nhận team có kinh nghiệm Kafka/MSK — bổ sung Kafka/MSK riêng cho hot-path (kiến trúc lai), không thay thế toàn bộ |
| PA-2 — SQS Standard + SNS | Không đảm bảo thứ tự trong seller — vi phạm `DRV-06` | `DRV-06` | Chỉ xét lại cho các luồng không yêu cầu thứ tự (VD Notification không cần đúng thứ tự tuyệt đối) — không áp dụng cho `OrderPlaced`/`PaymentConfirmed` |
## 5. Hệ quả
**Hệ quả tích cực**
- Không cần vận hành cụm message broker riêng — khớp năng lực team, giảm effort nền tảng ~70,2 MD
so với Kafka/MSK
- Đảm bảo đúng thứ tự xử lý trong phạm vi cần (theo seller)
**Hệ quả tiêu cực phải sống chung**
- Rủi ro trần throughput cho **một** seller có volume rất cao — cần theo dõi/cảnh báo riêng
(chưa thiết kế, xem việc phát sinh)
- Nếu `POC-01` FAIL, phải bổ sung kiến trúc lai (Kafka/MSK cho riêng hot-path) — tăng độ phức tạp
vận hành so với một giải pháp thuần nhất
**Cái quyết định này khoá lại**
| Muốn đổi về sau thì | Tốn |
|---|---|
| Chuyển từ SQS FIFO/EventBridge sang Kafka/MSK sau khi đã có producer/consumer thật | Viết lại toàn bộ tầng publish/consume, thiết kế lại partition/consumer group |
**Việc phát sinh**
| Việc | Chủ | Hạn | Ghi ở đâu |
|---|---|---|---|
| Chạy `POC-01` theo tiêu chí đã viết trước | Tech Lead + DevOps | Trước khi `Accepted` | `ARISK_e-commerce_v1.0.md §6` |
| Thiết kế cơ chế theo dõi/cảnh báo riêng cho seller volume cao (VD CloudWatch alarm theo group lag) | SA (hoạt động `inf`) + Tech Lead | GĐ2 tiếp theo | `INF_e-commerce` |
| Thêm fitness function kiểm tra publish luôn có `seller_id` làm message group key | Tech Lead | GĐ3 (`AGD`/`FIT`) | `FIT-08` (ứng viên) |
## 6. Cách kiểm chứng quyết định này được tuân thủ
| Cách kiểm | Công cụ | Chạy ở đâu | `FIT` |
|---|---|---|---|
| `POC-01` — throughput/độ trễ/mất message | k6/artillery, AWS `ap-southeast-1` thật | Trước `Accepted`, lặp lại trước mỗi major release | — (ghi vào `ARISK §6`) |
| Mọi message publish `OrderPlaced`/`PaymentConfirmed` có `MessageGroupId = seller_id` | Contract test / lint publish code | CI | `FIT-08` (ứng viên) |
| Cảnh báo khi một message group riêng lẻ có lag > ngưỡng | CloudWatch Alarm | Production, liên tục | — |
## 7. Điều kiện xét lại
| Dấu hiệu | Ngưỡng | Ai theo dõi |
|---|---|---|
| `POC-01` FAIL | Không đạt tiêu chí PASS đã viết trước | Tech Lead |
| Một seller có volume vượt trần message group SQS FIFO trong production | Lag message group > 5 giây kéo dài > 5 phút liên tục | SRE |
| Tổng throughput hệ thống tiệm cận giới hạn đã đo ở `POC-01` | > 80% ngưỡng đã đo | SRE |
## 8. Tham chiếu
- POC: `ARISK_e-commerce_v1.0.md §6 POC-01`
- Bài đo: `FIT-08` (ứng viên GĐ3)
- Tài liệu ngoài: `QAS_e-commerce_v1.0.md §A3 QAS-005, §A4 (xung đột dòng 2)`
- Thảo luận: `ASR_e-commerce_v1.0.md §B2 ASR-005`, `OPT_e-commerce_v1.0.md §8 ASM-07`
## 9. Review log (không đổi Status)
| Ngày | Người review | Vai trò | Quyết định | Lý do chưa chuyển `Accepted` |
|---|---|---|---|---|
| 2026-09-15 | Điều phối dự án (thay mặt Tech Lead, chế độ chạy thử) | Tech Lead (ký thay, ngoại lệ `DEC-01`) | `Reviewed (Proposed giữ nguyên)` — nội dung đủ làm cơ sở thiết kế tiếp (`icd`/`dat`/`sec`/`inf`/`fail`) | Radar 8 — bắt buộc `POC-01` (throughput SQS/EventBridge) PASS trước khi `Accepted`; chưa chạy |
> Đây là ghi nhận **review nội dung**, không phải "sign" theo nghĩa gate: `Status` giữ nguyên
> `Proposed`. Xem `00-index/ADL_e-commerce.md` (Change Log — Review 2026-09-15) và `ADL §8`
> "Việc phải làm" cho điều kiện chuyển `Accepted`. Confidence tổng thể của lượt review: 🔴 —
> `AG2` chưa ký.