From Static Rate Limiting to Adaptive Traffic Management in Airbnb's Key-Value Store

Bài tóm tắt Airbnb 2026 4. Điều chỉnh Độ khó: Nâng cao

Airbnb · 2026 · 4. Điều chỉnh · Độ khó: Nâng cao — bài gốc

Bối cảnh

  • Mussel là kho key-value multi-tenant cho dữ liệu dẫn xuất. Mọi lượt tra cứu (search, hỗ trợ khách...) cuối cùng đều chạm vào nó. Mussel là một fleet dispatcher stateless (pod Kubernetes) đứng trước storage.
  • QoS thế hệ đầu: đếm QPS bằng Redis, mỗi caller có một quota tĩnh theo phút, vượt thì trả 429. Đơn giản và đủ dùng khi traffic còn nhỏ, đồng nhất, và tải backend tỷ lệ thuận với số request.
  • Hai giới hạn lộ ra:
    • chênh lệch chi phí: tra một dòng và quét 100.000 dòng bị tính như nhau;
    • lệch truy cập: quota theo caller không thấy được hot key. Một listing nổi tiếng được hàng nghìn caller khác nhau gọi cùng lúc, mỗi caller vẫn trong quota, nhưng tổng lại đè một shard và làm chậm cả cụm.

Thay đổi chính

Mục tiêu đổi từ "không sập" sang tối đa goodput: làm được nhiều việc có ích nhất mà không giảm hiệu năng. Họ thêm ba lớp.

  • Resource-aware rate control: tính phí mỗi request theo request unit (RU), gồm chi phí cố định, số byte và latency. Latency bắt được khác biệt giữa đọc trúng cache và đọc đĩa. Hệ số được hiệu chỉnh bằng load test. Mỗi dispatcher giữ một token bucket theo RU, nạp lại mỗi epoch ngắn, nên không cần phối hợp giữa các node.

  • Load shedding theo mức quan trọng:

    • tỷ lệ latency = p95 dài hạn / p95 ngắn hạn. Bình thường gần 1,0; tụt về khoảng 0,3 tức là latency đang tăng vọt. Khi đó tăng giá RU cho một lớp client ít quan trọng để bucket của nó cạn nhanh hơn, rồi mở rộng dần sang lớp khác;
    • hàng đợi kiểu CoDel: request chờ quá lâu trong hàng thì bị fail sớm, giải phóng luồng cho việc ưu tiên hơn;
    • traffic quan trọng (hỗ trợ khách, trust & safety) luôn được giữ.

    Theo Airbnb, thời gian hồi phục giảm khoảng một nửa.

  • Phát hiện hot key và chống DDoS:

    • mỗi dispatcher đếm top-k key bằng thuật toán Space-Saving, chỉ tốn vài MB;
    • key nóng thì phục vụ từ LRU cache cục bộ, TTL khoảng 3 giây;
    • gộp request trùng (coalescing): request đến sau bám vào future của request đang bay, nên mỗi pod chỉ gửi khoảng một request cho mỗi hot key xuống storage.

    Trong một buổi diễn tập DDoS cỡ khoảng một triệu QPS nhắm vào vài key, backend gần như không nhận thấy.

Bài học (theo Airbnb)

  • Ra mắt sớm phần tạo tác động nhìn thấy được: RU accounting vừa lên đã tự throttle một caller có range scan âm thầm làm chậm cả cụm.
  • Giữ vòng điều khiển cục bộ (P², top-k, CoDel đều chạy trong từng dispatcher): scale tuyến tính và vẫn bảo vệ được khi chính control plane bị stress.
  • Bảo vệ ở hai thang thời gian: giá RU bắt spike nhỏ; tỷ lệ latency và CoDel bắt suy giảm lớn.
  • Bước tiếp theo: resource group ngay trong DB, tự chỉnh quota theo dữ liệu dùng 30 ngày.

Bài học cho SWE

  • Đếm request không đủ: quota phải phản ánh chi phí thật (dòng, byte, latency), giống capacity unit của DynamoDB.
  • Isolation theo caller không giải được hot key; cần lớp phát hiện theo key cộng cache ngắn hạn và gộp request. Cùng họ với memcache lease của Instagram và bounded load của Zalando (Cache và invalidation).
  • Load shedding cần biết mức quan trọng của traffic, giống Monzo xếp chính sách cắt tải theo mức ảnh hưởng (Monzo 2023).

Liên quan