DataOps nâng cao 22 — Data SLA & xử lý Data Downtime

13 thg 7, 2026 2 lượt xem
#data-engineering
#dataops
#incident-management
#data-sla
#rca

Từ "quan sát được" tới "cam kết được"

Hai bài Observability & DREObservability & Incident dựng khung nhìn thấy dữ liệu hỏng và quy trình sự cố cơ bản. Bài này đi sâu hơn vào phần vận hành cam kết: biến "chúng tôi cố gắng dữ liệu đúng" thành một hợp đồng mức dịch vụ có số đo, có ngân sách lỗi, có người trực, và một playbook xử lý sự cố đủ chi tiết để đội trực chạy lúc 2h sáng mà không phải suy nghĩ.

Câu hỏi trung tâm không còn là "dữ liệu có quan sát được không?" mà là "chúng ta cam kết dữ liệu tin cậy tới mức nào, đo bằng gì, và khi vi phạm thì xử lý ra sao?". Ở ngân hàng, đây là câu hỏi giải trình được với Ban điều hành và NHNN.

Data Downtime là gì

Data Downtime là khoảng thời gian dữ liệu sai / thiếu / trễ / không dùng được — tức khoảng mà một consumer nếu tin vào dữ liệu sẽ ra quyết định sai. Đây là khái niệm song song với "downtime" của hệ thống phần mềm, nhưng nguy hiểm hơn ở chỗ: web sập thì ai cũng thấy ngay; còn một bảng báo cáo vẫn trả về số nhưng số sai thì trông như đang "up" — người dùng cứ ra quyết định trên nền cát.

Hậu quả của data downtime ở ngân hàng:

  • Quyết định sai: duyệt tín dụng, định giá rủi ro, cắt hạn mức trên số liệu lệch.
  • Mất niềm tin: một lần Ban điều hành phát hiện dashboard sai, họ quay lại xin file Excel — công sức data platform đổ sông.
  • Rủi ro tuân thủ: báo cáo NHNN nộp sai số phải đính chính, có thể bị xử phạt và tổn hại uy tín.

Công thức trực giác

Có thể ước lượng data downtime theo trực giác (không phải công thức chính xác tuyệt đối, dùng để định hướng cải thiện):

Data Downtime ≈ Số sự cố × (Thời gian phát hiện + Thời gian khắc phục)
                     (N)          (TTD)              (TTR)

Ba đòn bẩy để giảm downtime hiện rõ: giảm số sự cố (test/contract/quy trình đổi nguồn), giảm TTD — Time To Detect (observability, alert đúng), giảm TTR — Time To Resolve (runbook, rollback nhanh, WAP). Cải thiện observability chủ yếu đánh vào TTD; cải thiện quy trình xử lý đánh vào TTR; cải thiện chất lượng đầu vào đánh vào N.

SLI / SLO / SLA cho một Data Product

Coi mỗi bảng/báo cáo quan trọng là một data product có mức dịch vụ cam kết. Ba khái niệm cần tách bạch:

Khái niệmLà gìVí dụ dữ liệu
SLI (Indicator)Số đo được phản ánh chất lượngfreshness = độ trễ giờ; completeness = % bản ghi đủ
SLO (Objective)Mục tiêu nội bộ đặt trên SLI"freshness ≤ 2h trong 99% ngày làm việc"
SLA (Agreement)Cam kết với consumer, có hệ quả nếu vi phạm"báo cáo rủi ro sẵn sàng trước 8h, sai thì đính chính + thông báo trong 30')

Nguyên tắc: SLA lỏng hơn SLO một biên an toàn. Nếu cam kết với sếp SLA "đúng 8h", nội bộ nên đặt SLO "xong 7h30" để còn thời gian phản ứng.

Bốn nhóm SLI cốt lõi cho dữ liệu

  1. Freshness — dữ liệu mới nhất tới thời điểm nào; đo bằng MAX(created_at) so với now. Trễ = downtime kiểu "chưa có số".
  2. Completeness — có đủ bản ghi/đủ trường không; đo bằng % dòng, % null của trường khoá, số dòng so kỳ vọng. Thiếu = downtime kiểu "số bị hụt".
  3. Độ chính xác (accuracy) — số có đúng không; đo bằng reconciliation với nguồn gốc, tổng kiểm chứng (control total), quy tắc nghiệp vụ. Sai = downtime nguy hiểm nhất vì trông vẫn "có số".
  4. Availability — bảng/báo cáo có truy vấn được, đúng schema, đúng hạt không; đo bằng % thời gian query thành công đúng contract.

SLI freshness — check chạy được

-- ▶ Chạy được
SELECT
  MAX(created_at)                                        AS latest_txn,
  (CURRENT_DATE - MAX(created_at)::date)                 AS days_stale,
  ROUND(EXTRACT(EPOCH FROM (now() - MAX(created_at))) / 3600.0, 1) AS hours_stale,
  COUNT(*) FILTER (WHERE created_at::date = CURRENT_DATE) AS rows_today
FROM transactions;

days_stale > 0 hoặc hours_stale vượt ngưỡng SLO vào giờ báo cáo nghĩa là đang vi phạm freshness — mở sự cố. Ở mức thực chiến, freshness nên đo theo lát cắt (từng nguồn, từng chi nhánh) vì một nguồn trễ dễ bị "che" bởi phần còn lại đúng hạn.

SLI completeness — tỷ lệ null của trường khoá

Completeness đo mức độ "đủ" của bản ghi. Ví dụ đo tỷ lệ tài khoản thiếu số dư hoặc thiếu loại tiền — hai trường không được null nếu bảng lành mạnh:

-- ▶ Chạy được
SELECT
  COUNT(*)                                                          AS total_rows,
  COUNT(*) FILTER (WHERE balance IS NULL)                           AS null_balance,
  COUNT(*) FILTER (WHERE currency IS NULL OR currency = '')         AS missing_currency,
  ROUND(100.0 * COUNT(*) FILTER (WHERE balance IS NULL)
        / NULLIF(COUNT(*), 0), 2)                                   AS pct_null_balance,
  CASE
    WHEN COUNT(*) FILTER (WHERE balance IS NULL) = 0
     AND COUNT(*) FILTER (WHERE currency IS NULL OR currency = '') = 0
    THEN 'PASS' ELSE 'FAIL'
  END                                                               AS completeness_slo
FROM accounts;

SLO completeness kiểu "pct_null_balance = 0 trên trường khoá" cho ra kết quả nhị phân PASS/FAIL — dễ đưa lên bảng theo dõi.

Error budget — quản lý bằng ngân sách, không bằng cảm tính

SLO không phải "100%" (bất khả thi và tốn kém vô lý). Nếu SLO = 99% ngày làm việc đúng hạn, thì 1% còn lại là error budget — ngân sách được phép hỏng. Quản lý bằng budget cho ra quyết định khách quan:

  • Còn budget nhiều → ưu tiên tính năng mới, chấp nhận thay đổi rủi ro có kiểm soát.
  • Cháy budget (đã vi phạm quá mức cho phép) → đóng băng thay đổi, dồn lực vào ổn định (thêm test, thêm monitor, sửa nợ kỹ thuật) cho tới khi budget hồi.

Ví dụ: báo cáo rủi ro tín dụng đặt SLO freshness 99,5% ngày làm việc/quý (~63 ngày). Budget ≈ 0,5% × 63 ≈ 0,3 ngày trễ được phép/quý. Trễ 1 buổi sáng là gần cháy — kích hoạt cơ chế đóng băng.

Tier hoá data product

Không phải bảng nào cũng đáng cam kết 99,9%. Phân tier theo mức quan trọng để dồn công sức đúng chỗ:

TierVí dụSLO minh hoạOn-call
Tier 0 / VàngBáo cáo NHNN, báo cáo rủi ro, số liệu Ban điều hànhfreshness ≤ 2h, accuracy reconcile 100%, availability 99,9%có, escalation nhanh
Tier 1 / BạcDashboard nghiệp vụ chính, mart bán hàngfreshness ≤ 6h, completeness caogiờ hành chính
Tier 2 / ĐồngBảng thăm dò, sandbox phân tíchbest-effortkhông cam kết

Tier quyết định độ ưu tiên khi sự cốmức đầu tư test/monitor. Xem thêm cách gắn cam kết với Quality & Data Contracts.

Incident Management thực chiến — Playbook

Khi một SLI vi phạm SLO, ta mở data incident. Playbook chuẩn hoá các bước để đội trực không phải nghĩ:

1. Phát hiện (Detect)

Hai đường vào: chủ động (alert từ observability — freshness/volume/schema/distribution) và bị động (người dùng báo "số này trông sai"). Mục tiêu DRE là luôn phát hiện trước consumer — mỗi lần user báo trước là một lỗ hổng monitoring cần vá.

2. Phân loại severity (Triage)

Gán SEV theo tác động, không theo cảm tính:

SeverityTiêu chíVí dụ ngân hàng
SEV1Số liệu Tier 0 sai/thiếu, ảnh hưởng quyết định hoặc báo cáo cơ quan quản lýBáo cáo NHNN trễ hạn nộp / sai tổng dư nợ
SEV2Data product quan trọng sai nhưng có đường vòng, chưa tới hạn báo cáoDashboard rủi ro lệch nhưng còn 6h trước cuộc họp
SEV3Lỗi nhỏ, bảng phụ, không ảnh hưởng quyết địnhTrễ mart thăm dò nội bộ

SEV quyết định ai được gọi, gọi nhanh cỡ nào, và có được đánh thức lúc nửa đêm không.

3. Thông báo consumer sớm (Comms)

Đây là bước data-specific quan trọng nhất và hay bị bỏ. Khác downtime phần mềm (user tự thấy web sập), data downtime vô hình — nếu không báo, consumer vẫn dùng số sai. Nguyên tắc:

  • Báo sớm, báo rõ: "Báo cáo X có thể sai từ [giờ], đang điều tra, đừng dùng để ra quyết định, cập nhật sau 30'."
  • Gắn banner cảnh báo ngay trên dashboard nếu có thể (đánh dấu bảng "under investigation").
  • Mục tiêu số một: ngăn người dùng ra quyết định trên số sai, kể cả khi chưa biết nguyên nhân.

4. Kiềm chế (Contain)

Chặn thiệt hại lan rộng trước khi hiểu hết nguyên nhân:

  • Dừng pipeline đang đẩy dữ liệu bẩn xuống hạ nguồn.
  • Rollback về phiên bản dbt/artifact tốt gần nhất.
  • Giữ bản tốt cũ nhờ mẫu WAP (Write-Audit-Publish): dữ liệu mới ghi vào vùng staging, chỉ publish khi qua audit — nếu audit fail thì consumer vẫn thấy bản publish cũ (đúng), không thấy bản mới (sai). Xem Environments & WAP.

WAP biến "kiềm chế" từ thao tác khẩn cấp thành hành vi mặc định: bản sai đơn giản không bao giờ tới tay consumer.

5. Khắc phục (Fix)

Sửa gốc rồi backfill lại phần dữ liệu hỏng, chạy lại kiểm tra chất lượng, và publish bản đúng. Ghi lại mốc "resolved" khi SLI trở lại trong SLO — đây là mốc tính TTR.

6. RCA — Root Cause Analysis

Sau khi hết chảy máu, đào nguyên nhân gốc bằng 5 Whys (hỏi "tại sao" tới khi chạm nguyên nhân hệ thống, không dừng ở triệu chứng). Phân loại nguyên nhân giúp tìm biện pháp phòng ngừa đúng:

Nhóm nguyên nhânBiểu hiệnPhòng ngừa điển hình
Đổi nguồn / schema driftNguồn thượng nguồn đổi cột/kiểu/nghĩaschema check, data contract, cảnh báo thượng nguồn
Lỗi code / logicBug trong dbt/transformtest, code review, CI/CD
Dữ liệu trễ / muộnBatch nguồn chưa đổ đủfreshness monitor, sensor chờ nguồn
Hạ tầngWarehouse quá tải, job timeout, mạngretry, giám sát tài nguyên, hạ tải

Ví dụ 5 Whys: Tổng dư nợ sai → vì thiếu một chi nhánh → vì file nguồn chi nhánh đó tới trễ → vì pipeline không chờ mà chạy đúng giờ → vì không có sensor kiểm tra đủ nguồn.Biện pháp gốc: thêm completeness-gate chờ đủ nguồn trước khi tính tổng.

7. Hậu kiểm & phòng ngừa (Prevent)

Mỗi sự cố phải sinh ra ít nhất một test/monitor mới để lần sau tự bắt được. Đây là vòng học: sự cố hôm nay → test ngày mai. Không thêm phòng ngừa = chấp nhận sự cố sẽ tái diễn.

Phát hiện sự cố bằng volume-baseline

Một trong những check "bắt sự cố sớm" hiệu quả nhất: so số dòng mỗi ngày với baseline động (trung bình trượt), cờ khi lệch quá biên. Ngưỡng cứng sẽ sai vào cuối tuần/lễ; baseline động tự thích nghi:

-- ▶ Chạy được
WITH daily AS (
  SELECT created_at::date AS d, COUNT(*) AS n
  FROM transactions
  GROUP BY created_at::date
),
scored AS (
  SELECT
    d, n,
    AVG(n) OVER (ORDER BY d ROWS BETWEEN 7 PRECEDING AND 1 PRECEDING) AS baseline_7d
  FROM daily
)
SELECT
  d, n,
  ROUND(baseline_7d::numeric, 1)                                          AS baseline_7d,
  ROUND((100.0 * (n - baseline_7d) / NULLIF(baseline_7d, 0))::numeric, 1) AS pct_diff,
  CASE
    WHEN baseline_7d IS NULL                        THEN 'no-baseline'
    WHEN ABS(n - baseline_7d) > 0.30 * baseline_7d  THEN 'ANOMALY'
    ELSE 'ok'
  END                                                                     AS status
FROM scored
ORDER BY d DESC;

Dòng ANOMALYtín hiệu vào bước Detect của playbook: volume lệch > 30% so trung bình 7 ngày → nghi thiếu nguồn hoặc nhân đôi dữ liệu → mở incident, phân loại SEV.

On-call bền vững & Runbook

On-call cho data khác on-call phần mềm ở nhịp: nhiều sự cố là batch đêm, không phải realtime 24/7. Nguyên tắc bền vững để đội không kiệt sức:

  • Chỉ đánh thức khi cần: chỉ SEV1 (Tier 0) mới page lúc nửa đêm; SEV2/3 chờ giờ hành chính.
  • Giảm nhiễu: alert phải actionable — mỗi page phải có runbook đi kèm. Alert không hành động được thì tắt hoặc hạ cấp.
  • Escalation rõ: on-call → tech lead → data platform lead → chủ quản nghiệp vụ, mỗi bậc có thời gian chờ (ví dụ 15' không phản hồi thì lên bậc).

Runbook mẫu — "Freshness Tier 0 vi phạm"

RUNBOOK: Báo cáo rủi ro trễ (freshness SLO vi phạm)
1. XÁC NHẬN: chạy check freshness → days_stale/hours_stale thực tế?
2. PHÂN LOẠI: Tier 0 + qua giờ báo cáo → SEV1.
3. COMMS: gửi mẫu "báo cáo có thể trễ, đừng dùng, cập nhật sau 30'".
4. KHOANH VÙNG: nguồn nào trễ? (check freshness theo lát cắt)
5. KIỀM CHẾ: giữ bản publish hôm qua (WAP), KHÔNG publish bản thiếu.
6. FIX: chờ/kích nguồn trễ → backfill → chạy lại audit → publish.
7. ĐÓNG: xác nhận SLI về SLO, ghi mốc resolved, hẹn postmortem.

Runbook tốt = người trực mới cũng xử lý được mà không cần gọi kiến trúc sư.

Blameless Postmortem & đo lường độ tin cậy

Blameless postmortem: sau SEV1/SEV2, họp mổ xẻ tập trung vào hệ thống và quy trình, không đổ lỗi cá nhân. Con người mắc lỗi; hệ thống tốt là hệ thống chịu được lỗi người. Đổ lỗi khiến người ta giấu sự cố — thứ độc hại nhất cho độ tin cậy. Mỗi postmortem chốt action item có chủ và deadline.

Đo độ tin cậy bằng số để cải tiến có định hướng:

Chỉ sốÝ nghĩaMục tiêu
MTTD (Mean Time To Detect)Trung bình phát hiện sau khi hỏngcàng nhỏ càng tốt — đo hiệu quả monitoring
MTTR (Mean Time To Resolve)Trung bình từ phát hiện đến sửa xongđo hiệu quả playbook/runbook
Số sự cố (theo tier/SEV)Tần suất hỏngxu hướng giảm = chất lượng lên
Data uptime% thời gian data product trong SLObáo cáo lên lãnh đạo

Văn hoá reliability đóng khung tất cả: cam kết đo được, minh bạch khi hỏng, học từ sự cố thay vì trừng phạt. Đó là thứ biến một đội "hay chữa cháy" thành đội "ít cháy".

Use case thực tế

Bối cảnh NCB, báo cáo tổng dư nợ theo chi nhánh nộp NHNN, hạn 8h sáng — data product Tier 0, SLO freshness ≤ 2h và accuracy reconcile 100%.

  • 06:12 — alert volume-baseline: số giao dịch hôm qua lệch −18% so trung bình 7 ngày (status = ANOMALY). Đồng thời freshness check cho days_stale = 0 nhưng completeness theo lát cắt thấy thiếu 1/40 chi nhánh. TTD ≈ vài phút nhờ monitor (không phải chờ user báo).
  • 06:15 — Triage: Tier 0, qua ngưỡng, còn <2h tới hạn nộp → SEV1.
  • 06:18 — Comms: gửi cán bộ báo cáo: "Tổng dư nợ có thể thiếu 1 chi nhánh, chưa nộp, cập nhật 06:45." Gắn banner "under investigation" trên dashboard → ngăn nộp số sai.
  • 06:20 — Contain: nhờ WAP, bản thiếu chưa publish; consumer vẫn thấy bản hôm qua (đúng), không thấy bản thiếu.
  • 06:25 — Fix: khoanh vùng → file chi nhánh tới trễ do sự cố mạng nguồn; kích lại ingest, backfill, chạy lại audit reconcile control-total = khớp → publish.
  • 06:40 — Resolve: SLI về SLO, nộp đúng hạn. MTTR ≈ 28'.
  • RCA (5 Whys): thiếu chi nhánh → file trễ → pipeline không chờ đủ nguồn → không có completeness-gate. Nguyên nhân nhóm "dữ liệu trễ".
  • Prevent: thêm sensor chờ đủ 40/40 nguồn trước khi tính tổng; thêm alert freshness theo lát cắt chi nhánh. Postmortem blameless, action item có chủ.

Kết quả: nhờ comms + WAP, không có số sai nào nộp NHNN dù nguồn trễ — đúng mục tiêu tối thượng của DRE.

Ghi nhớ

  • Data Downtime = khoảng dữ liệu sai/thiếu/trễ/không dùng được; nguy hiểm vì thường vô hình (bảng vẫn trả số). Trực giác: Downtime ≈ N × (TTD + TTR).
  • Tách SLI (đo được) / SLO (mục tiêu nội bộ) / SLA (cam kết với consumer); SLA nên lỏng hơn SLO một biên an toàn.
  • Bốn nhóm SLI: freshness, completeness, accuracy, availability. Đặt SLO theo tier — Tier 0 (báo cáo NHNN) cam kết cao nhất.
  • Error budget cho quyết định khách quan: còn budget → làm mới; cháy budget → đóng băng thay đổi, dồn lực ổn định.
  • Playbook: detect → triage (SEV1-3) → comms sớm (ngăn dùng số sai) → contain (dừng/rollback/WAP) → fix (backfill) → RCA (5 whys) → prevent.
  • Comms là bước data-specific quan trọng nhất — data downtime vô hình, không báo thì consumer vẫn ra quyết định sai.
  • RCA phân loại nguyên nhân (đổi nguồn/schema, lỗi code, dữ liệu trễ, hạ tầng) để phòng ngừa đúng; mỗi sự cố sinh ≥1 test/monitor mới.
  • On-call bền vững: chỉ page SEV1, alert phải actionable + có runbook, escalation rõ. Blameless postmortem để người ta không giấu sự cố.
  • Đo bằng MTTD, MTTR, số sự cố, data uptime; văn hoá reliability = cam kết đo được + minh bạch + học từ lỗi.

Bài viết liên quan

CSV/JSON/Parquet/Avro, lưu trữ theo hàng vs cột, nén, và OLTP vs OLAP.

13 thg 7, 2026 8

Data Engineering là gì, vai trò trong vòng đời dữ liệu, và bức tranh hệ sinh thái công cụ.

13 thg 7, 2026 5

Vì sao xử lý phân tán, mô hình Spark (RDD/DataFrame), lazy evaluation, shuffle và tối ưu.

13 thg 7, 2026 5

Đảm bảo chất lượng & minh bạch dữ liệu bằng dbt: data tests dựng sẵn (unique, not_null, relationships, accepted_values), singular test, unit test, và tài liệu tự sinh kèm lineage graph.

13 thg 7, 2026 5