← Series hub ← PrevNext →

Bài 3: Tấm khiên bảo vệ - Sức mạnh của 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, hành 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.
  • 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.
graph 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): 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.
  • 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.