Cross Shard Transactions at 10 Million Requests Per Second

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

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

Bối cảnh

  • Edgestore là lớp trừu tượng trên hàng nghìn node MySQL, giữ hàng petabyte metadata, hơn 10 triệu request/giây. Developer gom dữ liệu hay đi cùng nhau vào một colo (cùng shard vật lý): trong colo có transaction mạnh, latency thấp; giữa các colo chỉ là "best-effort".
  • Có dữ liệu không gom được (liên kết giữa người dùng và nội dung chia sẻ với người khác, hai người ở hai shard); không cách sắp xếp nào cắt hoàn hảo. Developer phải tự viết cơ chế ở tầng ứng dụng để che việc thiếu transaction chéo shard.

Thay đổi chính

  • 2PC sửa đổi: Phase 0 leader ghi một transaction record bền bên ngoài (là một object Edgestore, có thể đặt cùng shard với một participant); Phase 1 participant ghi bền ý định commit; Phase 2a leader đổi record sang committed (điểm commit tường minh); Phase 2b áp dụng. Record là nguồn sự thật nên khi leader chết thì chỉ cần abort rồi đi tiếp; bất kỳ thao tác song song nào cũng abort được transaction khi record còn pending; đọc/ghi đồng thời chỉ cần hỏi tối đa hai node để biết trạng thái.
  • Copy-on-write khi staging: lưu mutation thô vào bảng MySQL phụ, chỉ dựng trạng thái khi áp dụng, thay vì lưu bản sao đầy đủ (schema không cho trùng object): khuếch đại ghi giảm tới 95% so với đa phiên bản ngây thơ. Bảng phụ nhỏ (tỉ lệ với tốc độ transaction chéo shard) nên "lọc" khi đọc thường chỉ là kiểm tồn tại trong bộ nhớ.
  • Kiểm chứng offline: harness chạy liên tục trong môi trường build (tổng nhiều năm CPU), có fault injection ngẫu nhiên; từ lịch sử mutation dựng đồ thị thứ tự giữa các transaction: có chu trình là vi phạm serializability; đồ thị participant không đầy đủ là vi phạm atomicity; thêm luồng chỉ đọc cho phần "strict". Bắt được nhiều bug, từ lỗi bị nuốt tới lỗ hổng trong giao thức lọc khi đọc.
  • Shadow trên production: phiên bản "validation" của giao thức: staging ghi shadow rồi xoá ngay trong cùng transaction của API cũ, không báo leader; áp dụng là no-op; lọc vẫn kiểm nhưng bỏ qua kết quả. Ghi của API cũ vẫn là nguồn sự thật, nhưng Edgestore chịu đủ tải phối hợp của 2PC và tăng dần được. Đọc binlog lấy cả kết quả API cũ và bản shadow trong cùng transaction rồi so, tìm ra vài tính năng API không tương thích trước khi bật thật.
  • Giới hạn theo bài: chỉ 5–10% transaction là chéo shard vì dữ liệu đã gom tốt; lớp cache nhất quán mạnh hấp thụ hơn 95% lượt đọc nên chi phí lọc chịu được. Hệ không có hai điều kiện này có thể thấy 2PC quá nặng; thế hệ metadata tiếp theo hướng tới KV đơn giản + các service metadata với mức nhất quán khác nhau.

Vì sao

  • Độ phức tạp đã dồn quá nhiều về phía developer; nhiều chỗ transaction chéo shard thay cho giao thức tầng ứng dụng còn đắt hơn, nên vừa đơn giản vừa nhanh hơn.

Bài học cho SWE

  • 2PC trong production khả thi khi giao dịch chéo shard là thiểu số và có cache đỡ đọc; điểm commit tường minh trong một record ngoài làm phục hồi đơn giản.
  • Thêm ngữ nghĩa mạnh vào hệ đang chạy: chứng minh bằng harness kiểm tính chất (đồ thị thứ tự), rồi chạy giao thức mới ở chế độ bóng trên traffic thật trước khi để nó quyết định.

Liên quan