Hướng dẫn sử dụng Litestream sao lưu SQLite lên S3: Backup Real-time cho Production

Development tutorial - IT technology blog
Development tutorial - IT technology blog

Quick Start: Cấu hình Litestream sao lưu SQLite trong 5 phút

Chỉ cần một file SQLite và một bucket S3 (AWS S3, Cloudflare R2 hoặc MinIO), bạn có thể dựng xong cơ chế replication thời gian thực qua 3 bước.

Bước 1: Cài đặt Litestream

# Tải binary bản v0.3.13 cho Linux amd64
wget https://github.com/benbjohnson/litestream/releases/download/v0.3.13/litestream-v0.3.13-linux-amd64.tar.gz
tar -xvzf litestream-v0.3.13-linux-amd64.tar.gz
sudo mv litestream /usr/local/bin/
litestream version

Bước 2: Tạo cấu hình /etc/litestream.yml

dbs:
  - path: /var/www/app/data/production.db
    replicas:
      - type: s3
        bucket: my-sqlite-backups
        path: production-db
        region: ap-southeast-1
        access-key-id: YOUR_S3_ACCESS_KEY
        secret-access-key: YOUR_S3_SECRET_KEY

Bước 3: Khởi chạy replication

# Chạy thử ở foreground để kiểm tra log kết nối
litestream replicate -config /etc/litestream.yml

Ngay khi khởi động, Litestream tạo một bản snapshot đầy đủ lên S3. Sau đó, nó theo dõi các transaction mới và đẩy tiếp lên storage.

Tại sao SQLite cần Litestream khi lên Production?

Sức hút và rào cản của SQLite

SQLite có tốc độ đọc vượt trội nhờ loại bỏ hoàn toàn network round-trip. Bộ nhớ tiêu thụ thường chưa tới 30MB RAM. Nó không đòi hỏi bạn phải vận hành cả cụm server cồng kềnh như PostgreSQL hay MySQL. Dù vậy, phần lớn kỹ sư ngần ngại đưa SQLite lên môi trường production vì câu hỏi: Nếu ổ cứng máy chủ hỏng bất ngờ, làm sao để không mất dữ liệu?

Sao lưu truyền thống nguy hiểm thế nào?

Giải pháp thông thường là tạo cronjob copy file .db lúc nửa đêm hoặc dùng rsync. Cách này có hai rủi ro lớn:

  • Dữ liệu bị hỏng (Corrupted Database): SQLite ở chế độ WAL (Write-Ahead Logging) ghi các thay đổi vào file phụ .db-wal trước khi ghi vào đĩa. Nếu copy đúng lúc app đang ghi dữ liệu, bạn sẽ nhận được một file chắp vá. File này gần như không thể mở lại.
  • Mất dữ liệu cả ngày: Giả sử backup chạy định kỳ lúc 00:00. Máy chủ gặp sự cố vào 23:00. Bạn sẽ mất sạch 23 tiếng giao dịch của người dùng. RPO (Recovery Point Objective) như vậy quá cao đối với một ứng dụng thực tế.

Cơ chế Continuous WAL Replication

Litestream can thiệp trực tiếp ở tầng file system thay vì can thiệp vào mã nguồn app. Cơ chế vận hành gồm 4 điểm chính:

  • Bật chế độ WAL mode cho database.
  • Theo dõi file WAL liên tục theo chu kỳ 1 giây hoặc khi bộ đệm đạt dung lượng định trước.
  • Nén từng frame thay đổi bằng thuật toán LZFSE rồi stream thẳng lên object storage.
  • Hỗ trợ Point-in-Time Recovery (PITR). Bạn có thể khôi phục database về trạng thái chính xác đến từng mili-giây.

Vận hành bền bỉ trên Production

1. Quản lý tiến trình bằng Systemd Service

Trên máy chủ Ubuntu/Debian, tạo file /etc/systemd/system/litestream.service để tự phục hồi khi crash:

[Unit]
Description=Litestream Replication Service
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/litestream replicate -config /etc/litestream.yml
Restart=always
RestartSec=5
LimitNOFILE=65536
User=www-data
Group=www-data

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now litestream
sudo systemctl status litestream

2. Chạy chung với App trong Container

Khi đóng gói Docker trên VPS, Fly.io hoặc Railway, hãy dùng Litestream làm wrapper command bằng entrypoint script:

#!/bin/sh
set -e

# Khôi phục từ S3 nếu container mới tinh chưa có database
if [ ! -f /app/data/production.db ]; then
  echo "Local database missing. Restoring from replica..."
  litestream restore -if-replica-exists -config /etc/litestream.yml /app/data/production.db
fi

# Chạy replicate nền và khởi động app song song
exec litestream replicate -config /etc/litestream.yml -exec "node server.js"

Cờ -exec gắn chặt vòng đời của app vào Litestream. Khi ứng dụng nhận tín hiệu SIGTERM để tắt, Litestream sẽ đẩy nốt các frame dữ liệu cuối cùng lên S3 rồi mới dừng hẳn.

3. Kịch bản khôi phục thảm họa (Disaster Recovery)

Nếu server sập, chỉ cần dựng một máy mới và gõ lệnh:

litestream restore -config /etc/litestream.yml /var/www/app/data/production.db

Trong tình huống ai đó vô tình chạy nhầm lệnh DROP TABLE lúc 14:30:15, bạn có thể quay về 1 giây trước đó:

litestream restore -timestamp 2026-10-23T14:30:14Z -config /etc/litestream.yml /var/www/app/data/production.db

Lưu ý thực chiến từ hệ thống thật

  • Test kịch bản restore tự động: Đừng chờ sự cố xảy ra mới biết bản backup không dùng được. Hãy thiết lập một cronjob hàng tuần tải bản sao lưu về staging và chạy câu lệnh sqlite3 production.db "PRAGMA integrity_check;". Nếu kết quả trả về chữ ok, bạn mới có thể yên tâm.
  • Cân nhắc dùng Cloudflare R2 thay vì AWS S3: AWS S3 tính phí khoảng 0.005 USD cho mỗi 1.000 PUT request. Ứng dụng ghi liên tục có thể phát sinh 2 đến 3 triệu request mỗi tháng, khiến chi phí API vượt quá tiền dung lượng lưu trữ. Đổi sang Cloudflare R2 sẽ giúp bạn miễn phí 100% chi phí egress và có sẵn 1 triệu lượt ghi miễn phí mỗi tháng.
  • Thiết lập timeout trong code: Thêm cấu hình PRAGMA busy_timeout = 5000; ngay sau khi mở kết nối database trong app. Lệnh này buộc SQLite đợi tối đa 5 giây khi có xung đột ghi, tránh văng lỗi database is locked trong lúc Litestream đang đọc checkpoint.
  • Đảm bảo quyền ghi thư mục: Khi Litestream chạy, nó tạo ra các file tạm như production.db-shm và production.db-wal. User chạy Litestream (như www-data) buộc phải có quyền ghi trên toàn bộ thư mục chứa database, không chỉ riêng file .db.
Share: