Protecting our platform from spikes in usage by reducing load from the Monzo app

Bài tóm tắt Monzo 2023 3. Quy mô lớn Độ khó: Trung bình

Monzo · 2023 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc

Bối cảnh

  • Monzo gọi là stampeding herd: rất nhiều người mở app cùng lúc, ví dụ 16h ngày trước ngày lương với tính năng Get Paid Early, hoặc khi gửi push "Year in Monzo".
  • Mỗi lần mở app hay nhận push, app tải trước số dư, giao dịch... Spike dồn lên các hệ dùng chung (DB, distributed lock), có thể làm sập từ tính năng phụ (đổi icon) tới xử lý thanh toán thẻ.

Thay đổi chính

  • Đo lãng phí trước: log 1/1000 user ở edge proxy, ghi URL kèm hash của response (không log dữ liệu nhạy cảm). Kết quả: khoảng 70% GET có một request giống hệt trong 24 giờ trước, trả về đúng response đó.

  • Hướng thất bại: "changes API" trả thời điểm cập nhật cuối của mỗi tài nguyên.

    • Đây thực chất là bài toán cache invalidation tức thời.
    • Nhiều response được làm giàu lúc request (ví dụ feature flag đổi cách hiển thị số dư), nên không thể chắc đã nghe đủ event.
    • Response không có timestamp gốc, nên cũng không kiểm chứng được.
  • Giải bài toán đơn giản hơn: chỉ cần cắt tải khi quá tải, chấp nhận dữ liệu trễ vài giây. Ba đặc trưng của request:

    1. thời gian từ lần cuối tính response: mã vào ETag (hash + thời điểm tính), trả 304 mà không tính lại;
    2. nguyên nhân request: app gửi header push-notification, app-open, generic-reload hoặc interactive;
    3. app đã mở được bao lâu (header riêng).
  • Chính sách cắt tải:

    Loại request Phần traffic Độ chính xác khi cắt
    Do push, đã phục vụ trong 24 giờ 20% 80%
    Mở app, trong 1 giờ 20% 95%
    Reload trong 10 giây đầu 7% 95%

    Tổng cộng cắt được gần 50% GET với độ chính xác khoảng 90%.

  • Rollout an toàn:

    • chạy shadow mode (ghi lại quyết định nhưng vẫn tính response);
    • metric lên Prometheus;
    • chính sách nằm trong framework load shedding chung, xếp theo mức ảnh hưởng tới khách và bật/tắt theo lô.

Kết quả

Khi bật, lượng lock giảm nhẹ, lượt đọc các bảng giao dịch và số dư giảm rõ; tải lên các thành phần chính giảm 10–30%. Theo Monzo, khách hàng gần như không nhận ra.

Bài học cho SWE

  • Đo trước khi tối ưu: 70% GET trùng lặp là con số mở ra cả hướng giải.
  • Bỏ mục tiêu "đúng 100%" (cache invalidation chuẩn) thì có lời giải đơn giản: load shedding có điều kiện, chỉ bật khi quá tải.
  • Kiến thức sản phẩm (request nào do push, do mở app) là tín hiệu cắt tải tốt hơn mọi heuristic thuần hạ tầng.
  • Dùng ETag/304 để trả lời "không đổi" mà không cần tính lại.

Liên quan