DataOps nâng cao 14 — DataOps trong Data Mesh & quy mô
Khi một đội data trung tâm hết đường mở rộng
Các bài trước của series đã cho ta một bộ công cụ hoàn chỉnh: kiến trúc DataOps (DataOps nâng cao 1 — Kiến trúc), dbt, Airflow, CI/CD, data contract, observability, và một nền tảng self-service (DataOps nâng cao 7 — Platform & self-service). Tất cả đủ để một đội làm rất tốt. Câu hỏi của bài này khác: làm sao vận hành DataOps khi tổ chức có hàng chục domain và một đội trung tâm không còn kham nổi?
Ở NCB quy mô lớn, một đội data trung tâm duy nhất sẽ trở thành nút thắt. Mọi yêu cầu dữ liệu — thẻ, tín dụng, huy động, thanh toán, rủi ro, kênh số — đều xếp hàng vào một đội. Đội đó không hiểu sâu nghiệp vụ từng lĩnh vực, nên vừa chậm vừa dễ hiểu sai. Thêm domain thì backlog dài thêm, không phải năng lực tăng thêm. Đây là giới hạn cấu trúc, không phải giới hạn con người: thông lượng bị chặn bởi một điểm nghẽn duy nhất.
Lời giải là phi tập trung: chuyển quyền sở hữu và vận hành dữ liệu về cho domain — nơi hiểu nghiệp vụ nhất. Đó chính là Data Mesh (Data Mesh — Tổng quan). Bài này không nhắc lại lý thuyết mesh, mà trả lời một câu rất cụ thể: DataOps trông như thế nào trong một tổ chức data mesh?
DataOps đi từ "một đội" sang "mỗi domain"
Ý tưởng then chốt: DataOps không biến mất khi phi tập trung, nó được nhân bản có kiểm soát. Mỗi domain vận hành vòng đời DataOps đầy đủ cho data product của chính mình: ingest → transform → serve, kèm test, observability và SLA.
Ba trụ cột khiến mô hình này chạy được mà không hỗn loạn:
- Nền tảng self-service cấp năng lực để domain tự chủ nhưng nhất quán.
- Data contract làm giao diện giữa các domain — ghép dữ liệu mà không cần biết nội bộ nhau.
- Federated computational governance nhúng chuẩn chung vào nền tảng và CI dưới dạng code — tuân thủ mà không cần gác cổng thủ công.
Ta đi qua từng trụ cột.
Mỗi domain vận hành DataOps cho data product của mình
Trong data mesh, đơn vị sở hữu không phải "một bảng" mà là data product: một tài sản dữ liệu được đối xử như sản phẩm — có chủ, có SLA, có tài liệu, có giao diện rõ ràng. Domain Thẻ sở hữu và vận hành card_txn_daily, card_customer_360; domain Huy động sở hữu deposit_balance_daily; v.v.
Vận hành một data product đầy đủ nghĩa là domain tự lo cả vòng đời:
| Giai đoạn | Domain tự làm | Trách nhiệm DataOps |
|---|---|---|
| Ingest | Khai báo nguồn (core banking, card switch, file) qua khung EL chung | Test tính đầy đủ, freshness của landing |
| Transform | Viết model dbt trong repo của domain | Test schema/business, review qua PR, CI |
| Serve | Publish data product theo contract | Bảo đảm SLA, phát tín hiệu freshness |
| Operate | Giám sát pipeline của mình | On-call, xử lý incident, đo SLO |
Điểm mấu chốt: quyền sở hữu đi kèm trách nhiệm vận hành. Domain Thẻ không chỉ "viết SQL" rồi ném qua tường; họ on-call cho data product của mình, đo SLO, sửa incident. Đây là điều bài Data Mesh 3 — Data as a product gọi là "you build it, you run it" áp cho dữ liệu.
Nhưng nếu mỗi domain tự dựng lại toàn bộ hạ tầng thì ta quay về đúng vấn đề của bài 7: N cách làm, N mức chất lượng, N chỗ rò rỉ PII. Đó là lý do tự chủ phải đặt trên nền tảng chung.
Nền tảng self-service: tự chủ mà vẫn nhất quán
Nền tảng self-service là thứ giải quyết nghịch lý "phi tập trung nhưng đừng hỗn loạn". Nó cung cấp năng lực (capability) để domain tự lấy dùng, không cần đội platform can thiệp tay:
- EL chuẩn hoá: domain khai báo nguồn thay vì tự viết loader — cùng cách landing, đặt tên, bắt CDC.
- dbt template: project mẫu với macro chung (chuẩn hoá tiền tệ, mã hoá PII, quy ước staging/marts), test mặc định.
- Airflow managed + CI/CD template: domain chỉ deploy DAG và dán pipeline mẫu, không tự vá hạ tầng.
- Quality & observability bật sẵn: contract, test, freshness, anomaly detection mặc định — kế thừa DataOps nâng cao 5 — Quality & contracts và DataOps nâng cao 6 — Observability & DRE.
- Catalog & lineage tự động: mọi model đăng ký vào catalog, lineage sinh từ dbt.
Nền tảng giấu độ phức tạp sau một giao diện đơn giản (một file khai báo, một PR). Domain được tự chủ về nội dung (logic nghiệp vụ, mô hình dữ liệu) trong khi nền tảng bảo đảm tính nhất quán về cách làm (cách test, cách publish, cách mã hoá PII). Đội platform vẫn nhỏ vì họ làm nền tảng, không làm hộ pipeline cho từng domain.
Data contract: giao diện giữa các domain
Khi domain Tín dụng cần dữ liệu giao dịch từ domain Thẻ, họ không đọc thẳng bảng nội bộ của Thẻ. Làm vậy tạo ra khớp nối chặt: Thẻ đổi tên cột là Tín dụng gãy, và không ai dám refactor. Thay vào đó, hai domain nói chuyện qua data contract (Data Mesh 4 — Data contracts): một cam kết máy đọc được về schema, ngữ nghĩa, chất lượng và SLA của data product được publish.
Contract là giao diện ổn định: nội bộ Thẻ tự do thay đổi, miễn là cái publish ra vẫn đúng contract. Đây chính là "encapsulation" áp cho dữ liệu ở quy mô tổ chức.
# minh hoạ — data contract của product "card_txn_daily" (domain Thẻ publish)
# KHÔNG phải cú pháp chạy được; minh hoạ hình dạng contract
dataProduct: card_txn_daily
domain: the
owner: [email protected]
version: 2.1.0
sla:
freshness: "trước 07:00 hằng ngày (T+1)"
availability: "99.5%"
schema:
- name: customer_id # khoá liên domain — join được với các product khác
type: string
classification: pii
nullable: false
- name: txn_date
type: date
nullable: false
- name: txn_amount
type: decimal(18,2)
unit: VND
quality:
- customer_id không null và tồn tại trong master customer
- txn_amount >= 0
- không trùng (customer_id, txn_date, txn_id)
Vai trò của DataOps là enforce contract ở ranh giới:
- Bên publish: CI của domain Thẻ chạy test kiểm mọi mệnh đề trong contract trước khi publish. Vi phạm → chặn deploy, không để dữ liệu xấu ra ngoài.
- Kiểm soát breaking change: đổi schema không tương thích phải tăng major version và báo trước cho bên tiêu thụ — CI phát hiện breaking change và chặn merge (kỹ thuật từ bài 5).
- Bên tiêu thụ: domain Tín dụng viết code dựa trên contract phiên bản cụ thể, không dựa vào chi tiết nội bộ.
Contract biến ranh giới domain thành API có kiểm thử tự động, thay vì một mối phụ thuộc ngầm dễ gãy.
Federated computational governance: chuẩn chung như policy-as-code
Đây là mảnh ghép quan trọng nhất và cũng dễ làm sai nhất. Phi tập trung mà không có chuẩn chung thì dữ liệu các domain không ghép được: mỗi domain định danh khách hàng một kiểu, phân loại PII một kiểu, định nghĩa "giao dịch thành công" một kiểu. Nhưng nếu quay lại một ban governance trung tâm duyệt tay mọi thứ thì ta lại tạo nút thắt mới — đúng cái ta muốn tránh.
Lời giải là federated computational governance (Data Mesh 6 — Federated governance): các domain cùng thống nhất một bộ chuẩn tối thiểu, rồi nhúng chuẩn đó vào nền tảng và CI dưới dạng CODE (policy-as-code) để nó tự thực thi. Ba chữ trong tên nói lên tất cả:
- Federated (liên bang): chuẩn do các domain cùng quyết, không áp từ trên xuống.
- Computational (tính toán): chuẩn được thực thi bằng máy trong pipeline, không phải bằng người gác cổng.
- Governance (quản trị): vẫn có kiểm soát và tuân thủ — chỉ là tự động.
Các chuẩn chung điển hình cho NCB:
| Nhóm chuẩn | Nội dung | Thực thi bằng |
|---|---|---|
| Định danh | Mọi product dùng chung khoá customer_id từ master customer | Test contract: khoá tồn tại trong master |
| Chất lượng tối thiểu | Mọi product có test not-null/unique cho khoá + freshness | dbt test bật mặc định trong template |
| Bảo mật/PII | Cột PII phải gắn nhãn + mã hoá/masking theo chuẩn | Policy quét metadata trong CI; xem Mã hoá & masking |
| Interoperability | Kiểu dữ liệu, đơn vị (VND), format ngày chuẩn hoá | Linter schema trong CI |
Điểm cốt lõi: policy sống trong CI, không sống trong đầu người review. Ví dụ minh hoạ một policy quét PII (giả mã, không phải công cụ thật):
# minh hoạ — policy-as-code chạy trong CI của MỌI domain (do platform cấp)
# KHÔNG phải mã chạy được; minh hoạ ý tưởng
def check_pii_masking(model_metadata):
for col in model_metadata.columns:
if col.classification == "pii" and not col.masking_policy:
fail(f"Cột PII '{col.name}' chưa gắn masking policy — chặn merge")
return "ok"
def check_shared_customer_key(contract):
# interoperability: mọi product phải join được qua customer_id chuẩn
if "customer_id" not in contract.join_keys:
warn("Product không expose customer_id — sẽ không ghép được liên domain")
Với cách này, domain vừa tự chủ (viết logic nghiệp vụ theo ý mình) vừa tuân thủ (không thể merge nếu vi phạm chuẩn chung) — mà không cần một người ngồi duyệt từng PR. Governance trở thành một phần của nền tảng, thừa hưởng đúng tinh thần policy-as-code từ bài 7.
SLA/SLO cho data product ở quy mô
Ở mesh, mỗi domain cam kết SLA cho data product của mình trong contract (freshness, availability, độ chính xác). Nhưng cam kết phân tán sẽ vô nghĩa nếu không có cách đo và giám sát tập trung. Mô hình đúng:
- Cam kết phân tán: domain định nghĩa SLO trong contract (ví dụ Thẻ:
card_txn_dailysẵn sàng trước 07:00, availability 99.5%). - Đo phân tán: pipeline mỗi domain phát tín hiệu freshness/chất lượng khi publish.
- Giám sát tập trung: một dashboard SLO toàn tổ chức tổng hợp mọi data product — ai đang vi phạm SLA, product nào ảnh hưởng downstream nào (dựa vào lineage). Đội platform vận hành dashboard, không vận hành pipeline.
Nhờ đó lãnh đạo dữ liệu nhìn được sức khoẻ toàn bộ mesh trong một chỗ, dù không đội nào sở hữu tất cả pipeline. Đây là "quan sát tập trung, vận hành phân tán".
Lineage & catalog liên domain
Khi dữ liệu chảy xuyên domain (product của Thanh toán dùng product của Thẻ, product của Rủi ro dùng cả hai), hai năng lực trở thành sống còn:
- Catalog liên domain: một nơi để khám phá mọi data product của mọi domain — ai sở hữu, contract phiên bản nào, SLA ra sao. Không có catalog, mesh biến thành "hàng chục silo mới" — analyst domain này không biết domain kia có gì.
- Lineage liên domain: truy vết dòng dữ liệu xuyên ranh giới domain. Khi domain Thẻ định đổi schema, họ thấy ngay ai đang phụ thuộc để báo trước. Khi có incident chất lượng, ta truy ngược qua nhiều domain để tìm gốc.
Cả hai kế thừa Governance — Catalog & lineage, nhưng ở mesh chúng phải tự động sinh và xuyên domain — vì không ai có toàn cảnh bằng tay. Lineage xuyên domain cũng là thứ làm cho dashboard SLO ở trên có nghĩa: biết product nào hỏng thì kéo theo product nào.
Đánh đổi của phi tập trung
Phi tập trung không miễn phí. Đánh đổi trung tâm là tự chủ đổi lấy nguy cơ trùng lặp và không nhất quán:
| Được | Mất / Rủi ro | Cách giảm thiểu |
|---|---|---|
| Domain tự chủ, đi nhanh, hiểu nghiệp vụ | Có thể trùng lặp logic (nhiều domain tự tính "khách hàng active") | Chuẩn chung + product dùng lại qua contract |
| Không nút thắt trung tâm | Không nhất quán định nghĩa/định danh | Federated governance (policy-as-code) |
| Trách nhiệm rõ ràng theo domain | Chi phí nền tảng + học tập ban đầu cao | Golden path, template, onboarding |
| Mở rộng theo số domain | Cần kỷ luật cao ở từng domain | CI chặn cứng, không dựa thiện chí |
Chìa khoá: chuẩn chung chính là thứ giải quyết mặt trái của phi tập trung. Không có nó, tự chủ biến thành hỗn loạn. Có nó (và thực thi tự động), ta được tự chủ mà vẫn ghép được dữ liệu.
Khi nào mesh phù hợp — và khi nào không
Data mesh không phải mặc định tốt cho mọi tổ chức. Nó là lời giải cho vấn đề quy mô, và nếu chưa có vấn đề đó thì mesh chỉ thêm chi phí:
- Mesh phù hợp: tổ chức lớn, nhiều domain rõ ràng, mỗi domain có đội kỹ thuật đủ mạnh để tự vận hành, và đội trung tâm đã thực sự thành nút thắt.
- Tập trung vẫn tốt hơn: tổ chức nhỏ, ít domain, một đội data đủ kham. Áp mesh lúc này là "over-engineering" — ta gánh chi phí nền tảng + governance mà không thu được lợi ích mở rộng.
- Áp dụng từng phần: không cần "tất cả hoặc không". Có thể bắt đầu bằng vài domain trưởng thành nhất chuyển sang tự vận hành trên nền tảng chung, giữ phần còn lại tập trung, rồi mở rộng dần khi nền tảng và governance chín.
Nói cách khác: chọn mesh vì bạn có vấn đề quy mô, không vì nó thời thượng. Data Mesh 8 — Áp dụng trong ngân hàng đi sâu hơn về lộ trình.
Kiểm interoperability trên sandbox
Chuẩn interoperability quan trọng nhất là khoá liên domain chung: mọi data product phải join được qua customer_id (hoặc tương đương). Nếu hai "domain" tuân chuẩn này, dữ liệu của chúng ghép được mà không cần biết nội bộ nhau. Dưới đây là minh hoạ chạy được trên sandbox: coi accounts như output của "domain Huy động" và transactions như output của "domain Thanh toán", ta ghép hai bên qua chuỗi khoá chung về customers — đúng tinh thần một truy vấn liên domain trong mesh:
-- ▶ Chạy được
-- Minh hoạ interoperability: ghép "2 domain" qua khoá khách hàng chung
-- accounts ~ domain Huy động; transactions ~ domain Thanh toán; nối về customers
SELECT
c.id AS customer_id,
c.full_name,
c.city,
COUNT(DISTINCT a.id) AS so_tai_khoan, -- từ "domain Huy động"
COALESCE(SUM(a.balance),0) AS tong_so_du,
COUNT(t.id) AS so_giao_dich, -- từ "domain Thanh toán"
COALESCE(SUM(t.amount),0) AS tong_gia_tri_gd
FROM customers c
LEFT JOIN accounts a ON a.customer_id = c.id
LEFT JOIN transactions t ON t.account_id = a.id
GROUP BY c.id, c.full_name, c.city
ORDER BY tong_gia_tri_gd DESC
LIMIT 20;
Câu này minh hoạ điều cốt lõi: khi khoá join chuẩn hoá được enforce ở ranh giới (qua contract + policy), dữ liệu từ nhiều domain ghép được ngay thành cái nhìn 360 về khách hàng — dù mỗi domain do một đội khác vận hành hoàn toàn độc lập.
Use case thực tế
Bối cảnh: NCB trưởng thành, có 5 domain dữ liệu độc lập: Thẻ, Tín dụng, Huy động, Thanh toán, Rủi ro. Đội data trung tâm trước đây xử lý mọi thứ, backlog trung bình 6 tuần, mỗi báo cáo rủi ro tổng hợp mất 2 tuần chỉ để gom dữ liệu.
Chuyển sang mesh (áp dụng từng phần, 3 quý):
- Quý 1 — Đội platform (5 người, tách từ đội trung tâm) dựng nền tảng self-service: EL chuẩn, dbt template, Airflow managed, CI/CD template, quality/observability bật sẵn, catalog + lineage tự động. Song song, 5 domain cùng họp chốt bộ chuẩn chung: khoá
customer_idtừ master, PII taxonomy, đơn vị VND, format ngày. Chuẩn này được viết thành policy-as-code nhúng vào CI template. - Quý 2 — Hai domain trưởng thành nhất (Thẻ, Huy động) chuyển sang tự vận hành. Mỗi domain publish data product theo contract có SLA (freshness trước 07:00, availability 99.5%). CI chặn merge nếu vi phạm contract hoặc thiếu masking PII. Ba domain còn lại tạm giữ tập trung.
- Quý 3 — Ba domain còn lại lên nền tảng. Báo cáo rủi ro tổng hợp giờ join các data product qua
customer_idchuẩn thay vì gom tay từng nguồn.
Kết quả (minh hoạ định lượng):
| Chỉ số | Trước (tập trung) | Sau (mesh từng phần) |
|---|---|---|
| Backlog trung bình / yêu cầu | ~6 tuần | ~1 tuần (domain tự làm) |
| Thời gian gom dữ liệu báo cáo rủi ro | ~2 tuần | ~2 ngày (ghép qua contract) |
| Số PR bị chặn do vi phạm PII/contract | (không đo, phát hiện muộn) | Chặn tại CI, 0 rò rỉ ra prod |
| Quy mô đội platform | (cả đội trung tâm ~20) | 5 người vận hành nền tảng |
Điểm mấu chốt: đội platform không làm hộ pipeline domain nào; họ vận hành nền tảng và dashboard SLO. Governance không có ai gác cổng tay — mọi chuẩn tự thực thi trong CI. Dữ liệu 5 domain ghép được và tuân thủ vì contract + policy-as-code bảo đảm điều đó ở ranh giới.
Ghi nhớ
- Vấn đề: một đội data trung tâm không mở rộng nổi khi tổ chức lớn — nó là nút thắt cấu trúc; lời giải là phi tập trung về domain (Data Mesh).
- DataOps trong mesh không biến mất mà được nhân bản có kiểm soát: mỗi domain vận hành DataOps đầy đủ (ingest→transform→serve + test + observability + SLA) cho data product của mình.
- Nền tảng self-service cấp năng lực chung để domain tự chủ mà nhất quán — đội platform vẫn nhỏ vì làm nền tảng, không làm hộ pipeline.
- Data contract là giao diện giữa các domain: cam kết máy đọc được về schema/ngữ nghĩa/chất lượng/SLA; DataOps enforce contract ở ranh giới (CI chặn publish nếu vi phạm, kiểm soát breaking change).
- Federated computational governance: chuẩn chung (định danh, chất lượng tối thiểu, bảo mật, interoperability) nhúng vào nền tảng & CI như code (policy-as-code) — vừa tự chủ vừa tuân thủ, không gác cổng thủ công.
- SLA/SLO ở quy mô: mỗi domain cam kết, đo phân tán; giám sát tập trung qua dashboard SLO toàn mesh.
- Lineage & catalog liên domain: bắt buộc để khám phá và truy vết dữ liệu xuyên ranh giới domain; phải tự động sinh.
- Đánh đổi: tự chủ đổi lấy nguy cơ trùng lặp/không nhất quán — chuẩn chung (thực thi tự động) chính là thứ giải quyết mặt trái này.
- Khi nào mesh: tổ chức lớn, nhiều domain có đội đủ mạnh; tổ chức nhỏ nên giữ tập trung; nên áp dụng từng phần từ vài domain trưởng thành.
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.
Data Engineering là gì, vai trò trong vòng đời dữ liệu, và bức tranh hệ sinh thái công cụ.
Vì sao xử lý phân tán, mô hình Spark (RDD/DataFrame), lazy evaluation, shuffle và tối ưu.
Đả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.