DAG là gì
Bạn sẽ học được
- DAG là gì và vì sao phải là đồ thị không chu trình.
- Các thành phần của Airflow: scheduler, executor, metadata database.
- Đọc đúng
data_intervalthay vì nhầm với giờ chạy. - Viết DAG đầu tiên bằng TaskFlow API.
- Những hiểu nhầm khiến pipeline chạy sai ngày.
Khái niệm cốt lõi
DAG (Directed Acyclic Graph) là tập các task có hướng và không có chu trình.
extract_orders → transform_orders → load_orders- Có hướng:
extractchạy trướctransform. - Không chu trình: không có đường quay lại
extract. Nếu có, Airflow không biết bắt đầu từ đâu.
Mỗi lần DAG chạy gọi là một DAG run, gắn với một logical date (khoảng dữ liệu), không phải thời điểm bấm chạy.
Các thành phần
| Thành phần | Nhiệm vụ |
|---|---|
| Scheduler | Quyết định task nào đến lượt chạy |
| Executor | Chạy task (Local, Celery, Kubernetes) |
| Metadata DB | Lưu trạng thái DAG, task, lần chạy |
| Webserver | Giao diện xem và điều khiển |
| Triggerer | Xử lý deferred và sensor bất đồng bộ |
Nếu metadata DB mất, Airflow mất toàn bộ lịch sử chạy. Sao lưu DB quan trọng hơn sao lưu file DAG.
Data interval
Đây là khái niệm gây nhầm lẫn nhiều nhất.
DAG chạy lúc 02:00 ngày 2/3 với lịch hằng ngày xử lý dữ liệu của ngày 1/3:
data_interval_start = 2026-03-01 00:00
data_interval_end = 2026-03-02 00:00
logical date = 2026-03-01 (đầu khoảng)Quy tắc: một lần chạy chỉ được xử lý dữ liệu đã hoàn tất tại thời điểm nó bắt đầu. Vì vậy nó xử lý khoảng phía trước, không phải khoảng đang diễn ra.
Nhầm lẫn phổ biến: dùng datetime.now() trong task. Mỗi lần chạy lại cho kết quả khác và không tái lập được. Luôn dùng data_interval_start hoặc ds.
DAG đầu tiên
from datetime import datetime, timedelta
from airflow.decorators import dag, task
@dag(
dag_id="daily_orders",
schedule="0 2 * * *",
start_date=datetime(2026, 1, 1),
catchup=False,
default_args={
"retries": 2,
"retry_delay": timedelta(minutes=5),
},
tags=["orders"],
)
def daily_orders():
@task
def extract(**context):
ngay = context["data_interval_start"].date()
return {"ngay": str(ngay), "so_dong": 12000}
@task
def transform(payload):
return {**payload, "so_dong": payload["so_dong"]}
@task
def load(payload):
print(f"Nạp {payload['so_dong']} dòng cho ngày {payload['ngay']}")
load(transform(extract()))
daily_orders()Điểm cần chú ý:
catchup=Falseđể không tự chạy bù toàn bộ quá khứ từstart_date.retriesđặt ởdefault_argsáp cho mọi task.- TaskFlow suy ra phụ thuộc từ cách gọi hàm:
load(transform(extract()))tạo chuỗi ba task. data_interval_startlấy từ context, không dùngnow().
DAG không chu trình
Ví dụ sai:
extract → transform → load → transformAirflow sẽ báo lỗi chu trình khi parse. Cách sửa: tách bước kiểm tra thành task riêng, hoặc gộp logic.
Kiểm tra DAG trước khi đưa lên
airflow dags list
airflow tasks list daily_orders
airflow dags test daily_orders 2026-03-01dags test chạy toàn bộ DAG cho một logical date mà không ghi vào lịch sử production. Đây là cách kiểm tra nhanh nhất trước khi bật lịch.
Lỗi thường gặp
- Dùng
datetime.now(): kết quả không tái lập. - Nhầm logical date với giờ chạy: xử lý sai ngày.
- Để
catchup=Truemặc định: chạy bù hàng trăm ngày khi mới bật DAG. - Đặt logic nặng ở cấp DAG: file parse chậm, scheduler quá tải.
- Một DAG làm quá nhiều việc: khó theo dõi và chạy lại.
- Không đặt
start_date: DAG không được lập lịch.
Thực hành
- Vẽ DAG ba task cho pipeline đơn hàng.
- Xác định
data_interval_startcho lần chạy 2/3 lúc 02:00. - Viết DAG TaskFlow với
retries=2. - Chạy
airflow dags testcho một ngày cụ thể. - Giải thích vì sao
catchup=Truecó thể gây nguy hiểm.
Lỗi thường gặp
| Triệu chứng | Nguyên nhân | Cách sửa |
|---|---|---|
| DAG không xuất hiện | Lỗi parse hoặc thiếu start_date | Xem log scheduler |
| Chạy bù hàng loạt | catchup=True | Đặt catchup=False |
| Dữ liệu lệch một ngày | Nhầm logical date | Dùng data_interval_start |
| Chạy lại cho kết quả khác | Dùng now() | Dùng context |
| Scheduler chậm | Logic nặng trong file DAG | Chuyển vào task |
Tóm tắt
- DAG là đồ thị có hướng, không chu trình.
- Logical date là khoảng dữ liệu, không phải giờ chạy.
- Dùng
data_interval_start, không dùngdatetime.now(). catchup=Falsekhi mới bật DAG.- Kiểm tra bằng
airflow dags testtrước khi bật lịch.
Use ← → to move between lessons