Module 3 — Tổng kết & bế mạc track
Recap kiến trúc phái sinh: CDC, event sourcing, CQRS, lambda/kappa. Cheat sheet, glossary, self-assessment — và khép lại track Hệ thống Dữ liệu Quy mô lớn.
TL;DR: Module 3 ghép batch và stream thành kiến trúc thật. CDC đọc transaction log của database (WAL/binlog) thành stream — thay dual-write bằng đọc-log để tránh bất nhất. Event sourcing lưu chuỗi sự kiện bất biến, dựng lại state bằng replay (+ snapshot khi log dài). CQRS tách write model khỏi read model, đổi eventual consistency lấy read model tối ưu. Lambda vs Kappa kết hợp batch + stream ở tầng kiến trúc: lambda hai codebase (chính xác + real-time), kappa một codebase stream + replay. Đây cũng là trang khép lại cả track Hệ thống Dữ liệu Quy mô lớn.
Đã đi qua những gì
Track có một sợi chỉ xuyên suốt: một nguồn-sự-thật bất biến, nhiều hệ phái sinh luôn tính lại được. CDC là cách lan dữ liệu từ system of record ra hệ phái sinh mà không dual-write — đọc chính transaction log DB đã ghi sẵn (bắt đủ INSERT/UPDATE/DELETE, lag 100–500ms so với polling ≥10s). Event sourcing đẩy ý tưởng bất biến vào chính state nghiệp vụ: lưu event (sự việc đã xảy ra), state là fold của event log — mất state thì replay lại; log dài thì snapshot. CQRS tách trách nhiệm ghi (command) khỏi đọc (query): read model là materialized view cập nhật bất đồng bộ, giá phải trả là eventual consistency (lag ~50ms bình thường, vài giây khi tải cao). Lambda/Kappa trả lời câu "cần cả chính xác của batch lẫn độ trễ của stream thì kết hợp thế nào": lambda ba tầng (batch + speed + serving) nhưng hai codebase dễ drift; kappa một codebase stream + Kafka long-retention để replay, đổi bằng chi phí storage.
flowchart TB SOR["System of record<br/>(DB, bat bien)"] -->|"CDC (bai 01)"| STREAM["Stream su kien"] SOR -->|"event log"| ES["Event sourcing (bai 02)<br/>replay + snapshot"] STREAM --> CQRS["CQRS (bai 03)<br/>read model / materialized view"] STREAM --> LK["Lambda/Kappa (bai 04)<br/>batch + stream"] ES --> CQRS CQRS --> DERIV["Derived views<br/>(index, cache, report)"] LK --> DERIV
🗺️ Cheat sheet
| Khái niệm | Khi nào dùng / bản chất | Pitfall |
|---|---|---|
| CDC | Đồng bộ DB → index/cache/warehouse không dual-write | Dual-write crash → bất nhất; schema change vỡ downstream |
| Log-based CDC (Debezium) | Lag thấp, bắt DELETE, không tăng tải source | — (mặc định nên chọn) |
| Outbox pattern | Ghi event + business data trong 1 transaction | Bỏ qua → dual-write |
| Event sourcing | Cần audit/lịch sử đầy đủ, state là fold event | applyEvent có side-effect → replay hỏng |
| Snapshot | Log dài (vượt ~1.000 event / replay >100ms) | Không snapshot → replay hàng phút |
| Event versioning | Đổi schema event → upcaster v1→v2 | Sửa event cũ trong store |
| CQRS | Read/write load thật khác nhau, quy mô lớn | Over-engineer; đọc read model ngay sau write → stale/404 |
| Eventual consistency | Read model trễ sau write model | Ép đồng bộ tức thời làm mất lợi ích |
| Lambda | Reprocess cần xa hơn retention; batch logic phức tạp | 2 codebase → logic drift |
| Kappa | Retention 30–90 ngày đủ; stream engine đủ mạnh | Storage cost (75 TB/90 ngày ở 50k evt/s) |
📖 Glossary module
| Thuật ngữ | Định nghĩa 1 câu | Nguồn |
|---|---|---|
| CDC | Đọc changelog (WAL/binlog) của DB thành stream thay đổi | Debezium |
| Dual-write | Ghi DB rồi ghi hệ khác riêng — crash giữa chừng gây bất nhất | — |
| Outbox pattern | Ghi event vào bảng outbox trong cùng transaction DB | Debezium |
| Event sourcing | Lưu chuỗi event bất biến, state = fold(event) | Fowler 2005 |
| Snapshot | Checkpoint state để không replay toàn bộ log | — |
| CQRS | Tách write model (command) khỏi read model (query) | Fowler 2011 |
| Materialized view | Kết quả tính sẵn của một truy vấn, lưu riêng | — |
| Lambda architecture | Batch layer + speed layer + serving layer | Marz 2011 |
| Kappa architecture | Chỉ stream + replay từ log long-retention | Kreps 2014 |
⚠️ Pitfall tổng hợp
- Dual-write → ghi DB thành công, ghi Kafka fail → bất nhất im lặng. Dùng CDC đọc-log hoặc outbox.
- CDC schema change → rename cột vỡ downstream. Schema registry + expand-contract.
- applyEvent side-effect → replay gửi lại email/gọi lại API. Giữ applyEvent thuần.
- CQRS read-after-write → đọc read model ngay sau write thấy stale/404. Chấp nhận eventual consistency hoặc đọc write model cho critical.
- Lambda logic drift → batch view và speed view lệch. Cân nhắc kappa hoặc engine hợp nhất.
✅ Self-assessment
Bạn đã đạt module này nếu trả lời được:
- Giải thích được change data capture (CDC) biến database changelog thành stream để đồng bộ hệ phái sinh.
- Nếu chưa: đọc lại bài 01 mục "CDC là gì" + pitfall dual-write.
- So sánh được event sourcing và CQRS với CRUD truyền thống, lập luận trade-off.
- So sánh được kiến trúc lambda và kappa khi kết hợp batch với stream, chọn theo yêu cầu.
- Nếu chưa: đọc lại bài 04 bảng lambda vs kappa + chi phí storage.
- Thiết kế được một hệ dữ liệu phái sinh đầu-cuối nối batch, stream và CDC.
- Nếu chưa: làm lại bài 05 (capstone).
🎓 Bế mạc track — Hệ thống Dữ liệu Quy mô lớn
Bạn vừa đi hết ba module: Batch (khối bất biến, throughput cao), Stream (dòng vô tận, độ trễ thấp), và Kiến trúc phái sinh (ghép hai thứ đó thành hệ thật). Một ý tưởng nối tất cả: input bất biến là nguồn-sự-thật; mọi thứ khác là phái sinh, luôn tính lại được — từ output batch, đến materialized view CQRS, đến state dựng-lại-bằng-replay của event sourcing. Đây chính là "unbundling database" mà DDIA Chương 12 gọi tên: log làm tầng tích hợp, derived data trôi ra từ đó.
Từ đây, những hướng đi sâu hơn: consensus & consistency (đã học ở track Tier 1 — di-phan-tan), data mesh / lakehouse, và streaming SQL (Flink SQL, ksqlDB, Materialize) như bước kế tiếp thực hành.
📚 Tài liệu mở rộng
- CDC: Debezium docs; How CDC Works — Confluent.
- Event sourcing / CQRS: Event Sourcing — Martin Fowler; CQRS — Martin Fowler.
- Lambda / Kappa: How to beat the CAP theorem — Nathan Marz; Questioning the Lambda Architecture — Jay Kreps.
- Sách: Designing Data-Intensive Applications (Kleppmann), Chương 12 — The Future of Data Systems.
Bài này có giúp bạn hiểu bản chất không?
Hỏi đáp về bài này
Chưa có câu hỏi
Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).
Đặt câu hỏi đầu tiên