Himeji: A Scalable Centralized System for Authorization at Airbnb

Bài tóm tắt Airbnb 2021 3. Quy mô lớn Độ khó: Khó

Airbnb · 2021 · 3. Quy mô lớn · Độ khó: Khó — bài gốc

Bài ngoài sheet, lấy về Medium qua Wayback. Một đồng tác giả (Abhishek Parmar) từng làm Zanzibar ở Google.

Bối cảnh

  • Ở thời monolith Rails, mỗi resource có một API duy nhất để đọc dữ liệu, và kiểm tra quyền nằm trong API đó, nên rất dễ quản lý.
  • Khi tách sang SOA (data service bọc DB, presentation service ghép dữ liệu từ nhiều data service), kiểm tra quyền ban đầu được dời lên presentation service. Kết quả:
    • code kiểm tra quyền bị nhân bản ở nhiều presentation service cùng đọc một dữ liệu, rồi lệch nhau;
    • fan-out: phần lớn lần kiểm tra phải gọi thêm service khác, chậm, khó gánh tải, kéo tụt độ tin cậy.

Thay đổi chính

  • Dời kiểm tra quyền xuống data service, và data service gọi Himeji, một hệ phân quyền tập trung dựa trên Zanzibar, làm nguồn sự thật cho dữ liệu quyền.
  • Fan-out lúc ghi thay vì lúc đọc: ghi dữ liệu quyền khi resource thay đổi, vì workload thiên về đọc.
  • API: check(entity, relation, principal), ví dụ "user 123 có quyền WRITE lên mô tả của listing 10 không".
  • Lưu trữ: tuple entity # relation @ principal; entity gồm loại : id : phần (ví dụ LISTING : 10 : DESCRIPTION); principal là user hoặc tham chiếu tới entity khác (Reference(RESERVATION:500)).
  • Cấu hình YAML theo đại số tập hợp (giống Zanzibar): WRITE = hợp của WRITE và OWNER, READ = hợp của READ và WRITE. Chủ listing chỉ cần một tuple OWNER là đọc và ghi được.
  • Khác Zanzibar ở reference: quan hệ đi sau một entity được tham chiếu (GUEST, COTRAVELLER, BOOKER…) nằm trong cấu hình chứ không nằm trong tuple. Lý do theo Airbnb: tập quan hệ giữa hai loại entity không đổi theo từng bản ghi, nên dữ liệu lưu giảm từ N*M xuống N tuple. Ví dụ: khách của reservation 500 đọc được vị trí của listing 10 sau hai lần đọc DB.
  • Kiến trúc ba tầng: orchestration (đọc cấu hình, phát lệnh fetch, route tới cache bằng consistent hashing), cache (shard + replica, mỗi shard một instance trên mỗi AZ, nhắm hit rate khoảng 98%), data (DB shard logic).
  • Thay đổi so với Zanzibar: tách tầng orchestration khỏi tầng cache để deploy không phải restart cache; invalidate cache theo mutation phát ra từ DB (CDC); lưu trên Aurora thay vì Spanner. Giữ hedging, cache phân tầng, load shedding như Zanzibar.
  • Số liệu (3/2021): từ 0 (3/2020) lên 850k entity/giây; availability 99,999%, p50 1,8 ms, p95 7 ms, p99 12 ms; hàng chục tỉ quan hệ.
  • Công cụ để các team chịu dùng: backfill tuple theo cấu hình (Airflow + Spark, chủ service chỉ khai báo cách dựng tuple từ bản export DB), sinh code Java/Scala, thick client có log, metric và điều khiển rollout migration, UI để debug quyền.

Vì sao

  • Theo Airbnb: trước Himeji, giữ nhất quán và hiệu năng giữa nhiều mảnh logic phân quyền rời nhau là rất khó. Mô hình dữ liệu đơn giản cộng cấu hình linh hoạt cho phép gom phân quyền sản phẩm và dữ liệu về một chỗ.

Bài học cho SWE

  • Tách monolith làm vỡ "một đường vào dữ liệu", nên kiểm tra quyền phải đi theo dữ liệu (data service), không đi theo API trình bày.
  • Workload đọc nhiều thì trả chi phí lúc ghi (ghi sẵn tuple) để lần check chỉ cần vài lần đọc có cache.
  • Hệ phân quyền tập trung chỉ được dùng khi việc onboard rẻ: backfill chung, sinh code, client có rollout control, công cụ debug.

Liên quan