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.
flowchart TD UNB["Input unbounded<br/>(dong su kien)"] --> LOG["Log-based broker<br/>Kafka offset"] LOG --> WIN["Windowing<br/>event-time + watermark"] WIN --> JOIN["Stream join<br/>+ exactly-once"] JOIN --> OUT["Ket qua real-time<br/>tinh dung du tre/loi"]
🗺️ 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?
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