166 lines
7.7 KiB
Markdown
166 lines
7.7 KiB
Markdown
# PART 2 — biến thể `data-pipeline`
|
||
|
||
> **Dùng khi** `PRODUCT = data-pipeline` — sản phẩm là **dữ liệu**: ETL, ingest, kho dữ
|
||
> liệu, báo cáo BI. Cắm khối này vào chỗ PART 2 của [`../srs.md`](../srs.md).
|
||
>
|
||
> **Tiêu chí G3 riêng của biến thể này**: mỗi luồng có data contract nguồn và đích · bảng
|
||
> ánh xạ trường đầy đủ · quy tắc chất lượng có ngưỡng và hành vi khi vi phạm · **có mục đối
|
||
> soát nguồn–đích** · đã trả lời xong chạy lại/backfill/dữ liệu đến muộn.
|
||
|
||
🔴 **Người dùng của bạn không nhìn thấy sản phẩm — họ nhìn thấy những con số.** Con số sai
|
||
mà không ai biết là chế độ hỏng nguy hiểm nhất của loại sản phẩm này, vì nó im lặng. Vì vậy
|
||
§2.6 (đối soát) và §2.5 (chất lượng) là hai mục quan trọng nhất, không phải phần phụ.
|
||
|
||
---
|
||
|
||
## 2.1 Danh sách luồng dữ liệu
|
||
|
||
| ID | Luồng | Nguồn | Đích | Tần suất | Kiểu | Khối lượng/lần | BR |
|
||
|---|---|---|---|---|---|---|---|
|
||
| FLW-01 | | | | Hằng đêm 02:00 | Toàn bộ / Tăng dần / CDC | ~… bản ghi | |
|
||
|
||
## 2.2 Sơ đồ lineage
|
||
|
||
<!-- archify: dataflow · diagrams/SRS_<US>_lineage.dataflow.json -->
|
||
```mermaid
|
||
flowchart LR
|
||
POS[["POS API"]]
|
||
ERP[["ERP export CSV"]]
|
||
STG[("staging.pos_raw")]
|
||
DW[("dw.fact_sales")]
|
||
RPT(["Báo cáo doanh thu"])
|
||
NGUOIDOC(["👤 Kế toán, Ban giám đốc"])
|
||
|
||
POS -->|FLW-01| STG
|
||
STG -->|FLW-02| DW
|
||
ERP -->|FLW-03| DW
|
||
DW --> RPT
|
||
RPT --> NGUOIDOC
|
||
```
|
||
|
||
*Trụ `[( )]` = kho dữ liệu · khung đôi `[[ ]]` = nguồn ngoài, không do mình sở hữu · bo tròn
|
||
`([ ])` = đầu ra và người đọc. Nhãn cạnh là mã luồng `FLW-nn`, khớp bảng §2.1.*
|
||
|
||
🔴 **Vẽ tới tận người tiêu thụ cuối** — báo cáo nào, **ai đọc**. Dừng ở bảng dữ liệu thì khi
|
||
luồng hỏng lúc 2 giờ sáng không ai biết phải báo cho ai, và không đánh giá được mức nghiêm
|
||
trọng.
|
||
|
||
**Bảng đi kèm** *(quy tắc W13)*:
|
||
|
||
| Luồng | Nguồn → Đích | Tần suất | SLA độ tươi | Hỏng thì ai bị ảnh hưởng | Chủ sở hữu nguồn |
|
||
|---|---|---|---|---|---|
|
||
| FLW-01 | POS API → staging | Hằng đêm 02:00 | D+1 08:00 | Toàn bộ chuỗi phía sau | NCC X — anh Huy |
|
||
|
||
## 2.3 FLW-01 — <Tên luồng>
|
||
|
||
### 2.3.1 Nguồn
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Hệ thống nguồn** | |
|
||
| **Cách lấy** | API / file / CDC / queue |
|
||
| **Ai sở hữu nguồn** | *(đầu mối khi schema đổi)* |
|
||
| **Nguồn có báo trước khi đổi schema không** | 🔴 Không ⇒ phải có phát hiện schema drift |
|
||
| **Cửa sổ dữ liệu sẵn sàng** | *(từ mấy giờ nguồn mới có đủ dữ liệu hôm qua)* |
|
||
|
||
### 2.3.2 SLA độ tươi
|
||
|
||
*Thay cho "thời gian phản hồi" của biến thể `screen`.*
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Dữ liệu ngày D phải sẵn sàng trước** | D+1 08:00 |
|
||
| **Trễ tối đa chấp nhận được** | |
|
||
| **Ai được báo khi trễ** | |
|
||
| **Người dùng thấy gì khi dữ liệu chưa tới** | 🔴 Số cũ? Số rỗng? **Có nhãn cảnh báo không?** |
|
||
|
||
🔴 Câu cuối là câu hay bị bỏ nhất. Báo cáo hiển thị số của hôm kia mà không có nhãn "dữ liệu
|
||
tới 28/08" là cách người dùng ra quyết định trên số cũ mà không biết.
|
||
|
||
### 2.3.3 Data contract — schema nguồn
|
||
|
||
| Trường nguồn | Kiểu | Có thể null | Nghĩa nghiệp vụ | Giá trị hợp lệ | Ghi chú |
|
||
|---|---|---|---|---|---|
|
||
|
||
### 2.3.4 Ánh xạ trường
|
||
|
||
| Trường đích | Từ trường nguồn | Phép biến đổi | Khi nguồn null | Khi nguồn sai định dạng | BR |
|
||
|---|---|---|---|---|---|
|
||
| `store_code` | `shop.id` | upper(trim(x)) | → `UNKNOWN` | → quarantine | BR-0nn |
|
||
| `amount` | `total` | chia 100 (nguồn lưu đơn vị nhỏ nhất) | → 0 | → quarantine | BR-0nn |
|
||
|
||
🔴 **Ba cột cuối là phần thay thế cho "validation + message lỗi" của biến thể `screen`.**
|
||
Bỏ trống ⇒ kỹ sư dữ liệu tự quyết, và mỗi luồng một kiểu.
|
||
|
||
### 2.3.5 Khoá và trùng lặp
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Khoá nghiệp vụ** | *(cái gì xác định một bản ghi là duy nhất)* |
|
||
| **Nguồn có gửi trùng không** | |
|
||
| **Trùng thì xử lý sao** | Giữ bản mới nhất / cộng dồn / báo lỗi |
|
||
| **Bản ghi bị sửa ở nguồn** | Ghi đè / giữ lịch sử (SCD loại mấy) |
|
||
|
||
## 2.4 Quy tắc chất lượng dữ liệu
|
||
|
||
| ID | Kiểm tra gì | Ngưỡng | Vi phạm thì làm gì | Ai được báo |
|
||
|---|---|---|---|---|
|
||
| DQ-01 | Số bản ghi so với trung bình 7 ngày | ±30% | ⚠️ Cảnh báo, vẫn nạp | |
|
||
| DQ-02 | Tỷ lệ `store_code` không map được | > 1% | 🛑 **Dừng luồng** | |
|
||
| DQ-03 | Tổng tiền âm | > 0 bản ghi | 🔴 Quarantine bản ghi đó | |
|
||
|
||
**Ba hành vi khi vi phạm — chọn rõ một, không được để mơ hồ:**
|
||
|
||
| Hành vi | Nghĩa | Dùng khi |
|
||
|---|---|---|
|
||
| `drop` | Bỏ bản ghi, ghi log | Bản ghi rác đã biết, không ảnh hưởng tổng |
|
||
| `quarantine` | Tách sang bảng riêng để xử lý tay | 🔴 **Mặc định nên chọn** — giữ được dữ liệu để điều tra |
|
||
| `fail` | Dừng cả luồng | Sai lệch có thể làm hỏng báo cáo tài chính |
|
||
|
||
🔴 **`drop` im lặng là chế độ hỏng tệ nhất.** Số liệu thiếu mà không ai biết. Chọn `drop`
|
||
phải kèm ngưỡng cảnh báo.
|
||
|
||
## 2.5 Trạng thái tương đương "màn hình rỗng"
|
||
|
||
| Tình huống | Xử lý | Người dùng thấy gì |
|
||
|---|---|---|
|
||
| Ngày không có giao dịch nào (chủ nhật, lễ) | Nạp 0 bản ghi — **không phải lỗi** | Báo cáo hiện 0, có nhãn "không có giao dịch" |
|
||
| Nguồn không phản hồi | | |
|
||
| Nguồn trả rỗng bất thường | 🔴 Phân biệt với ca trên bằng cách nào? | |
|
||
|
||
Phân biệt **"không có dữ liệu"** với **"chưa lấy được dữ liệu"** là bắt buộc. Hai thứ này
|
||
nhìn giống nhau trên báo cáo nhưng ý nghĩa ngược nhau.
|
||
|
||
## 2.6 Đối soát nguồn – đích
|
||
|
||
🔴 **Mục bắt buộc, không được bỏ.** Đây là thứ duy nhất chứng minh dữ liệu không bị mất
|
||
giữa đường.
|
||
|
||
| # | Đối chiếu gì | Nguồn | Đích | Sai lệch cho phép | Tần suất | Ai kiểm |
|
||
|---|---|---|---|---|---|---|
|
||
| 1 | Số bản ghi | count(pos_api) | count(fact_sales) | 0 | Mỗi lần chạy | Tự động |
|
||
| 2 | Tổng tiền | sum(total) | sum(amount)×100 | ≤ 1 đơn vị (làm tròn) | Hằng ngày | Tự động |
|
||
| 3 | Đối chiếu với báo cáo hệ thống cũ | | | | Hằng tháng | Kế toán |
|
||
|
||
**Sai lệch vượt ngưỡng thì làm gì, ai chịu trách nhiệm xử lý:** …
|
||
|
||
## 2.7 Chạy lại, backfill, dữ liệu đến muộn
|
||
|
||
| Câu hỏi | Trả lời |
|
||
|---|---|
|
||
| **Chạy lại cùng một ngày hai lần** → kết quả có giống không (idempotent)? | 🔴 Không idempotent ⇒ nói rõ quy trình dọn trước khi chạy lại |
|
||
| **Backfill** lịch sử N ngày làm thế nào? Mất bao lâu? Ảnh hưởng báo cáo đang chạy không? | |
|
||
| **Dữ liệu đến muộn** (giao dịch hôm qua tới hôm nay) | Nạp vào ngày phát sinh hay ngày nhận? |
|
||
| Nạp vào ngày phát sinh ⇒ **báo cáo đã chốt có thay đổi không?** | 🔴 Nếu có, ai được báo |
|
||
| **Thất bại giữa chừng** | Rollback toàn bộ / tiếp tục từ checkpoint |
|
||
|
||
## 2.8 Vận hành
|
||
|
||
| | |
|
||
|---|---|
|
||
| Chạy tự động lúc | |
|
||
| Chạy tay được không, ai được chạy | |
|
||
| Cảnh báo gửi đi đâu | |
|
||
| Ai trực khi luồng hỏng ban đêm | |
|
||
| Hỏng bao lâu thì phải báo người dùng | |
|