Kafka, 10 use caseKafka, 10 use cases

Kafka không phải hàng đợi. Nó là một cuốn log chỉ ghi thêm, và mỗi bên đọc tự giữ dấu trang của mình.Kafka isn't a queue. It's an append-only log, and every reader keeps its own bookmark.

Cả mười use case bên dưới đều là hệ quả của một thiết kế duy nhất đó: message không mất khi đọc, thứ tự được giữ trong partition, và nhiều người đọc ở những vị trí khác nhau.All ten use cases below follow from that one design: messages survive being read, order holds within a partition, and many readers sit at different positions.

partition 0append ▸100101102103104105106107108109110111112113114billingsearch idxreplay

Record mới luôn được ghi vào cuối. Mỗi consumer group đọc ở vị trí riêng và tự tiến theo nhịp riêng; nhóm “replay” đang đọc lại dữ liệu cũ mà không ảnh hưởng ai.New records are always appended at the end. Each consumer group reads from its own position at its own pace; the “replay” group is re-reading old data without affecting anyone.

Khi nào không cần KafkaWhen you don't need Kafka

Phần lớn hệ thống không cần Kafka. Một cụm production đúng nghĩa cần tối thiểu 3 broker, giám sát lag, quản lý schema và một người hiểu rebalance. Bản managed (MSK, Confluent Cloud, Aiven) bớt phần vận hành, không bớt phần thiết kế.Most systems don't need Kafka. A real production cluster means at least 3 brokers, lag monitoring, schema management, and someone who understands rebalancing. Managed offerings (MSK, Confluent Cloud, Aiven) remove ops work, not design work.

Quy tắc thực dụng: chỉ cân nhắc Kafka khi có ít nhất hai trong bốn nhu cầu — nhiều consumer độc lập, cần phát lại, thông lượng lớn và liên tục, cần thứ tự theo key.Rule of thumb: consider Kafka only when you have at least two of four needs — several independent consumers, replay, sustained high throughput, ordering by key.

Nhu cầuNeedPhương án rẻ hơnCheaper option
Giao việc cho workerHand jobs to workersBảng Postgres + SELECT … FOR UPDATE SKIP LOCKED; hoặc SQS, RabbitMQPostgres table + SELECT … FOR UPDATE SKIP LOCKED; or SQS, RabbitMQ
Vài subscriber cho một eventA few subscribers per eventSNS → SQS, EventBridge, Google Pub/Sub; Redis Streams nếu đã có RedisSNS → SQS, EventBridge, Google Pub/Sub; Redis Streams if you already run Redis
Analytics hành viBehaviour analyticsGửi thẳng vào công cụ analytics hoặc warehouseSend straight to an analytics tool or the warehouse
Gom logLog aggregationFluent Bit / Vector có buffer trên đĩa → Loki hoặc OpenSearchFluent Bit / Vector with disk buffer → Loki or OpenSearch
Metrics & cảnh báoMetrics & alertingPrometheus + AlertmanagerPrometheus + Alertmanager
Đẩy thay đổi DB ra ngoàiPublish DB changesBảng outbox + một worker pollingOutbox table + a polling worker
Nạp warehouseLoad the warehouseELT theo lịch (dbt, Airbyte, cron)Scheduled ELT (dbt, Airbyte, cron)
Cần lịch sử để chạy lạiHistory for rerunsLưu raw event vào S3 theo ngàyStore raw events in S3, partitioned by day

Chọn cái nào trong 30 giâyPick one in 30 seconds

Bạn đang cố làm gì?
│
├─ Chưa có ≥2 trong 4 nhu cầu (nhiều consumer, replay, thông lượng lớn, thứ tự)?
│     └─▶ KHÔNG dùng Kafka. Xem bảng baseline.
│
├─ Giao việc cho worker, mỗi việc làm đúng một lần?
│     ├─ cần delay / priority / ack từng việc ─▶ RabbitMQ, SQS
│     └─ khối lượng rất lớn, chấp nhận trần partition ─▶ A1
│
├─ Một event, nhiều team cùng cần? ──────────────────▶ A2
│
├─ Hút dữ liệu khối lượng lớn từ nhiều nguồn?
│     ├─ hành vi người dùng ────────────────────────▶ B1
│     ├─ log, khi backend không chịu nổi peak ──────▶ B2
│     └─ số đo, khi không pull được ───────────────▶ B3
│
├─ Dữ liệu nằm trong DB, cần chảy ra ngoài? ────────▶ C2 (+ outbox)
├─ Biến đổi / join liên tục, cần kết quả trong giây? ▶ C1
├─ Đổ vào warehouse / lake, tươi theo phút? ────────▶ C3
├─ Lịch sử thay đổi là yêu cầu nghiệp vụ? ───────────▶ D1 (event store + Kafka làm bus)
└─ Cần chạy lại sau sự cố? ─────────────────────────▶ D2: đi kèm mọi lựa chọn trên,
                                                     chỉ cần đặt retention đúng
What are you trying to do?
│
├─ Fewer than 2 of the 4 needs (many consumers, replay, throughput, ordering)?
│     └─▶ DON'T use Kafka. See the baseline table.
│
├─ Hand work to workers, each job done once?
│     ├─ need delay / priority / per-job ack ─▶ RabbitMQ, SQS
│     └─ huge volume, partition cap acceptable ─▶ A1
│
├─ One event, several teams need it? ───────────────▶ A2
│
├─ Absorb high-volume data from many sources?
│     ├─ user behaviour ───────────────────────────▶ B1
│     ├─ logs, when the backend can't take peak ───▶ B2
│     └─ measurements, when scraping isn't viable ─▶ B3
│
├─ Data lives in a DB and must flow out? ───────────▶ C2 (+ outbox)
├─ Continuous transform / join, results in seconds? ▶ C1
├─ Load a warehouse / lake, fresh within minutes? ──▶ C3
├─ Change history is a business requirement? ───────▶ D1 (event store + Kafka as bus)
└─ Need to rerun after an incident? ────────────────▶ D2: comes with all of the above,
                                                     just set retention right

10 use caseThe 10 use cases

A1

Nhắn tin bất đồng bộAsync messaging

Truyền tinMessaging
producerconsumer

Producer ghi xong là đi, consumer đọc khi sẵn sàng.The producer writes and moves on; the consumer reads when ready.

Chọn Kafka cho async messaging là đổi sự tiện của hàng đợi truyền thống (ack từng message, delay, priority) lấy khả năng giữ lại, đọc lại message và thông lượng rất cao.Choosing Kafka for async messaging trades the conveniences of a classic queue (per-message ack, delay, priority) for retained, re-readable messages at very high throughput.

Dùng choUse for
Gửi email, SMS xác nhận sau khi đặt hàng.Sending confirmation email or SMS after checkout.
ĐượcGain
Hấp thụ đột biến tải: consumer chậm thì lag tăng, hệ thống không sập.Absorbs load spikes: a slow consumer just builds lag instead of falling over.
MấtLose
Không ack từng message. Offset là một vị trí, nên một message lỗi sẽ chặn cả partition nếu không có retry topic.No per-message ack. An offset is a position, so one poison message blocks its whole partition unless you add retry topics.

Dấu hiệu nhận biếtTelltale sign Request có thể trả về ngay, phần việc còn lại làm sau vài giây cũng không ai phàn nàn.The request can return immediately and nobody minds if the rest happens a few seconds later.

Hiệu đính so với ảnhCorrection to the image Ảnh viết “producer never waits for the consumer”. Đúng về mặt tách rời, nhưng producer vẫn chờ broker xác nhận — và nên chờ, nếu bạn không muốn mất dữ liệu.The image says the producer never waits for the consumer. True for decoupling, but the producer still waits for the broker's ack — and should, unless you're fine losing data.
Chi tiết: cách hoạt động, lợi ích, hạn chế, mẹoDetails: how it works, benefits, limits, tips

Nó là gìWhat it is

Service A ghi message vào một topic rồi tiếp tục việc của mình; service B đọc message đó khi nó rảnh. Hai bên không cần cùng sống một lúc, cũng không cần biết địa chỉ của nhau.Service A writes a message to a topic and carries on; service B reads it when it has capacity. The two never need to be up at the same time or know each other's address.

producer ──append──▶ [ topic: orders ] ◀──poll── consumer
                      0  1  2  3  4  5
                               ▲
                        committed offset

Hoạt động thế nàoHow it works

Producer gửi record tới broker đang làm leader của partition. Với acks=all, broker chỉ xác nhận khi mọi replica trong ISR đã ghi xong — tức là producer không chờ consumer, nhưng vẫn chờ broker. Consumer chủ động poll, xử lý, rồi commit offset. Đọc xong message vẫn còn đó cho tới khi hết retention.The producer sends the record to the broker leading that partition. With acks=all, the broker acknowledges only once every in-sync replica has it — so the producer never waits for the consumer, but it does wait for the broker. The consumer polls, processes, then commits its offset. Reading does not delete anything; the message stays until retention expires.

Phù hợp cho việc gìWhat it's good for

  • Gửi email, SMS xác nhận sau khi đặt hàng.Sending confirmation email or SMS after checkout.
  • Xử lý ảnh, video người dùng vừa upload.Processing images or video right after upload.
  • Tách luồng checkout khỏi hệ thống kho để kho chậm không kéo checkout chậm theo.Decoupling checkout from inventory so a slow inventory system doesn't slow checkout.

Lợi íchBenefits

  • Hấp thụ đột biến tải: consumer chậm thì lag tăng, hệ thống không sập.Absorbs load spikes: a slow consumer just builds lag instead of falling over.
  • Consumer chết thì message vẫn còn, mặc định giữ 7 ngày (log.retention.hours=168).If the consumer dies, messages wait — 7 days by default (log.retention.hours=168).
  • Mở rộng consumer theo chiều ngang, tới đúng bằng số partition.Consumers scale horizontally, up to the partition count.

Hạn chếLimitations

  • Không ack từng message. Offset là một vị trí, nên một message lỗi sẽ chặn cả partition nếu không có retry topic.No per-message ack. An offset is a position, so one poison message blocks its whole partition unless you add retry topics.
  • Với consumer group cổ điển, độ song song tối đa bằng số partition; thêm instance thứ 13 cho topic 12 partition chỉ để nó ngồi chơi.With classic consumer groups, parallelism caps at the partition count; a 13th instance on a 12-partition topic just idles.
  • Không có delay, priority hay TTL cho từng message như RabbitMQ hay SQS.No per-message delay, priority or TTL like RabbitMQ or SQS.

Mẹo triển khaiImplementation tips

  • Tách lỗi tạm thời khỏi lỗi vĩnh viễn: retry topic có backoff cho cái trước, DLQ cho cái sau.Separate transient from permanent failures: retry topics with backoff for the first, a DLQ for the second.
  • Đặt max.poll.interval.ms lớn hơn thời gian xử lý tệ nhất của một batch, nếu không consumer bị đá khỏi group và rebalance liên tục.Set max.poll.interval.ms above your worst-case batch time, or the consumer gets kicked from the group and rebalances in a loop.
  • Nếu thật sự cần ngữ nghĩa hàng đợi, xem Share Groups (KIP-932) ở Kafka 4.x trước khi tự chế. Kiểm tra trạng thái của nó trên đúng phiên bản bạn chạy.If you genuinely need queue semantics, look at Share Groups (KIP-932) in Kafka 4.x before building your own. Check its status for the exact version you run.
A2

Pub-sub fan-outPub-sub fan-out

Truyền tinMessaging
orderbillingemailanalytics

Một event, mỗi bên quan tâm tự đọc theo nhịp riêng.One event; every interested party reads it at its own pace.

Chọn fan-out qua Kafka là đổi quyền kiểm soát ai phụ thuộc vào ai lấy khả năng thêm consumer mà không chạm vào producer.Choosing fan-out through Kafka trades control over who depends on whom for adding consumers without touching the producer.

Dùng choUse for
OrderPlaced → billing, email, analytics, chống gian lận.OrderPlaced → billing, email, analytics, fraud.
ĐượcGain
Producer không phụ thuộc vào số lượng subscriber.The producer doesn't depend on how many subscribers exist.
MấtLose
Schema event trở thành API công khai: đổi một field là ảnh hưởng mọi team đang đọc.The event schema becomes a public API: changing one field hits every team reading it.

Dấu hiệu nhận biếtTelltale sign Mỗi lần thêm tính năng, bạn lại phải sửa service gốc để gọi thêm một API nữa.Every new feature means editing the origin service to call one more API.

Chi tiết: cách hoạt động, lợi ích, hạn chế, mẹoDetails: how it works, benefits, limits, tips

Nó là gìWhat it is

Một event có nhiều bên cần biết. Trong Kafka, mỗi subscriber là một consumer group riêng với offset riêng, nên mỗi group nhận mỗi message đúng một lần.One event, many parties who care. In Kafka each subscriber is its own consumer group with its own offset, so every group gets each message once.

                 ┌─▶ group: billing    (offset 812)
order ─▶ [topic] ┼─▶ group: email      (offset 640)
                 └─▶ group: analytics  (offset 120)

Hoạt động thế nàoHow it works

Topic không biết ai đang đọc nó. Thêm subscriber nghĩa là tạo consumer group mới, producer không đổi một dòng code nào. Bên trong mỗi group, Kafka chia partition cho các instance của group đó.The topic has no idea who reads it. Adding a subscriber means starting a new consumer group; the producer doesn't change. Inside each group, partitions are divided among that group's instances.

Phù hợp cho việc gìWhat it's good for

  • OrderPlaced → billing, email, analytics, chống gian lận.OrderPlaced → billing, email, analytics, fraud.
  • Giá thay đổi → cache, search index, push cho app mobile.Price changed → cache, search index, mobile push.
  • User đăng ký → CRM, onboarding, gợi ý sản phẩm.User signed up → CRM, onboarding, recommendations.

Lợi íchBenefits

  • Producer không phụ thuộc vào số lượng subscriber.The producer doesn't depend on how many subscribers exist.
  • Subscriber chậm không kéo subscriber khác chậm theo.A slow subscriber doesn't slow down the others.
  • Subscriber mới có thể đọc từ đầu (trong phạm vi retention) để nạp bù dữ liệu cũ (backfill).A new subscriber can read from the beginning (within retention) to backfill.

Hạn chếLimitations

  • Schema event trở thành API công khai: đổi một field là ảnh hưởng mọi team đang đọc.The event schema becomes a public API: changing one field hits every team reading it.
  • Khó trả lời câu “ai đang phụ thuộc vào event này?” nếu không có catalog.Hard to answer “who depends on this event?” without a catalog.
  • Broker không lọc giúp: mỗi group nhận toàn bộ topic rồi tự bỏ cái không cần.No broker-side filtering: each group receives the whole topic and discards what it doesn't need.

Mẹo triển khaiImplementation tips

  • Đặt tên event theo sự thật đã xảy ra (OrderPlaced), không theo mệnh lệnh (SendEmail).Name events as facts that happened (OrderPlaced), not commands (SendEmail).
  • Bật compatibility BACKWARD trên Schema Registry ngay từ ngày đầu, đừng đợi tới lần vỡ đầu tiên.Turn on BACKWARD compatibility in Schema Registry on day one, not after the first breakage.
  • Đặt group.id theo tên service. Hai service dùng chung group.id sẽ âm thầm chia nhau message.Name group.id after the service. Two services sharing a group.id silently split the messages between them.
B1

Theo dõi hành vi người dùngActivity tracking

Thu gomIngestion
clicksdashboardwarehouse

Mọi click, view, search thành một dòng event liên tục.Every click, view and search becomes a continuous event stream.

Chọn Kafka cho activity tracking là đổi chi phí vận hành một cụm luôn chạy lấy một dòng hành vi dùng chung cho cả realtime và batch.Choosing Kafka for activity tracking trades the cost of an always-on cluster for one behaviour stream shared by realtime and batch.

Dùng choUse for
Dashboard realtime: bao nhiêu người đang ở trang thanh toán.Realtime dashboard: how many people are on the checkout page right now.
ĐượcGain
Thông lượng cao nhờ batch và nén; một cụm nhỏ xử lý hàng trăm nghìn event mỗi giây.High throughput from batching and compression; a small cluster handles hundreds of thousands of events per second.
MấtLose
Dữ liệu cá nhân kéo theo nghĩa vụ xoá (GDPR); log bất biến rất khó xoá một người nếu không thiết kế từ đầu.Personal data brings deletion duties (GDPR); an immutable log makes deleting one person hard unless designed in.

Dấu hiệu nhận biếtTelltale sign Hàng nghìn event nhỏ mỗi giây, mất vài cái không sao, nhưng xu hướng phải thấy được trong vài giây.Thousands of small events per second, losing a few is fine, but trends must show up within seconds.

Chi tiết: cách hoạt động, lợi ích, hạn chế, mẹoDetails: how it works, benefits, limits, tips

Nó là gìWhat it is

Ghi lại hành vi người dùng thành dòng event để phân tích. Đây chính là bài toán LinkedIn tạo ra Kafka để giải quyết, khoảng 2010–2011.Recording user behaviour as an event stream for analysis. This is the problem LinkedIn built Kafka to solve, around 2010–2011.

web / app ─▶ collector ─▶ [page-views : 12 partitions] ─┬─▶ realtime dashboard
                                                         └─▶ warehouse (hourly)

Hoạt động thế nàoHow it works

SDK phía client gửi event về collector qua HTTP. Collector kiểm tra, gắn timestamp phía server, rồi ghi vào Kafka theo batch với key là user_id hoặc session_id để giữ thứ tự cho từng người. Các hệ thống downstream đọc cùng dòng đó với độ trễ khác nhau.A client SDK posts events to a collector over HTTP. The collector validates them, stamps server time, and batches them into Kafka keyed by user_id or session_id so each person's events stay ordered. Downstream systems read the same stream at different latencies.

Phù hợp cho việc gìWhat it's good for

  • Dashboard realtime: bao nhiêu người đang ở trang thanh toán.Realtime dashboard: how many people are on the checkout page right now.
  • Gợi ý sản phẩm dựa trên vài click gần nhất.Recommendations based on the last few clicks.
  • A/B test cần số liệu theo giờ chứ không theo ngày.A/B tests that need hourly, not daily, numbers.

Lợi íchBenefits

  • Thông lượng cao nhờ batch và nén; một cụm nhỏ xử lý hàng trăm nghìn event mỗi giây.High throughput from batching and compression; a small cluster handles hundreds of thousands of events per second.
  • Một dòng dữ liệu phục vụ cả realtime lẫn batch.One stream serves both realtime and batch consumers.
  • Thứ tự theo từng người dùng được giữ nhờ key.Per-user ordering is preserved through the key.

Hạn chếLimitations

  • Dữ liệu cá nhân kéo theo nghĩa vụ xoá (GDPR); log bất biến rất khó xoá một người nếu không thiết kế từ đầu.Personal data brings deletion duties (GDPR); an immutable log makes deleting one person hard unless designed in.
  • Event trùng hoặc thiếu từ client là chuyện thường; Kafka không sửa được.Duplicate or missing client events are normal; Kafka can't fix them.
  • Hot key (bot, tài khoản test) dồn dữ liệu vào một partition.Hot keys (bots, test accounts) pile data onto one partition.

Mẹo triển khaiImplementation tips

  • Không cho client ghi thẳng vào Kafka; luôn đi qua collector để lọc, giới hạn tốc độ và gắn thời gian server.Never let clients write to Kafka directly; go through a collector for filtering, rate limiting and server time.
  • Bật compression.type=zstd hoặc lz4 và tăng linger.ms, batch.size. Event nhỏ dạng JSON nén rất tốt.Enable compression.type=zstd or lz4 and raise linger.ms and batch.size. Small JSON events compress extremely well.
  • Sinh event_id ngay ở client để downstream loại trùng (dedup) được.Generate an event_id on the client so downstream can dedupe.
B2

Gom log tập trungLog aggregation

Thu gomIngestion
svc A/B/Csearcharchive

Log của mọi service đi qua một bộ đệm trước khi tới nơi tìm kiếm.Every service's logs pass through one buffer before reaching search.

Chọn Kafka làm tầng đệm log là đổi thêm một hệ thống phải vận hành lấy việc không mất log khi backend tìm kiếm quá tải.Choosing Kafka as a log buffer trades running one more system for not losing logs when the search backend is overloaded.

Dùng choUse for
Hàng trăm service cần một chỗ tìm log chung.Hundreds of services that need one place to search logs.
ĐượcGain
Tách tốc độ sinh log khỏi tốc độ đánh index.Decouples log production rate from indexing rate.
MấtLose
Thêm một hệ thống phải vận hành chỉ để chuyển log; nhiều nơi không cần.One more system to run just to move logs; many teams don't need it.

Dấu hiệu nhận biếtTelltale sign Cứ có sự cố là hệ thống log sập theo.Every incident takes the logging system down with it.

Chi tiết: cách hoạt động, lợi ích, hạn chế, mẹoDetails: how it works, benefits, limits, tips

Nó là gìWhat it is

Gom log của tất cả service về một dòng chung, rồi phân phối tới hệ thống tìm kiếm và kho lưu trữ dài hạn. Kafka ở đây là bộ đệm, không phải nơi tìm log.Collecting every service's logs into one stream, then fanning them out to search and long-term storage. Kafka is the buffer here, not where you search.

svc A ┐
svc B ┼─▶ agent ─▶ [logs] ─┬─▶ OpenSearch / Loki   (7–30 days)
svc C ┘                    └─▶ object storage (S3)  (years)

Hoạt động thế nàoHow it works

Agent trên mỗi node (Fluent Bit, Vector, Filebeat) đọc stdout hoặc file log rồi ghi vào Kafka. Khi cụm tìm kiếm chậm hay sập, log dồn lại trong Kafka thay vì bị agent vứt đi.An agent on each node (Fluent Bit, Vector, Filebeat) tails stdout or log files and writes to Kafka. When the search cluster slows down or dies, logs pile up in Kafka instead of being dropped by the agent.

Phù hợp cho việc gìWhat it's good for

  • Hàng trăm service cần một chỗ tìm log chung.Hundreds of services that need one place to search logs.
  • Cụm Elasticsearch hay quá tải đúng lúc có sự cố — lúc cần log nhất.An Elasticsearch cluster that overloads during incidents — exactly when you need logs most.
  • Cùng một log phải tới cả hệ thống tìm kiếm, SIEM và kho audit.The same logs must reach search, a SIEM and an audit archive.

Lợi íchBenefits

  • Tách tốc độ sinh log khỏi tốc độ đánh index.Decouples log production rate from indexing rate.
  • Thêm đích mới (SIEM, kho lạnh) không cần đụng tới agent.Adding a destination (SIEM, cold storage) doesn't touch the agents.
  • Retention của Kafka là lưới an toàn khi backend chết vài giờ.Kafka retention is the safety net when the backend is down for hours.

Hạn chếLimitations

  • Thêm một hệ thống phải vận hành chỉ để chuyển log; nhiều nơi không cần.One more system to run just to move logs; many teams don't need it.
  • Log thường là dữ liệu lớn nhất bạn có; đĩa và network nhân lên theo replication factor.Logs are usually your largest data volume; disk and network multiply by the replication factor.
  • Kafka không tìm kiếm được, bạn vẫn cần backend.Kafka can't search; you still need the backend.

Mẹo triển khaiImplementation tips

  • Đo trước: nếu agent ghi thẳng vào Loki hoặc OpenSearch vẫn chịu được peak, bạn chưa cần Kafka. Agent hiện đại có buffer trên đĩa.Measure first: if agents writing straight to Loki or OpenSearch survive peak, you don't need Kafka yet. Modern agents have on-disk buffers.
  • Tách topic: log audit (retention dài, acks=all) khác log debug (retention ngắn, acks=1).Split topics: audit logs (long retention, acks=all) versus debug logs (short retention, acks=1).
  • Để key null cho log để dữ liệu rải đều các partition.Leave the key null for logs so data spreads evenly across partitions.
B3

Metrics & cảnh báoMetrics & alerting

Thu gomIngestion
metricsTSDBalert job

Kafka chở số đo; việc tính và báo động nằm ở downstream.Kafka carries measurements; computing and alerting happen downstream.

Chọn Kafka cho metrics là đổi sự đơn giản của mô hình pull lấy khả năng gom fan-in khổng lồ và tái sử dụng dữ liệu.Choosing Kafka for metrics trades the simplicity of the pull model for huge fan-in and reusable data.

Dùng choUse for
Hàng triệu thiết bị IoT đẩy telemetry.Millions of IoT devices pushing telemetry.
ĐượcGain
Chịu được fan-in rất lớn, kiểu IoT.Handles very large fan-in, IoT-style.
MấtLose
Với metrics hạ tầng thông thường, Prometheus pull + Alertmanager đơn giản hơn nhiều.For ordinary infrastructure metrics, Prometheus scrape plus Alertmanager is far simpler.

Dấu hiệu nhận biếtTelltale sign Nguồn số đo quá nhiều hoặc quá rải rác để một Prometheus đi pull được.There are too many or too scattered metric sources for a Prometheus to scrape.

Hiệu đính so với ảnhCorrection to the image Ảnh vẽ Kafka như thể nó tự bắn cảnh báo. Thực tế Kafka không đánh giá rule nào cả; hệ thống đứng sau mới là nơi tính “p99 high”.The image draws Kafka as if it fires alerts itself. Kafka evaluates no rules; “p99 high” is computed by whatever sits behind it.
Chi tiết: cách hoạt động, lợi ích, hạn chế, mẹoDetails: how it works, benefits, limits, tips

Nó là gìWhat it is

Đẩy số đo (độ trễ, tỷ lệ lỗi, nhiệt độ cảm biến) qua Kafka tới kho chuỗi thời gian và bộ đánh giá cảnh báo.Shipping measurements (latency, error rate, sensor temperature) through Kafka to a time-series store and an alert evaluator.

hosts / IoT ─▶ [metrics] ─┬─▶ TSDB ─▶ dashboard
                          └─▶ stream job: p99 > 500ms for 5m ─▶ [alerts] ─▶ on-call

Hoạt động thế nàoHow it works

Kafka chỉ vận chuyển. Việc tính cảnh báo nằm ở downstream: hoặc TSDB (VictoriaMetrics, M3, Mimir) chạy rule, hoặc một stream job tính percentile theo cửa sổ thời gian rồi ghi sự kiện cảnh báo ra topic riêng.Kafka only transports. Alerts are computed downstream: either a TSDB (VictoriaMetrics, M3, Mimir) evaluates rules, or a stream job computes windowed percentiles and writes alert events to their own topic.

Phù hợp cho việc gìWhat it's good for

  • Hàng triệu thiết bị IoT đẩy telemetry.Millions of IoT devices pushing telemetry.
  • Nhiều cụm, nhiều region cần gom metrics về một chỗ.Many clusters and regions funnelling metrics into one place.
  • Cảnh báo kết hợp metrics với event nghiệp vụ (lỗi thanh toán tăng sau một lần triển khai).Alerts combining metrics with business events (payment failures rising after a deploy).

Lợi íchBenefits

  • Chịu được fan-in rất lớn, kiểu IoT.Handles very large fan-in, IoT-style.
  • Một dòng dữ liệu nuôi cả dashboard, cảnh báo và phân tích dài hạn.One stream feeds dashboards, alerts and long-term analysis.
  • TSDB chết thì metrics đợi trong Kafka, không mất.If the TSDB dies, metrics wait in Kafka rather than disappearing.

Hạn chếLimitations

  • Với metrics hạ tầng thông thường, Prometheus pull + Alertmanager đơn giản hơn nhiều.For ordinary infrastructure metrics, Prometheus scrape plus Alertmanager is far simpler.
  • Kafka nằm trên đường cảnh báo: Kafka sập thì ai báo bạn biết?Kafka sits on the alerting path: if Kafka goes down, who tells you?
  • Percentile không cộng gộp được; gửi p99 đã tính sẵn từ từng host rồi lấy trung bình là sai.Percentiles don't aggregate; averaging per-host precomputed p99s is wrong.

Mẹo triển khaiImplementation tips

  • Giám sát chính Kafka bằng một đường độc lập, không đi qua Kafka.Monitor Kafka itself through an independent path that doesn't go through Kafka.
  • Gửi histogram hoặc sketch (HDR, t-digest), không gửi p99 đã tính.Ship histograms or sketches (HDR, t-digest), not precomputed p99s.
  • Dùng key = tên metric + host để mỗi chuỗi giữ đúng thứ tự.Key by metric name + host so each series stays ordered.
C1

Xử lý luồngStream processing

Xử lý & tích hợpProcessing & integration
rawcustomersenriched

Lọc, làm giàu, gộp event ngay khi nó chảy qua.Filter, enrich and aggregate events as they flow past.

Chọn stream processing là đổi sự đơn giản và dễ gỡ lỗi của batch lấy kết quả có trong vài giây.Choosing stream processing trades the simplicity and debuggability of batch for results within seconds.

Dùng choUse for
Gắn thông tin khách hàng vào mỗi đơn hàng.Attaching customer data to every order.
ĐượcGain
Độ trễ tính bằng giây thay vì giờ.Latency in seconds instead of hours.
MấtLose
Thời gian là phần khó nhất: event đến muộn, đến sai thứ tự, watermark, grace period.Time is the hard part: late events, out-of-order events, watermarks, grace periods.

Dấu hiệu nhận biếtTelltale sign Bạn đang chạy job batch 5 phút một lần chỉ để có số liệu “gần như realtime”.You're running a batch job every 5 minutes just to get “near realtime” numbers.

Chi tiết: cách hoạt động, lợi ích, hạn chế, mẹoDetails: how it works, benefits, limits, tips

Nó là gìWhat it is

Biến đổi event trong lúc nó đang chảy: lọc, làm giàu bằng cách join với dữ liệu khác, gộp theo cửa sổ thời gian, rồi ghi kết quả ra topic mới.Transforming events while they flow: filtering, enriching by joining other data, aggregating over time windows, then writing results to a new topic.

[raw-orders] ──┐
               ├─▶ join(customer_id) ─▶ [orders-enriched]
[customers]  ──┘   (KTable from a compacted topic)

Hoạt động thế nàoHow it works

Kafka chỉ chứa và chuyển; xử lý do engine khác làm: Kafka Streams (thư viện Java chạy ngay trong app), Apache Flink, hoặc ksqlDB. State như bảng join hay bộ đếm được lưu cục bộ và sao lưu vào một changelog topic để khôi phục khi crash.Kafka stores and moves; the processing is done by an engine: Kafka Streams (a Java library inside your app), Apache Flink, or ksqlDB. State such as join tables or counters lives locally and is backed up to a changelog topic for crash recovery.

Phù hợp cho việc gìWhat it's good for

  • Gắn thông tin khách hàng vào mỗi đơn hàng.Attaching customer data to every order.
  • Phát hiện gian lận: quá 5 giao dịch trong 2 phút từ một thẻ.Fraud detection: more than 5 transactions from one card in 2 minutes.
  • Tồn kho realtime cộng trừ theo từng event.Realtime inventory updated by every event.

Lợi íchBenefits

  • Độ trễ tính bằng giây thay vì giờ.Latency in seconds instead of hours.
  • Exactly-once trong phạm vi Kafka (đọc–xử lý–ghi bằng transaction, processing.guarantee=exactly_once_v2).Exactly-once within Kafka (read–process–write in a transaction, processing.guarantee=exactly_once_v2).
  • App Kafka Streams mở rộng như một service bình thường, không cần cụm riêng.A Kafka Streams app scales like a normal service, no separate cluster.

Hạn chếLimitations

  • Thời gian là phần khó nhất: event đến muộn, đến sai thứ tự, watermark, grace period.Time is the hard part: late events, out-of-order events, watermarks, grace periods.
  • State lớn thì khôi phục sau crash chậm.Large state means slow recovery after a crash.
  • Join hai stream yêu cầu co-partitioning (cùng số partition, cùng key); sai thì kết quả âm thầm sai.Joining two streams requires co-partitioning (same partition count, same key); get it wrong and results are silently wrong.

Mẹo triển khaiImplementation tips

  • Hỏi trước: trễ 15 phút có ai mất tiền không? Nếu không, dùng batch.Ask first: does a 15-minute delay cost anyone money? If not, use batch.
  • Với Kafka Streams, đặt num.standby.replicas=1 để failover không phải dựng lại state từ đầu.In Kafka Streams, set num.standby.replicas=1 so failover doesn't rebuild state from scratch.
  • Luôn ghi rõ dùng event time hay processing time, và grace period cho từng window.Always state whether you use event time or processing time, and the grace period of each window.
C2

Change Data CaptureChange Data Capture

Xử lý & tích hợpProcessing & integration
pg WALsearch idxcachewarehouse

Mọi thay đổi trong database thành event, không sửa code ứng dụng.Every database change becomes an event, without touching application code.

Chọn CDC là đổi việc lộ cấu trúc bảng nội bộ ra ngoài lấy sự nhất quán tuyệt đối giữa DB và event mà không phải sửa code.Choosing CDC trades exposing internal table structure for guaranteed consistency between the DB and the events, with no code changes.

Dùng choUse for
Đồng bộ Postgres sang Elasticsearch.Syncing Postgres into Elasticsearch.
ĐượcGain
Không có dual-write: DB là nguồn duy nhất, event luôn khớp với dữ liệu đã commit.No dual write: the DB is the single source, so events always match committed data.
MấtLose
Event mang cấu trúc bảng nội bộ, nên schema DB thành hợp đồng công khai; đổi tên cột là vỡ consumer.Events carry internal table structure, so the DB schema becomes a public contract; renaming a column breaks consumers.

Dấu hiệu nhận biếtTelltale sign Code đang “ghi DB xong rồi ghi thêm Kafka”, và thỉnh thoảng bước thứ hai thất bại.Your code does “write the DB, then write Kafka”, and sometimes the second step fails.

Chi tiết: cách hoạt động, lợi ích, hạn chế, mẹoDetails: how it works, benefits, limits, tips

Nó là gìWhat it is

Bắt từng INSERT, UPDATE, DELETE từ database và phát chúng thành event cho các hệ thống khác.Capturing every INSERT, UPDATE and DELETE from a database and publishing them as events for other systems.

Postgres WAL ─▶ Debezium (Kafka Connect) ─▶ [db.public.orders] ─┬─▶ search index
                                                                ├─▶ cache invalidation
                                                                └─▶ warehouse

Hoạt động thế nàoHow it works

Connector đọc transaction log của database — WAL của Postgres qua logical replication, binlog của MySQL — chứ không dùng trigger hay polling. Mỗi thay đổi thành một event mang trạng thái before và after. DELETE sinh một event xoá, theo sau là một tombstone (value = null) để log compaction dọn key đó.The connector reads the database's transaction log — Postgres WAL via logical replication, MySQL binlog — not triggers or polling. Each change becomes an event carrying before and after state. A DELETE produces a delete event followed by a tombstone (null value) so log compaction can drop that key.

Phù hợp cho việc gìWhat it's good for

  • Đồng bộ Postgres sang Elasticsearch.Syncing Postgres into Elasticsearch.
  • Xoá cache đúng lúc dữ liệu đổi.Invalidating caches exactly when data changes.
  • Tách dần monolith: service mới nhận dữ liệu từ database cũ.Strangling a monolith: new services receive data from the old database.

Lợi íchBenefits

  • Không có dual-write: DB là nguồn duy nhất, event luôn khớp với dữ liệu đã commit.No dual write: the DB is the single source, so events always match committed data.
  • Không phải sửa ứng dụng cũ.No changes to legacy applications.
  • Snapshot ban đầu cộng dòng thay đổi giúp hệ thống mới đuổi kịp từ con số không.An initial snapshot plus the change stream lets a new system catch up from zero.

Hạn chếLimitations

  • Event mang cấu trúc bảng nội bộ, nên schema DB thành hợp đồng công khai; đổi tên cột là vỡ consumer.Events carry internal table structure, so the DB schema becomes a public contract; renaming a column breaks consumers.
  • Replication slot bị bỏ quên khiến Postgres giữ WAL tới khi đầy đĩa.A forgotten replication slot makes Postgres retain WAL until the disk fills.
  • Event ở mức hàng dữ liệu, không mang ý nghĩa nghiệp vụ (“cột status đổi” chứ không phải “đơn đã giao”).Events are row-level, not business-level (“status column changed”, not “order delivered”).

Mẹo triển khaiImplementation tips

  • Kết hợp với outbox pattern: ghi event nghiệp vụ vào bảng outbox trong cùng transaction, CDC chỉ đọc bảng đó. Bạn vừa có nhất quán vừa có event có nghĩa.Pair it with the outbox pattern: write business events to an outbox table in the same transaction and let CDC read only that table. You get consistency and meaningful events.
  • Giám sát lượng WAL mà slot đang giữ (pg_replication_slots) và cảnh báo khi vượt ngưỡng.Monitor WAL retained by slots (pg_replication_slots) and alert above a threshold.
  • Bật compaction cho topic CDC nếu downstream chỉ cần trạng thái mới nhất của mỗi hàng.Enable compaction on CDC topics if downstream only needs the latest state of each row.
C3

Pipeline dữ liệuData pipelines

Xử lý & tích hợpProcessing & integration
eventswarehousedata lake

Đổ dữ liệu liên tục vào warehouse và data lake.Feed warehouses and data lakes continuously.

Chọn pipeline streaming là đổi sự đơn giản của ETL theo lịch lấy dữ liệu tươi và khả năng đổ vào nhiều đích cùng lúc.Choosing a streaming pipeline trades the simplicity of scheduled ETL for fresh data and many destinations at once.

Dùng choUse for
Nạp event vào warehouse vài phút một lần.Loading events into the warehouse every few minutes.
ĐượcGain
Dữ liệu tươi theo phút thay vì theo ngày.Freshness in minutes instead of days.
MấtLose
Flush xuống lake quá thường xuyên sẽ sinh ra hàng nghìn file nhỏ, cần job compaction.Flushing to the lake too often creates thousands of small files that need compaction.

Dấu hiệu nhận biếtTelltale sign Dữ liệu của đêm qua đã là quá cũ, và bạn có nhiều hơn một đích.Last night's data is already too old, and you have more than one destination.

Chi tiết: cách hoạt động, lợi ích, hạn chế, mẹoDetails: how it works, benefits, limits, tips

Nó là gìWhat it is

Chuyển dữ liệu từ hệ thống nguồn vào warehouse và data lake liên tục, thay cho job ETL chạy lúc nửa đêm.Moving data from source systems into warehouses and lakes continuously, instead of a midnight ETL job.

[events] ─▶ Kafka Connect sink ─┬─▶ Snowflake / BigQuery
                               └─▶ S3  (Parquet / Iceberg)

Hoạt động thế nàoHow it works

Kafka Connect, Flink hoặc Spark đọc topic, gom thành lô theo số record hoặc theo thời gian, rồi ghi file hay bảng ở đích. Kafka đứng giữa nguồn sinh liên tục và đích nạp theo lô.Kafka Connect, Flink or Spark reads the topic, batches by record count or time, then writes files or tables at the destination. Kafka sits between a continuous source and a batch-loaded sink.

Phù hợp cho việc gìWhat it's good for

  • Nạp event vào warehouse vài phút một lần.Loading events into the warehouse every few minutes.
  • Lake dạng Iceberg phục vụ phân tích và ML.An Iceberg lake for analytics and ML.
  • Cùng dữ liệu đổ vào nhiều đích khác nhau.The same data landing in several destinations.

Lợi íchBenefits

  • Dữ liệu tươi theo phút thay vì theo ngày.Freshness in minutes instead of days.
  • Nguồn và đích tách rời: đích chết thì dữ liệu chờ trong Kafka.Source and sink are decoupled: if the sink dies, data waits in Kafka.
  • Kafka Connect có sẵn hàng trăm connector.Kafka Connect has hundreds of ready-made connectors.

Hạn chếLimitations

  • Flush xuống lake quá thường xuyên sẽ sinh ra hàng nghìn file nhỏ, cần job compaction.Flushing to the lake too often creates thousands of small files that need compaction.
  • Exactly-once tới hệ thống ngoài tuỳ connector; nhiều connector chỉ đảm bảo at-least-once.Exactly-once into external systems depends on the connector; many only guarantee at-least-once.
  • Thay đổi schema phải đi xuyên suốt cả pipeline.Schema changes must propagate through the whole pipeline.

Mẹo triển khaiImplementation tips

  • Cân flush size với độ tươi: vài file Parquet cỡ trăm MB tốt hơn hàng nghìn file vài KB.Balance flush size against freshness: a few hundred-MB Parquet files beat thousands of tiny ones.
  • Dùng định dạng có schema (Avro, Protobuf) ngay từ topic, đừng đợi tới warehouse.Use a schema'd format (Avro, Protobuf) from the topic onward, not just at the warehouse.
  • Bật DLQ cho connector (errors.tolerance=all + errors.deadletterqueue.topic.name) để một record hỏng không dừng cả pipeline.Enable a connector DLQ (errors.tolerance=all + errors.deadletterqueue.topic.name) so one bad record doesn't stop the pipeline.
D1

Event sourcingEvent sourcing

Log là lịch sửLog as history
commandread modelaudit

Lưu chuỗi sự kiện; trạng thái là kết quả phát lại chuỗi đó.Store the sequence of events; state is what you get by replaying it.

Chọn event sourcing là đổi sự đơn giản của CRUD lấy toàn bộ lịch sử thay đổi và khả năng dựng lại mọi view.Choosing event sourcing trades the simplicity of CRUD for the full history of changes and the ability to rebuild any view.

Dùng choUse for
Sổ cái tài chính, kế toán.Financial ledgers and accounting.
ĐượcGain
Audit trail đầy đủ, có sẵn, không cần viết thêm.A complete audit trail, built in.
MấtLose
Đổi cấu trúc event cũ rất khó (versioning, upcasting).Changing the shape of old events is hard (versioning, upcasting).

Dấu hiệu nhận biếtTelltale sign Câu hỏi “tại sao trạng thái lại thế này?” quan trọng ngang câu hỏi “trạng thái là gì?”.“Why is the state like this?” matters as much as “what is the state?”.

Hiệu đính so với ảnhCorrection to the image Ảnh xếp event sourcing ngang hàng các use case khác. Kafka hợp làm bus phát event hơn là event store chính, vì nó không hỗ trợ “chỉ append nếu phiên bản hiện tại là N”.The image lists event sourcing alongside the rest. Kafka fits better as the event bus than as the primary event store, because it has no “append only if the current version is N”.
Chi tiết: cách hoạt động, lợi ích, hạn chế, mẹoDetails: how it works, benefits, limits, tips

Nó là gìWhat it is

Lưu những gì đã xảy ra (Nạp 100, Rút 30) thay vì chỉ lưu giá trị hiện tại (số dư = 70). Trạng thái được tính bằng cách duyệt qua toàn bộ sự kiện.Storing what happened (Deposited 100, Withdrew 30) instead of only the current value (balance = 70). State is computed by folding over the events.

[account-42]  Opened → Deposited(100) → Withdrew(30) → Deposited(5)
                                    phát lại ──▶ số dư = 75
[account-42]  Opened → Deposited(100) → Withdrew(30) → Deposited(5)
                                     replay ──▶ balance = 75

Hoạt động thế nàoHow it works

Hệ thống kiểm tra mỗi lệnh với trạng thái hiện tại; hợp lệ thì sinh event và append. Projection (read model) đọc event để dựng các view phục vụ truy vấn. Trong phần lớn hệ thống thật, event store chính là một database có kiểm tra phiên bản (EventStoreDB, hoặc Postgres với cột version), còn Kafka làm bus phát event ra ngoài.Each command is validated against current state; if valid, an event is produced and appended. Projections (read models) consume events to build query views. In most real systems the event store is a database with version checks (EventStoreDB, or Postgres with a version column), and Kafka is the bus that publishes the events.

Phù hợp cho việc gìWhat it's good for

  • Sổ cái tài chính, kế toán.Financial ledgers and accounting.
  • Hệ thống bắt buộc phải có audit đầy đủ (bảo hiểm, y tế).Systems legally required to keep a full audit trail (insurance, healthcare).
  • Domain cần nhiều read model khác nhau trên cùng dữ liệu.Domains needing many different read models over the same data.

Lợi íchBenefits

  • Audit trail đầy đủ, có sẵn, không cần viết thêm.A complete audit trail, built in.
  • Dựng read model mới từ toàn bộ lịch sử.New read models can be built from full history.
  • Gỡ lỗi bằng cách phát lại đúng chuỗi sự kiện đã gây lỗi.Debug by replaying the exact event sequence that caused the bug.

Hạn chếLimitations

  • Đổi cấu trúc event cũ rất khó (versioning, upcasting).Changing the shape of old events is hard (versioning, upcasting).
  • Độ phức tạp tư duy cao: team phải quen CQRS và eventual consistency.High conceptual cost: the team must be comfortable with CQRS and eventual consistency.
  • Dùng Kafka làm event store duy nhất thì thiếu optimistic concurrency theo từng aggregate và không đọc nhanh được “mọi event của account-42”.Kafka as the only event store lacks per-aggregate optimistic concurrency and can't cheaply read “all events for account-42”.

Mẹo triển khaiImplementation tips

  • Áp dụng cho một bounded context có giá trị cao, đừng áp cho cả hệ thống.Apply it to one high-value bounded context, not the whole system.
  • Nếu Kafka phải là nguồn sự thật, đặt retention.ms=-1 và suy nghĩ kỹ trước khi bật compaction — compaction xoá lịch sử.If Kafka must be the source of truth, set retention.ms=-1 and think hard before enabling compaction — compaction deletes history.
  • Snapshot định kỳ để không phải phát lại từ event số 0 mỗi lần.Take periodic snapshots so you don't replay from event zero every time.
D2

Phát lại & khôi phụcReplay & recovery

Log là lịch sửLog as history
producergroup livegroup replay

Quay lại offset cũ và xử lý lại — trong phạm vi retention.Rewind to an earlier offset and reprocess — within retention.

Chọn giữ log lâu để phát lại là đổi chi phí lưu trữ lấy khả năng sửa sai bằng cách chạy lại thay vì vá dữ liệu.Choosing long retention for replay trades storage cost for fixing mistakes by rerunning instead of patching data.

Dùng choUse for
Một bản triển khai lỗi đã ghi sai dữ liệu downstream suốt 6 tiếng.A bad deploy wrote wrong data downstream for six hours.
ĐượcGain
Khôi phục bằng một thao tác vận hành, không phải script vá dữ liệu.Recovery is an ops action, not a data-patching script.
MấtLose
Phát lại gây side effect lần hai (gửi lại email, trừ tiền lại) nếu consumer không idempotent.Replay repeats side effects (re-sent emails, double charges) unless consumers are idempotent.

Dấu hiệu nhận biếtTelltale sign Sau sự cố, câu hỏi là “chạy lại 6 tiếng vừa rồi thế nào” chứ không phải “dữ liệu đi đâu rồi”.After an incident the question is “how do we rerun the last six hours”, not “where did the data go”.

Hiệu đính so với ảnhCorrection to the image Ảnh viết “re-read from any offset, any time”. Không đúng: chỉ những offset còn nằm trong retention. Offset trước log start offset đã biến mất.The image says “re-read from any offset, any time”. Not quite: only offsets still inside retention. Anything before the log start offset is gone.
Chi tiết: cách hoạt động, lợi ích, hạn chế, mẹoDetails: how it works, benefits, limits, tips

Nó là gìWhat it is

Vì Kafka không xoá message khi đọc, consumer có thể quay về một offset cũ và xử lý lại: để sửa hậu quả của bug, dựng lại dữ liệu, hoặc cho hệ thống mới đuổi kịp.Because Kafka doesn't delete on read, a consumer can rewind to an earlier offset and reprocess: to undo a bug's damage, rebuild data, or let a new system catch up.

  log start                                       log end
     │ 120  121 … 480  481 … 500 … 812 │
     ▲                ▲              ▲
 cũ nhất còn giữ   reset về đây   consumer đang ở đây
 (0–119 đã bị retention xoá)
  log start                                       log end
     │ 120  121 … 480  481 … 500 … 812 │
     ▲                ▲              ▲
 oldest retained   reset here     consumer is here
 (0–119 already deleted by retention)

Hoạt động thế nàoHow it works

Offset của consumer group nằm trong topic nội bộ __consumer_offsets. Dừng consumer, chạy kafka-consumer-groups.sh --reset-offsets (với --to-datetime, --to-offset hoặc --shift-by), rồi khởi động lại. Chỉ phát lại được phần còn giữ: theo retention.ms/retention.bytes, hoặc bản mới nhất của mỗi key nếu topic dùng compaction.Consumer group offsets live in the internal __consumer_offsets topic. Stop the consumer, run kafka-consumer-groups.sh --reset-offsets (with --to-datetime, --to-offset or --shift-by), then restart. You can only replay what is retained: per retention.ms/retention.bytes, or the latest value per key on a compacted topic.

Phù hợp cho việc gìWhat it's good for

  • Một bản triển khai lỗi đã ghi sai dữ liệu downstream suốt 6 tiếng.A bad deploy wrote wrong data downstream for six hours.
  • Dựng một search index mới từ đầu.Building a new search index from scratch.
  • Service mới cần lịch sử để khởi động.A new service needs history to bootstrap.

Lợi íchBenefits

  • Khôi phục bằng một thao tác vận hành, không phải script vá dữ liệu.Recovery is an ops action, not a data-patching script.
  • Thử logic mới trên dữ liệu thật bằng một consumer group mới, không ảnh hưởng production.Test new logic on real data with a new consumer group, without touching production.
  • Tiered storage (KIP-405) cho phép giữ log lâu với giá của object storage.Tiered storage (KIP-405) keeps long history at object-storage prices.

Hạn chếLimitations

  • Phát lại gây side effect lần hai (gửi lại email, trừ tiền lại) nếu consumer không idempotent.Replay repeats side effects (re-sent emails, double charges) unless consumers are idempotent.
  • Chỉ trong retention; dữ liệu đã bị xoá thì không có offset nào đưa nó về.Only within retention; once deleted, no offset brings it back.
  • Phát lại khối lượng lớn tạo tải đột biến lên hệ thống đích.Large replays hammer the destination system.

Mẹo triển khaiImplementation tips

  • Thiết kế consumer idempotent trước khi cần phát lại: upsert theo khoá, hoặc bảng dedup theo event_id.Make consumers idempotent before you need replay: upsert by key, or a dedup table keyed by event_id.
  • Phát lại bằng consumer group mới khi có thể, đừng reset group đang chạy production.Replay with a new consumer group when you can; don't reset the live production group.
  • Đặt retention theo câu hỏi: lâu nhất mất bao lâu để phát hiện một bug? Cộng thêm biên an toàn.Size retention by asking: what's the longest it takes to notice a bug? Then add margin.

Bảng so sánhComparison table

Độ trễ cầnLatency needPhụ thuộc replayReplay relianceYêu cầu thứ tựOrdering needĐộ khó làm đúngHard to get rightThay thế khi quy mô nhỏCheaper option at small scale
A1 Nhắn tin bất đồng bộAsync messaginggiâysecondsthấplowtheo keyper keytrung bìnhmediumPostgres SKIP LOCKED, SQSPostgres SKIP LOCKED, SQS
A2 Pub-sub fan-outPub-sub fan-outgiâysecondstrung bìnhmediumtheo keyper keytrung bình (schema)medium (schema)SNS + SQSSNS + SQS
B1 Theo dõi hành vi người dùngActivity trackinggiây–phútseconds–minutestrung bìnhmediumtheo userper userthấplowghi thẳng vào analyticswrite straight to analytics
B2 Gom log tập trungLog aggregationgiâysecondsthấplowkhông cầnnonethấplowagent → Lokiagent → Loki
B3 Metrics & cảnh báoMetrics & alertinggiâysecondsthấplowtheo chuỗiper seriestrung bìnhmediumPrometheusPrometheus
C1 Xử lý luồngStream processingmili giây–giâyms–secondscao (dựng lại state)high (state rebuild)bắt buộc theo keyrequired per keycaohighSQL batch mỗi N phútSQL batch every N minutes
C2 Change Data CaptureChange Data Capturegiâysecondscao (snapshot)high (snapshot)bắt buộc theo khoá chínhrequired per primary keytrung bình–caomedium–highoutbox + pollingoutbox + polling
C3 Pipeline dữ liệuData pipelinesphútminutescaohighthấplowtrung bìnhmediumELT theo lịchscheduled ELT
D1 Event sourcingEvent sourcingkhông áp dụng (nguồn sự thật)n/a (source of truth)bắt buộcessentialbắt buộc theo aggregaterequired per aggregaterất caovery highbảng history trong DBhistory table in the DB
D2 Phát lại & khôi phụcReplay & recoverykhông áp dụngn/achính là nóit is the pointgiữ nguyên thứ tự gốckeeps original ordertrung bình (idempotency)medium (idempotency)raw event trên S3raw events on S3

Anti-patternsAnti-patterns

Sai lầmMistakeVì sao saiWhy it's wrongSửa thế nàoHow to fix it
Dùng Kafka như database để truy vấnQuerying Kafka like a databaseKafka không có index; tìm một record nghĩa là quét partitionNo indexes; finding one record means scanning a partitionĐẩy ra DB hoặc state store rồi truy vấn ở đóMaterialise into a DB or state store and query there
Key = null khi cần thứ tựNull key when order mattersRecord cùng thực thể rải khắp partition, thứ tự mấtOne entity's records scatter across partitions; order is lostĐặt key là ID thực thể (order_id, user_id)Key by the entity ID (order_id, user_id)
Ít partition lúc đầu, tăng sauFew partitions now, add laterTăng partition làm đổi ánh xạ key → partition, phá thứ tự theo keyAdding partitions remaps key → partition and breaks per-key orderƯớc lượng theo thông lượng đích × 2 ngay từ đầuSize for target throughput × 2 from the start
Hàng nghìn partition “cho chắc”Thousands of partitions “just in case”Mỗi partition tốn file handle, bộ nhớ, thời gian failoverEach costs file handles, memory and failover timeChỉ tạo đủ cho mức song song thật sự cầnCreate only what real parallelism needs
Nhét file lớn vào messageStuffing large files into messagesVượt ~1 MB mặc định, làm nghẽn broker và replicationExceeds the ~1 MB default and clogs brokers and replicationĐể file ở object storage, gửi đường dẫn (claim check)Put the file in object storage, send a pointer (claim check)
Auto-commit rồi mới xử lýAuto-commit, then processCrash giữa chừng là mất message đã commit nhưng chưa xử lýA crash mid-way loses messages that were committed but not processedCommit thủ công sau khi xử lý xongCommit manually after processing
Thử lại ngay trong vòng pollRetrying inside the poll loopMột message lỗi chặn cả partition và làm consumer bị đá khỏi groupOne bad message blocks the partition and gets the consumer evictedRetry topic có backoff + DLQRetry topics with backoff + DLQ
Tin exactly-once tới DB ngoàiTrusting exactly-once into an external DBTransaction của Kafka dừng ở biên KafkaKafka transactions stop at Kafka's boundarySink idempotent: upsert theo khoá hoặc dedup theo event_idIdempotent sink: upsert by key or dedupe by event_id
Không có schemaNo schemaMột producer đổi field là mọi consumer âm thầm vỡ theoOne producer changes a field and every consumer breaks silentlySchema Registry + rule compatibilitySchema Registry + compatibility rules

0. Kiến thức nền tối thiểu0. Minimum background

topic: orders  (replication factor 3)
 partition 0 │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ ◀── append (key = order_id)
 partition 1 │ 0 │ 1 │ 2 │ 3 │
 partition 2 │ 0 │ 1 │ 2 │ 3 │ 4 │
                     ▲           ▲
         group "email" ở đây   group "billing" ở đây
topic: orders  (replication factor 3)
 partition 0 │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ ◀── append (key = order_id)
 partition 1 │ 0 │ 1 │ 2 │ 3 │
 partition 2 │ 0 │ 1 │ 2 │ 3 │ 4 │
                     ▲           ▲
         group "email" is here   group "billing" is here
  • Record: một message gồm key, value, timestamp và headers. Kích thước tối đa mặc định khoảng 1 MB.Record: a message with a key, value, timestamp and headers. Default max size is about 1 MB.
  • Topic: tên một dòng record, ví dụ orders. Chia thành nhiều partition.Topic: a named stream of records, e.g. orders. Split into partitions.
  • Partition: một log có thứ tự, chỉ ghi thêm. Thứ tự chỉ được đảm bảo trong một partition. Record cùng key luôn vào cùng partition.Partition: an ordered, append-only log. Order is guaranteed only within a partition. Records with the same key always land in the same partition.
  • Offset: số thứ tự của record trong partition. Consumer nhớ mình đang ở offset nào.Offset: a record's position in its partition. Consumers remember which offset they're at.
  • Broker: một server Kafka. Mỗi partition có một leader và các follower; tập follower bắt kịp leader gọi là ISR.Broker: one Kafka server. Each partition has a leader and followers; followers that are caught up form the ISR.
  • Consumer group: nhóm consumer chia nhau partition. Mỗi partition chỉ thuộc một consumer trong group; các group khác nhau đọc độc lập.Consumer group: consumers that share partitions. Each partition belongs to one consumer in the group; different groups read independently.
  • Retention xoá dữ liệu cũ theo thời gian/dung lượng. Compaction chỉ giữ bản mới nhất cho mỗi key.Retention deletes old data by time or size. Compaction keeps only the latest value per key.
  • Ngữ nghĩa giao nhận: mặc định là at-least-once. Exactly-once chỉ đúng bên trong Kafka (idempotent producer + transaction); ra hệ thống ngoài thì đích phải idempotent.Delivery semantics: at-least-once by default. Exactly-once holds only inside Kafka (idempotent producer + transactions); external sinks must be idempotent.
  • KRaft: từ Kafka 4.0, ZooKeeper bị bỏ hẳn; metadata do chính các controller của Kafka quản lý.KRaft: since Kafka 4.0, ZooKeeper is gone; Kafka's own controllers manage metadata.

Checklist trước khi lên productionPre-production checklist

  • Replication factor 3, min.insync.replicas=2, producer acks=all.Replication factor 3, min.insync.replicas=2, producer acks=all.
  • Idempotent producer đang bật (mặc định từ Kafka 3.0 — kiểm tra lại nếu client cũ).Idempotent producer enabled (default since Kafka 3.0 — verify on older clients).
  • Đã chọn key có chủ đích; đã kiểm tra hot key.Keys chosen deliberately; hot keys checked.
  • Số partition tính theo thông lượng đích, không đoán.Partition count derived from target throughput, not guessed.
  • Retention đặt theo thời gian phát hiện bug lâu nhất cộng biên an toàn.Retention set to the longest bug-detection time plus margin.
  • Schema Registry với rule compatibility cho mọi topic dùng chung.Schema Registry with compatibility rules on every shared topic.
  • Consumer idempotent; đã chạy thử một lần replay thật.Consumers are idempotent; a real replay has been rehearsed.
  • Retry topic và DLQ, có người được báo khi DLQ có message.Retry topics and a DLQ, with someone alerted when the DLQ fills.
  • Cảnh báo consumer lag theo thời gian, không chỉ theo số message.Consumer lag alerts by time, not only by message count.
  • Giám sát Kafka bằng đường độc lập với Kafka.Kafka monitored through a path independent of Kafka.
  • TLS + SASL, ACL theo nguyên tắc quyền tối thiểu, quota cho từng client.TLS + SASL, least-privilege ACLs, per-client quotas.
  • Đã thử: tắt một broker, rolling restart, rebalance khi triển khai.Tested: killing a broker, rolling restarts, rebalancing during deploys.

3 câu cần nhớThree things to remember

  1. Kafka là log, không phải hàng đợi: message còn đó sau khi đọc, mỗi consumer group tự giữ offset của mình.Kafka is a log, not a queue: messages remain after being read, and each consumer group keeps its own offset.
  2. Thứ tự chỉ được đảm bảo trong một partition, nên chọn key là quyết định thiết kế quan trọng nhất bạn sẽ đưa ra.Order is guaranteed only within a partition, so choosing the key is the most important design decision you'll make.
  3. Đừng dùng Kafka khi chưa có ít nhất hai trong bốn nhu cầu: nhiều consumer độc lập, phát lại, thông lượng lớn liên tục, thứ tự theo key.Don't reach for Kafka until you have at least two of four needs: independent consumers, replay, sustained high throughput, per-key ordering.