← Chương trước: Bài 2: Kiến trúc Flash Sale — Bí ẩn phía sau Redis và Hot Keys | Mục lục Series | Chương tiếp theo: Bài 4: Tầng Dữ liệu — Từ MySQL Sharding đến TiDB NewSQL →
Answer-first: Tấm khiên bảo vệ hệ thống trước cơn bão traffic Flash Sale kết hợp hàng đợi Apache Kafka để đệm đơn hàng và san phẳng đỉnh tải, cùng cơ chế suy giảm dịch vụ mềm (Graceful Degradation) tự động tắt các tính năng phụ để dồn tài nguyên cho luồng thanh toán.
Bài 3: Tấm khiên bảo vệ - Ứng dụng Kafka và Graceful Degradation
Qua Bài 2, chúng ta đã dùng Redis để trừ tồn kho trên RAM với tốc độ chớp mắt. Tuy nhiên, quy trình mua hàng chưa kết thúc. Hệ thống còn phải: Tạo Order trong MySQL, sinh hóa đơn, trừ tiền ví ShopeePay, tính phí vận chuyển, và cộng điểm Shopee xu.
Nếu ta cố gắng làm tất cả những việc này Cùng lúc (Synchronous), hệ thống sẽ ngay lập tức “vỡ trận” do Database bị khóa chờ (Lock timeout) hoặc gọi API bên thứ ba quá lâu. Bí quyết là: Bất đồng bộ hóa (Asynchronous Processing).
1. Peak Shaving (Gọt Đỉnh Traffic) bằng Apache Kafka
Triết lý của thiết kế Flash Sale là: Nhận request thật nhanh, xử lý thật chậm. Shopee dùng Apache Kafka - một Message Queue chuyên xử lý streaming lưu lượng siêu lớn - làm một “chiếc phễu” chứa bộ đệm.
- Khi Redis trừ tồn kho thành công, một Message chứa nội dung “User A đặt mua iPhone” được bắn vào Kafka. Để bảo đảm không mất đơn hàng, Producer được cấu hình chặt chẽ với
acks=allvàenable.idempotence=true. - Hệ thống trả về ngay cho app thông báo: “Bạn đã xếp hàng thành công, hệ thống đang xử lý đơn hàng”. Trải nghiệm người dùng chỉ diễn ra trong vài mili-giây.
- Phía sau cánh gà (Backend Workers), các tiến trình Golang cứ tà tà kéo (pull) message từ Kafka về để tiến hành insert vào Database.
- Kết quả: Nếu có 1 triệu đơn văng tới trong 1 giây (đỉnh Spike), thay vì sập DB, 1 triệu thông điệp đó nằm gọn trong Kafka. Worker xử lý tốc độ 10k đơn/giây, thì sau 100 giây hệ thống sẽ làm xong. Đỉnh traffic đã bị “gọt” bằng lại (Peak Shaving) một cách tuyệt đẹp. Đảm bảo an toàn dữ liệu 100% trong năm 2026.
flowchart LR
subgraph "Traffic Storm"
Users(("Millions of Users")) -->|"1 Million Req/s"| Checkout["Checkout Service"]
end
Checkout -->|"Write"| Kafka[("Apache Kafka<br/>Message Broker")]
subgraph "Async Processing"
Kafka -->|"Pull at 10k/s"| Worker1["Order Worker"]
Kafka -->|"Pull at 10k/s"| Worker2["Payment Worker"]
Worker1 --> DB[("MySQL / TiDB")]
Worker2 --> API["External APIs"]
end
2. Eventual Consistency (Tính nhất quán cuối cùng)
Shopee áp dụng triết lý Eventual Consistency trong hệ thống phân tán. Đừng cố ép dữ liệu đồng bộ ngay lập tức mọi nơi (Strong Consistency). Sẽ có độ trễ nhỏ từ lúc bạn bấm đặt hàng thành công đến khi hóa đơn thực sự xuất hiện trong mục “Đang xử lý”. Sự đánh đổi nhỏ về thời gian này giúp cứu vãn tính sẵn sàng (Availability) của toàn bộ sàn thương mại điện tử.
3. Graceful Degradation (Suy thoái có kiểm soát)
Vào thời khắc giao thừa 11.11, Shopee phải áp dụng chính sách Bảo vệ luồng cốt lõi (Core Flow: Tìm kiếm -> Thêm Giỏ Hàng -> Thanh toán). Mọi thứ khác có thể “chết”, nhưng Checkout thì không!
- Circuit Breaker (Ngắt mạch tự động) và Adaptive Load Shedding: Khi một hệ thống (ví dụ: Service Khuyến mãi) bị quá tải và phản hồi chậm, Circuit Breaker (như Hystrix hoặc Sentinel) sẽ tự động kích hoạt, cắt đứt hoàn toàn kết nối đến service đó trong một khoảng thời gian, ép nó trả về lỗi mặc định ngay lập tức để không kéo chậm dây chuyền. Hơn nữa, Adaptive Load Shedding dựa trên tình trạng CPU/Memory thực tế sẽ chủ động thả trôi các request ít quan trọng.
- Feature Toggling (Công tắc tính năng): Dev Shopee xây dựng sẵn các “công tắc” trên hệ thống quản lý cấu hình. Khi traffic vọt lên ngưỡng nguy hiểm, hệ thống tự động tắt (Degrade) các chức năng rườm rà:
- Tắt hiển thị lịch sử xem hàng.
- Tạm ẩn hệ thống thống kê của Seller.
- Ẩn phần đề xuất (Recommendation) tốn nhiều CPU.
- Tắt đổi Avatar hồ sơ.
Bài học cho Dev: Message Queue (như Kafka/RabbitMQ) là chìa khóa để phân rã hệ thống nguyên khối thành các pipeline độc lập. Trong thiết kế chịu tải, phải luôn có tư duy đánh đổi (Trade-off): Chấp nhận từ bỏ các tính năng phụ để giữ cho mạch máu chính của sản phẩm sống sót.
← Chương trước: Bài 2: Kiến trúc Flash Sale — Bí ẩn phía sau Redis và Hot Keys | Mục lục Series | Chương tiếp theo: Bài 4: Tầng Dữ liệu — Từ MySQL Sharding đến TiDB NewSQL →
❓ Câu Hỏi Thường Gặp (FAQ)
Q1: Bài 3: Tấm khiên bảo vệ — Message Queue và Graceful Degradation giải quyết vấn đề cốt lõi nào trong kiến trúc hệ thống?
Cơ chế đệm hàng đợi (Message Queue Buffer), kỹ thuật Rate Limiting nhiều tầng và chiến lược suy giảm dịch vụ mềm (Graceful Degradation).
Q2: Những lưu ý quan trọng nhất khi triển khai thực tế là gì?
Cần chú trọng phân tầng ranh giới trách nhiệm (bounded context), thiết lập cơ chế fallback dự phòng, và giám sát chặt chẽ qua metrics OpenTelemetry để phát hiện sớm các điểm nghẽn.
Q3: Làm sao để kiểm thử và đánh giá hiệu quả sau khi áp dụng?
Áp dụng kiểm thử tải (load test), benchmark độ trễ P95/P99 trước và sau triển khai, kết hợp tracing phân tán để xác minh tính ổn định dưới tải cao.
