Lập lịch và backfill
Bạn sẽ học được
- Viết lịch chạy bằng cron và đọc đúng ý nghĩa.
- Hiểu quan hệ giữa lịch chạy và khoảng dữ liệu.
- Dùng
catchupvàmax_active_runsđúng cách. - Chạy backfill an toàn.
- Xử lý dữ liệu đến muộn.
Khái niệm cốt lõi
Lịch chạy trả lời hai câu hỏi khác nhau:
- Khi nào chạy? — biểu thức cron.
- Xử lý dữ liệu nào? — data interval.
Hai câu này không giống nhau. DAG chạy lúc 02:00 ngày 2/3 xử lý dữ liệu ngày 1/3.
Cron cơ bản
┌ phút (0-59)
│ ┌ giờ (0-23)
│ │ ┌ ngày trong tháng (1-31)
│ │ │ ┌ tháng (1-12)
│ │ │ │ ┌ ngày trong tuần (0-6, 0 = Chủ nhật)
│ │ │ │ │
* * * * *| Biểu thức | Nghĩa |
|---|---|
0 2 * * * | 02:00 mỗi ngày |
0 2 * * 1 | 02:00 thứ Hai |
0 */6 * * * | Mỗi 6 giờ |
30 1 1 * * | 01:30 ngày 1 mỗi tháng |
0 2 * * 1-5 | 02:00 các ngày làm việc |
Airflow còn hỗ trợ @daily, @hourly, @weekly, và timedelta cho lịch đều đặn.
Catchup
catchup=True khiến Airflow chạy bù mọi khoảng dữ liệu từ start_date đến hiện tại.
@dag(
dag_id="daily_orders",
schedule="0 2 * * *",
start_date=datetime(2024, 1, 1),
catchup=False,
)Nếu start_date là 1/1/2024 và hôm nay là 1/3/2026, bật catchup sẽ tạo gần 800 lần chạy cùng lúc. Điều này thường không phải điều bạn muốn khi mới triển khai.
Chỉ bật catchup khi thật sự cần xử lý lại quá khứ và đã tính đến tải hệ thống.
Max active runs
max_active_runs=1Giới hạn số lần chạy đồng thời của một DAG. Với pipeline ghi vào cùng một bảng, đặt 1 để tránh hai lần chạy tranh nhau.
max_active_tasks giới hạn số task song song trong một lần chạy.
Backfill
Chạy lại một khoảng thời gian:
airflow dags backfill daily_orders \
--start-date 2026-03-01 \
--end-date 2026-03-07Ba điều cần kiểm tra trước khi backfill:
- Task có idempotent không? Nếu không, backfill sẽ tạo dữ liệu trùng.
- Hệ thống đích có chịu được tải không?
- Có phụ thuộc bên ngoài nào bị gọi lại (email, API tính tiền) không?
Backfill không phải "chạy lại cho đẹp". Nó ghi dữ liệu thật vào hệ thống thật.
Dữ liệu đến muộn
Nguồn có thể đến muộn vài giờ hoặc vài ngày. Ba cách xử lý:
| Cách | Khi nào dùng |
|---|---|
| Chạy lại ngày cũ khi dữ liệu đến | Có cảnh báo độ tươi |
| Cửa sổ chờ cố định | Nguồn trễ đều đặn |
| Xử lý theo lô lớn hơn | Dữ liệu trễ nhiều ngày |
Với cách đầu, cần đảm bảo task idempotent và có cơ chế phát hiện dữ liệu đến muộn.
Múi giờ
Airflow lưu thời gian theo UTC. Nếu nghiệp vụ theo giờ Việt Nam, đặt timezone trong DAG hoặc quy đổi rõ ràng:
import pendulum
@dag(
dag_id="daily_orders",
schedule="0 2 * * *",
start_date=pendulum.datetime(2026, 1, 1, tz="Asia/Ho_Chi_Minh"),
)Không có múi giờ, một ngày nghiệp vụ có thể bị cắt sai mốc.
Lỗi thường gặp
- Bật catchup mà không biết: hàng trăm lần chạy đồng thời.
- Backfill trên task không idempotent: dữ liệu trùng.
- Không giới hạn
max_active_runs: tranh chấp ghi. - Dùng giờ local trong code: lệch múi giờ.
- Cron hiểu sai ngày trong tuần: chạy sai ngày.
- Không kiểm tra tải trước backfill: làm sập hệ thống nguồn.
Thực hành
- Viết cron cho 02:00 thứ Hai đến thứ Sáu.
- Xác định khoảng dữ liệu của lần chạy 1/4 lúc 02:00 với lịch hằng ngày.
- Đặt
max_active_runs=1và giải thích lý do. - Chạy backfill ba ngày trên môi trường dev.
- Thiết kế cách xử lý dữ liệu đến muộn hai ngày.
Lỗi thường gặp
| Triệu chứng | Nguyên nhân | Cách sửa |
|---|---|---|
| Hàng trăm run cùng lúc | catchup=True | Đặt False |
| Dữ liệu trùng sau backfill | Task không idempotent | Sửa cách ghi |
| Hai run tranh nhau | Không giới hạn | max_active_runs=1 |
| Lệch một ngày | Múi giờ | Đặt timezone |
| Nguồn quá tải | Backfill lớn | Chạy theo lô nhỏ |
Tóm tắt
- Lịch chạy và khoảng dữ liệu là hai khái niệm khác nhau.
catchup=Truecó thể tạo hàng trăm lần chạy.- Giới hạn
max_active_runskhi ghi vào cùng đích. - Backfill chỉ an toàn khi task idempotent.
- Đặt múi giờ rõ ràng cho nghiệp vụ địa phương.
Use ← → to move between lessons