Module 2 — Tổng kết & cheat sheet
Recap stream: log-based broker (Kafka offset), windowing (event-time, watermark), stream join, exactly-once. Cheat sheet, glossary, self-assessment trước Module 3.
TL;DR: Module 2 dựng stream từ một thay đổi gốc so với batch: input là dòng vô tận, job chạy mãi, phản hồi từng event. Log-based broker (Kafka) giữ log chỉ-append + offset là con trỏ consumer → nhiều consumer group đọc độc lập, replay được. Windowing cắt dòng vô tận thành cửa sổ; event-time (không phải processing-time) cho reprocess đúng; watermark quyết định "chờ bao lâu là đủ". Stream join cần window (stream-stream) hoặc KTable (stream-table); exactly-once = idempotent producer + transaction. Trang này để bookmark trước Module 3 — kiến trúc phái sinh.
Đã đi qua những gì
Bắt đầu bằng tư duy stream: input unbounded không có "điểm kết thúc" → phải xử lý từng event khi tới, duy trì state liên tục, và mọi kết quả là bản tạm thời. Mô hình nền là producer/consumer tách biệt qua topic. Log-based broker hiện thực hoá điều đó: Kafka thay queue (xoá sau đọc) bằng log chỉ-append; offset là con trỏ của mỗi consumer group nên nhiều team đọc cùng topic độc lập và replay được trong retention window — khác hẳn RabbitMQ/AMQP. Windowing giải bài toán "tổng hợp trên dòng vô tận": tumbling/hopping/sliding/session cắt dòng thành cửa sổ hữu hạn; điểm khoá là event-time vs processing-time (chỉ event-time cho reprocess ra cùng kết quả) và watermark (lower-bound trên event-time, trade-off latency vs completeness; event trễ xử lý bằng allowed lateness + side output). Stream join cần window khi ghép hai stream (tránh state vô hạn), không cần với KTable. Khép bằng exactly-once: idempotent producer (dedup tại broker) + transaction (atomic write + offset commit) — hai tầng, không phải một flag.

🗺️ Cheat sheet
| Khái niệm | Khi nào dùng / bản chất | Pitfall |
|---|---|---|
| Stream / unbounded | Input dòng vô tận, cần độ trễ thấp | Dùng batch cho real-time → trễ cả mẻ |
| Producer/consumer | Tách biệt qua topic, tốc độ độc lập | Consumer lag không giám sát |
| Log-based broker (Kafka) | Nhiều team đọc cùng luồng + replay | Tưởng "đọc xong là mất" như queue |
| Offset | Con trỏ consumer group (không phải trạng thái broker) | auto.offset.reset=latest bỏ dữ liệu cũ |
| Partition key | Quyết định partition + thứ tự | Sai key → mất thứ tự cùng entity |
| Tumbling window | Tổng hợp chu kỳ cố định | Bỏ lỡ span vắt qua ranh giới window |
| Sliding window | Phát hiện bất thường "bất kỳ khoảng nào" | State lớn hơn tumbling |
| Session window | Phân tích phiên theo khoảng im lặng | — |
| Event-time | Reprocess ra cùng kết quả | Dùng processing-time → reprocess sai |
| Watermark | "event ≤ t đã đến đủ" → đóng window | =0 bỏ event trễ; thiếu → window không đóng |
| Stream-stream join | Ghép hai stream, cần window | Không window → state vô hạn |
| Stream-table (KTable) join | Lookup giá trị mới nhất, non-windowed | — |
| Exactly-once | idempotent producer + transaction | Bật idempotence tưởng đủ EOS |
📖 Glossary module
| Thuật ngữ | Định nghĩa 1 câu | Nguồn |
|---|---|---|
| Event | Sự kiện bất biến có timestamp, append vào dòng | DDIA Ch11 |
| Topic / partition | Kênh sự kiện; partition = một file log tuần tự | Kafka Design |
| Offset | Số thứ tự cố định của message trong partition | Kafka Design |
| Consumer group | Nhóm consumer chia nhau partition của topic | Kafka Design |
| Retention | Thời gian Kafka giữ log (default 168h) | Kafka |
| Event-time / processing-time | Đồng hồ producer vs đồng hồ server | Dataflow Model 2015 |
| Watermark | Lower-bound trên event-time đã xử lý xong | Flink / Dataflow |
| Idempotent producer | Producer ID + sequence number → dedup broker (Kafka 0.11.0) | Kafka Design |
| Exactly-once (EOS) | Mỗi record ảnh hưởng kết quả đúng một lần | Kafka / Flink |
⚠️ Pitfall tổng hợp
- Batch cho real-time → trễ cả mẻ. Bài toán độ-trễ-thấp cần stream.
- Kafka như queue "đọc xong là mất" →
auto.offset.reset=latestbỏ dữ liệu cũ. Kafka giữ log; offset là con trỏ consumer group. - Processing-time thay event-time → reprocess lịch sử cho kết quả KHÁC production. Dùng event-time + watermark.
- Watermark sai → =0 bỏ event trễ; thiếu → window không đóng, state vô hạn. Chọn delay khớp SLA + allowed lateness + side output.
- at-least-once tưởng exactly-once → double-count. EOS = idempotent producer + transaction, hoặc consumer idempotent/dedup.
✅ Self-assessment
Bạn đã đạt module này nếu trả lời được:
- Giải thích được mô hình stream (event, producer/consumer) và vì sao input unbounded đổi cách xử lý so với batch.
- Nếu chưa: đọc lại bài 01 mục "Vì sao input vô tận đổi cách xử lý".
- So sánh được message broker truyền thống (xoá sau đọc) với log-based broker (Kafka giữ log + offset).
- Nếu chưa: đọc lại bài 02 bảng so sánh queue vs log.
- Thiết kế được windowing và stream join, lập luận xử lý event trễ bằng event-time và watermark.
- Giải thích được đảm bảo exactly-once qua idempotent + atomic commit, và fault tolerance của stream.
- Nếu chưa: đọc lại bài 04 mục exactly-once.
🚀 What's next
Module 3 — Kiến trúc phái sinh — ghép batch (Module 1) và stream (Module 2) thành một hệ dữ liệu thật: CDC biến changelog của database thành stream, event sourcing lưu chuỗi event bất biến, CQRS tách đường đọc khỏi đường ghi, và lambda/kappa kết hợp hai thế giới. Khép lại bằng capstone đồ án nối cả track.
📚 Tài liệu mở rộng
- Kafka: Apache Kafka Design; The Log — Jay Kreps (LinkedIn).
- Windowing/watermark: The Dataflow Model — Akidau et al. (VLDB 2015); Apache Flink — Timely Stream Processing.
- Exactly-once: End-to-End Exactly-Once in Flink (with Kafka).
- Sách: Designing Data-Intensive Applications (Kleppmann), Chương 11 — Stream Processing.
Bài tiếp theo: Module 3 — Kiến trúc phái sinh: tổng quan
Bài này có giúp bạn hiểu bản chất không?
Bài này đáng gửi cho bạn học cùng?
Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.
Lab — thiết kế một stream pipeline thật
Bài tiếp Kiến trúc phái sinh (CDC, event sourcing, CQRS)Module 3 — Kiến trúc phái sinh: tổng quan
Thảo luận & góp ý
Hỏi đáp về bài này