Litestream Revamped: SQLite Replication

Bài tóm tắt Fly.io 2025 2. Tăng trưởng Độ khó: Trung bình

Fly.io · 2025 · 2. Tăng trưởng · Độ khó: Trung bình — bài gốc

Bài của tác giả Litestream (Ben Johnson, Fly.io); một phần là kế hoạch chưa triển khai.

Bối cảnh

  • 2020, Litestream: chạy cạnh ứng dụng SQLite mà ứng dụng không cần biết; giữ một transaction đọc dài để chặn checkpoint WAL, dựng "shadow WAL" và đẩy liên tục các trang WAL lên object storage tương thích S3. Mất server thì khôi phục DB ở máy khác: "mất server nhưng không mất dữ liệu".
  • Sau đó, LiteFS: thêm read replica và failover primary cho SQLite qua một filesystem FUSE đứng giữa ứng dụng và đĩa để nhận biết transaction; dùng Consul để bảo đảm một leader. Mạnh hơn nhưng khó triển khai hơn, nên Litestream vẫn phổ biến hơn.
  • Giới hạn của Litestream cũ: khôi phục phải tải và phát lại mọi thay đổi từ snapshot gần nhất (một trang đổi nghìn lần là phát lại nghìn lần); tiến trình Litestream có thể chết riêng và bỏ sót thay đổi, nên nó dùng nhiều "generation" (snapshot + luồng WAL) để đồng bộ lại, khiến failover và read replica khó làm; polling WAL và khôi phục chậm làm việc sao chép hàng nghìn DB từ một process không khả thi.

Thay đổi chính

  • Định dạng LTX từ LiteFS: lưu dải trang đã sắp xếp gắn với transaction theo từng khoảng thời gian; gộp được nhiều file thành một file chỉ giữ phiên bản mới nhất của mỗi trang (compaction kiểu LSM), nên khôi phục tới một thời điểm mà ít trang trùng.
  • Lease bằng conditional write của object storage (S3 có từ 11/2024, Tigris cũng có): bảo đảm chỉ một instance Litestream ghi vào một đích, nên chỉ cần một generation mới nhất; bỏ được phụ thuộc vào Consul; node tạm thời chạy chồng lên nhau cũng không làm rối nhau.
  • Sao chép cả thư mục (/data/*.db) với hàng trăm, hàng nghìn DB.
  • Kế hoạch: lớp read replica dựa trên VFS của SQLite, đọc và cache trang thẳng từ object storage (kém hiệu quả hơn SQLite cục bộ, bù bằng cache và prefetch); PITR như một primitive để rollback hay fork cả code lẫn dữ liệu, ví dụ cho coding agent.

Bài học cho SWE

  • Ghi log trang thô thì đơn giản nhưng khôi phục chậm; log theo transaction có compaction giữ thời gian khôi phục có trần.
  • Tính năng mới của tầng lưu trữ (conditional write) có thể thay một hệ đồng thuận riêng (Consul) cho bài toán một leader.
  • Công cụ dễ triển khai thắng công cụ mạnh hơn nhưng đòi thêm hạ tầng.

Liên quan