Mục lục
Kafka Internals — phần 1/3. Series đi theo một record từ producer đến commit. Phần 2 đi vào producer; phần 3 đi vào consumer và offset.
Phiên bản: bài viết đối chiếu Apache Kafka 4.3.x tại tháng 10/2026. Với Kafka 3.x, một số mặc định và protocol đã khác; những chỗ đáng chú ý sẽ được ghi rõ.
Để đọc bài này: người đọc cần nắm các khái niệm cơ bản về Kafka: topic, partition, producer, consumer và offset. Hệ thống ví dụ có 3 broker, replication factor 3, 12 partitions,
min.insync.replicas=2; consumer xử lý đồng bộ trong poll loop. Các con số trong bài là minh hoạ, không phải kết quả đo production.
Một đơn hàng bị chặn 30 giây
Topic orders có 12 partitions. Consumer group có 4 instance. Instance A đang giữ partition 3; instance B giữ partition 7. Một đơn hàng trên partition 3 gọi payment service và bị timeout 30 giây.
Trong 30 giây đó, mọi record đến sau trên partition 3 phải chờ. Nếu A còn giữ partition 4, partition 4 cũng chờ, vì consumer xử lý tuần tự trong một thread. Partition 7 vẫn chạy bình thường vì B không bị chặn.
Đây là ví dụ giả định, nhưng cơ chế thì có thật. Nó giải thích luôn ba giới hạn thường gặp:
- Thứ tự chỉ được đảm bảo trong một partition, không phải toàn topic.
- Một partition chỉ thuộc một consumer trong một group tại một thời điểm.
- Số partition là trần parallelism của group. Scale lên 20 consumer mà topic vẫn 12 partitions thì 8 instance sẽ không nhận được partition nào.
Nếu giảm còn 1 partition để "đảm bảo thứ tự", mọi record đi qua một consumer. Throughput giảm, khả năng chịu lỗi giảm, và một record chậm chặn toàn bộ consumption của topic.
Đây không phải bug. Đó là hệ quả của một mô hình dữ liệu: Kafka là một tập các log có thứ tự, không phải một hàng đợi công việc. Hiểu mô hình này sẽ trả lời được câu hỏi quan trọng hơn: khi nào nên dùng Kafka, và khi nào nên chọn công cụ khác.
Kafka là một replicated log, không phải hàng đợi
Ở tầng thấp, Kafka lưu một chuỗi record trong các partition. Mỗi partition là một log append-only, được replicate sang các broker khác. Producer ghi vào cuối log; consumer đọc từ một offset. Không có khái niệm "message tiếp theo" ngoài offset tiếp theo trong một partition.
Record, partition, offset
Một record gồm key, value, headers và timestamp. Với default partitioner, key được hash để chọn partition. Cùng một key đi vào cùng một partition, nên các record của cùng một đơn hàng nằm cạnh nhau và giữ được thứ tự. Nếu key là null, producer dùng sticky partitioner: record được dồn vào một partition cho đến khi batch đầy, nhưng không có ordering theo key.
Partition là một log append-only. Mỗi record nhận một offset tăng đơn điệu trong partition đó. Offset không phải ID toàn cục: partition 3 và partition 7 đều có offset 0, và offset 0 của chúng là hai vị trí khác nhau. Record không bị sửa tại chỗ; compaction chỉ xóa bản cũ.
Consumer group chia các partition cho các instance. Một partition chỉ thuộc một consumer trong group tại một thời điểm, nhưng nhiều group có thể đọc cùng một partition độc lập. Offset đã commit của mỗi group nằm trong topic nội bộ __consumer_offsets; vì vậy hai group có thể đọc cùng dữ liệu ở hai tốc độ khác nhau mà không ảnh hưởng nhau.
Hai chi tiết dễ bị bỏ qua. Thứ nhất, thứ tự của Kafka là thứ tự append vào partition, không phải thứ tự nghiệp vụ: nếu hai producer ghi cùng một key đồng thời, broker quyết định thứ tự cuối cùng. Thứ hai, tăng số partition có thể đổi mapping key → partition, làm record cũ và mới của cùng một key rơi vào hai partition khác nhau. Số partition không giảm được, nên đây là quyết định phải làm trước khi có traffic thật.

Retention và compaction quyết định vòng đời dữ liệu
Kafka không xóa record khi consumer đã đọc. Record tồn tại theo retention hoặc theo chính sách compaction của topic.
Với cleanup.policy=delete — mặc định — Kafka xóa segment cũ khi vượt retention.ms hoặc retention.bytes. Mặc định topic giữ 7 ngày (retention.ms=604800000); đặt -1 là không giới hạn thời gian, còn retention.bytes=-1 là không giới hạn theo kích thước. Vì xóa theo segment, dung lượng thực tế có thể lớn hơn mức bạn hình dung.
Với cleanup.policy=compact, Kafka giữ bản ghi cuối cùng cho mỗi key. Record cũ cùng key bị dọn dần; tombstone (value null) đánh dấu key bị xóa và được giữ thêm một thời gian (delete.retention.ms, mặc định 1 ngày) để consumer kịp đọc. Compaction chạy nền, không tức thời.
Hệ quả: replay chỉ có thể trong cửa sổ retention. Nếu topic giữ 7 ngày, consumer mới chỉ đọc lại được 7 ngày gần nhất. Retention không phải backup, và replication cũng không phải backup: replication bảo vệ trước lỗi broker, không bảo vệ trước lỗi logic xóa dữ liệu hoặc một sự kiện xóa topic.
Offset cũng có thể có khoảng trống. Compaction xóa record, aborted transaction không trả record cho consumer read_committed, và offset vẫn tiếp tục tăng. Đừng giả định offset liên tục hay dùng offset như số thứ tự nghiệp vụ.
Replication: acks=all mạnh đến đâu?
Mỗi partition có một leader và các follower. Follower fetch từ leader để sao chép log. Tập replica bắt kịp leader là ISR (in-sync replicas). High watermark là offset mà mọi replica trong ISR đã replicate; consumer chỉ đọc được đến vùng đó.
acks=all — mặc định từ Kafka 3.0 — khiến leader đợi toàn bộ ISR ack trước khi báo thành công. Cần nhấn mạnh: "toàn bộ ISR", không phải "toàn bộ replica". Nếu ISR co lại còn 2 trong 3 replica, acks=all chỉ đợi 2 replica đó.
min.insync.replicas đặt ngưỡng ISR tối thiểu để nhận ghi. Mặc định là 1, nên acks=all với RF=3 vẫn có thể chỉ đợi leader nếu ISR co lại. Với RF=3 và min.insync.replicas=2, nếu hai broker chết và ISR chỉ còn 1, producer nhận lỗi thay vì ghi vào một replica duy nhất. Đây là availability đổi lấy durability: từ chối ghi thay vì nhận rủi ro mất dữ liệu.
unclean.leader.election.enable là lựa chọn ngược lại. Mặc định là false. Nếu bật, một replica ngoài ISR có thể thành leader khi các replica khác không sẵn sàng. Điều này tăng availability nhưng có thể làm mất record chưa kịp replicate. Vì vậy câu "acks=all không mất dữ liệu" chỉ đúng khi đi kèm min.insync.replicas và election policy phù hợp.
Trong Kafka 4.x, metadata do KRaft controller quorum quản lý; ZooKeeper đã bị loại bỏ từ 4.0. Controller quorum nằm ngoài data path: nó giữ metadata và bầu leader, nhưng không replicate record. Đừng nhầm replication của partition với replication của metadata.
Cấu hình | Điều được đảm bảo | Khi nào có thể mất |
|---|---|---|
| Leader đã ghi; chưa chắc follower đã có | Leader chết trước khi follower replicate |
| Ít nhất 2 ISR đã có record | ISR tụt dưới 2 thì producer lỗi; nếu bật unclean election, vẫn có thể mất |
| Cả 3 replica đã có record | Một replica chết là không ghi được; availability giảm |

Consumer thường đọc từ leader. KIP-392 cho phép đọc từ follower gần nhất nếu cấu hình rack-aware fetching, nhưng mặc định vẫn là leader.
Vì sao log lại nhanh — và vì sao nhanh không đủ
Kafka nhanh vì nó làm một việc đơn giản rất tốt: ghi tuần tự vào cuối log. Ghi tuần tự thân thiện với disk hơn nhiều so với cập nhật ngẫu nhiên nhiều dòng. Kafka cũng dựa vào page cache của OS, không đặt toàn bộ dữ liệu trong JVM heap. Producer gom record thành batch, nén batch, rồi gửi ít request hơn. Consumer fetch theo batch. Follower replicate theo pipeline.
Zero-copy là một mảnh khác: với plaintext, Kafka có thể dùng sendfile để chuyển dữ liệu từ page cache ra socket mà không copy qua user space. Nhưng zero-copy không miễn phí trong mọi cấu hình: TLS/SSL cần mã hoá trong user space, nên lợi ích này có thể mất khi bật encryption.
Có một chi tiết quan trọng thường bị bỏ qua: Kafka không fsync từng record theo mặc định. flush.messages mặc định là Long.MAX_VALUE; Kafka dựa vào OS flush và replication để bảo vệ dữ liệu. acks=all đảm bảo record đã nằm trong log của các ISR, nhưng không đảm bảo nó đã được fsync xuống đĩa vật lý. Nếu toàn bộ replica mất điện cùng lúc, record gần nhất vẫn có thể mất. Đây là lý do durability của Kafka là "replication + OS flush", không phải một cam kết tuyệt đối.
Và throughput cao không có nghĩa latency thấp. Một record phải đi qua nhiều chặng:
linger.msở producer: mặc định 5ms từ Kafka 4.0, tăng lên để gom batch.- Broker append và replication:
acks=allđợi ISR. - Consumer fetch:
fetch.min.bytesvàfetch.max.wait.msquyết định consumer chờ bao lâu. - Xử lý của ứng dụng: một payment call 30 giây sẽ chặn consumer thread.
Tail latency còn đến từ page cache miss, disk chậm, GC, rebalance và hot partition. Giả sử một hệ thống có throughput 100 MB/s; nó vẫn có thể có p99 latency rất xấu nếu một partition bị chặn.
Mục tiêu | Knob chính | Cái giá |
|---|---|---|
Throughput |
| Latency tăng, memory tăng |
Latency thấp |
| Nhiều request hơn, CPU cao hơn |
Durability |
| Availability giảm khi thiếu replica, cost tăng |
Cost thấp | retention ngắn, RF thấp, tiered storage | Replay window ngắn, durability giảm |
Kafka được tối ưu cho throughput và sequential access. Latency thấp là một cấu hình riêng, không phải thuộc tính mặc định.
Điểm mạnh thật sự — và điều kiện để có chúng
Kafka không mạnh vì có nhiều tính năng. Nó mạnh vì một cơ chế duy nhất: một log replicated cho phép nhiều consumer đọc độc lập và replay. Hầu hết điểm mạnh khác là hệ quả của cơ chế đó.
Nhu cầu | Cơ chế đáp ứng | Điều kiện để đúng | Bài toán điển hình |
|---|---|---|---|
Replay/backfill | Retention + reset offset | Retention đủ dài; schema ổn định | Consumer mới, sửa bug, audit |
Fan-out | Nhiều consumer group | Partition/consumer đủ; group độc lập | Event backbone, notification |
Ordering theo key | Key → partition | Key cardinality tốt; không hot key | Trạng thái đơn hàng, tài khoản |
Buffer burst | Log trên disk | Disk/lag capacity; có monitoring | Giải mã tải, decoupling |
Durability | Replication + | RF≥3, | Payment, audit, CDC |
Hệ sinh thái | Connect/Streams/Schema Registry | Có người vận hành | CDC, stream processing |
Replay là điểm mạnh khó thay thế nhất. Queue thông thường xóa message sau khi ack; Kafka giữ lại theo retention. Một consumer mới có thể đọc lại từ đầu, một consumer bị lỗi có thể tua lại để sửa dữ liệu, một pipeline mới có thể backfill mà không cần producer gửi lại. Điều kiện là retention đủ dài và schema không thay đổi theo cách phá vỡ consumer cũ.
Fan-out thật sự độc lập vì mỗi consumer group có offset riêng. Một group có thể đọc chậm mà không ảnh hưởng group khác. Điều kiện là đủ partition cho parallelism và đủ dung lượng cho từng group.
Ordering theo key đủ cho nhiều bài toán nghiệp vụ: mọi event của một đơn hàng, một tài khoản, một thiết bị nằm cùng partition. Nó không cho global ordering, và nó chỉ đúng nếu key có cardinality tốt. Một key quá phổ biến tạo hot partition; thêm partition không chia được một key.
Buffer cho phép producer và consumer chạy ở hai tốc độ khác nhau. Nhưng backlog không miễn phí: nó là disk, là lag, là thời gian recovery. Giả sử một topic có 1 tỷ record tồn đọng; nó vẫn "hoạt động", nhưng consumer có thể mất hàng giờ để đuổi kịp.
Durability là kết quả của cấu hình, không phải mặc định của sản phẩm. RF=3, minISR=2, acks=all và election policy hợp lý mới tạo ra mức bảo vệ mong muốn. Và durability không thay thế backup.
Bài toán nào phù hợp
Bài toán | Mức phù hợp | Lý do |
|---|---|---|
Event backbone/domain events | Mạnh | Nhiều consumer, replay, ordering theo key |
CDC/outbox | Mạnh | Log là đích tự nhiên của thay đổi dữ liệu |
Audit/event sourcing | Mạnh | Giữ lịch sử, replay được |
Activity tracking/metrics/logs | Mạnh | Throughput cao, nhiều consumer |
Stream processing | Mạnh | Kafka Streams/Flink đọc trực tiếp |
Task queue đơn giản | Có điều kiện | Làm được, nhưng retry/DLQ/priority phải tự xây |
Notification/fan-out | Có điều kiện | Phụ thuộc volume và yêu cầu delay |
Request/reply | Yếu | Không phải mô hình của Kafka |
Delay/priority/TTL | Yếu | Không có primitive per-message |
Payload lớn | Yếu | Cần claim check/external storage |
Global ordering | Yếu | Chỉ có per-partition ordering |
CRUD volume thấp | Yếu | Vận hành đắt so với nhu cầu |
Điểm chung: Kafka phù hợp khi dữ liệu là một dòng sự kiện cần được giữ lại, chia sẻ cho nhiều consumer và đọc lại. Nếu dữ liệu chỉ là một task cần chuyển từ A sang B, Kafka thường là quá mức cần thiết.
Điểm yếu cố hữu — cái giá của log
Phần lớn điểm yếu của Kafka không phải lỗi cấu hình. Chúng là hệ quả trực tiếp của mô hình partition và log.
Ordering chỉ theo partition
Một record chậm chặn các record sau trong cùng partition. Nếu consumer xử lý đồng bộ, nó còn chặn mọi partition khác trên cùng consumer thread. Đây là head-of-line blocking, và nó là lý do một đơn hàng lỗi có thể làm chậm cả một nhóm đơn hàng.
Hot key là mặt còn lại. Giả sử key là tenantId và một tenant chiếm 40% traffic; partition chứa tenant đó chịu tải cao hơn hẳn. Thêm partition không chia được một key; muốn giảm hot key phải đổi key hoặc tách topic.
Global ordering đòi hỏi một partition. Một partition chỉ cho một consumer trong group, nên throughput bị giới hạn bởi consumer đó. Với nhiều producer, thứ tự vẫn là thứ tự broker nhận request, không phải thứ tự nghiệp vụ.
Số partition không giảm được. Tăng partition có thể đổi mapping key → partition và làm lệch ordering giữa record cũ và mới. Đây là quyết định không thể đảo ngược, cần làm trước khi có traffic thật.
Kafka không phải queue đa dụng
Kafka không có per-message delay, priority, TTL hay visibility timeout. Retention là cấp topic, không phải cấp message. Muốn "nhắc thanh toán sau 15 phút", "ưu tiên job VIP" hoặc "task hết hạn sau 1 giờ", cần một scheduler hoặc queue khác.
Retry topic, DLQ, delay topic là những pattern của ứng dụng, không phải primitive của Kafka. Chúng hoạt động, nhưng bạn phải tự xây, tự vận hành và tự đảm bảo ordering.
KIP-932 share group (production-ready từ Kafka 4.2) bổ sung một phần semantics kiểu queue: record được acquire và acknowledge, có delivery count. Nhưng nó không thay thế đầy đủ một queue đa dụng: không có offset commit kiểu consumer group, semantics khác, và không có sẵn mọi thứ như delay/priority. Cần đọc kỹ trước khi dùng share group thay cho SQS/RabbitMQ.
Vận hành và chi phí dữ liệu
Kafka là một hệ phân tán phải vận hành: broker, disk, replication, controller quorum, upgrade, quota, multi-tenancy, security. Một team nhỏ, volume thấp thường trả giá vận hành cao hơn giá trị nhận được.
Dữ liệu cũng không rẻ. RF=3 nghĩa là mỗi byte được lưu ba lần; cross-AZ replication thêm chi phí network; retention dài làm storage tăng tuyến tính. Backlog không miễn phí: lag lớn là disk, là thời gian recovery, là incident.
Monitoring tối thiểu gồm lag, ISR, disk, controller health và request latency. Nếu không có người trực và dashboard, Kafka sẽ trở thành một điểm mù.
Những giới hạn còn lại
Exactly-once của Kafka chỉ đúng trong biên read-process-write bên trong Kafka. Nếu consumer ghi DB hoặc gọi HTTP, Kafka không làm side effect đó trở nên exactly-once; cần idempotency key, outbox hoặc một thiết kế riêng. Bài 2 sẽ đi sâu vào điểm này.
Payload lớn nên dùng claim check: gửi metadata vào Kafka, nội dung thật nằm ở object storage; max.message.bytes và max.request.size là giới hạn cần biết.
Schema là một chi phí khác. Không có Schema Registry, producer và consumer dễ coupling theo JSON tự phát; thay đổi field có thể phá consumer cũ.
Kafka không phải database: không có query, không có secondary index. Nó cũng không phải request/response: muốn có kết quả trả về, cần correlation ID và response topic, hoặc dùng HTTP/gRPC.
Điểm yếu | Cơ chế | Failure mode | Giảm thiểu/alternative |
|---|---|---|---|
Head-of-line | 1 partition → 1 consumer | Record chậm chặn key | Async processing, tách topic, partition hợp lý |
Hot key | Hash lệch | Một partition quá tải | Key salting, tách topic |
Không delay/priority/TTL | Log semantics | Không schedule được | SQS/Rabbit/Redis, scheduler ngoài |
Ops cost | Broker/disk/controller | Burnout, incident | Managed service, owner rõ |
Storage cost | RF=3 + retention | Cost tăng | Tiered storage, compaction, retention |
Payload lớn | Batch/record limit | Broker pressure | Claim check |
EOS hẹp | Transaction chỉ trong Kafka | Duplicate side effect | Idempotency/outbox |
Không request/reply | Async log | Correlation phức tạp | HTTP/gRPC |
Khi nào nên dùng Kafka
Không có câu trả lời đúng cho mọi hệ thống. Có năm câu hỏi giúp loại Kafka sớm nếu không phù hợp.
1. Dữ liệu có phải event log/stream cần replay, hay chỉ là task cần chuyển? Nếu cần đọc lại, backfill hoặc nhiều consumer cùng đọc một dòng sự kiện, Kafka có lợi thế. Nếu chỉ cần chuyển job từ A sang B, queue đơn giản hơn.
2. Có nhiều consumer độc lập/fan-out không? Nếu chỉ có một consumer, lợi thế fan-out không tồn tại; bạn đang trả giá cho một log nhưng chỉ dùng như queue.
3. Có cần ordering theo key không? Key có cardinality tốt không? Nếu cần ordering theo orderId, Kafka làm tốt. Nếu cần global ordering, Kafka không phù hợp. Nếu key là một vài tenant lớn, hot partition sẽ xuất hiện.
4. Có cần hấp thụ burst/decouple producer-consumer không? Kafka làm tốt, nhưng phải tính disk, lag và thời gian recovery. Backlog không miễn phí.
5. Có owner vận hành và ngân sách cho broker/disk/retention không? Nếu không, managed service hoặc một queue nhẹ hơn là lựa chọn hợp lý hơn.
Không nên dùng Kafka khi
- Chỉ cần chuyển task từ A sang B, không cần replay/fan-out.
- Cần per-message delay, priority, TTL hoặc visibility timeout.
- Cần request/response đồng bộ.
- Payload rất lớn và không muốn claim check.
- Cần global ordering tuyệt đối.
- Không có người/ngân sách vận hành broker.
So sánh nhanh với các lựa chọn khác
Lựa chọn | Delivery/ordering | Replay | Delay/priority | Ops | Phù hợp |
|---|---|---|---|---|---|
Kafka | At-least-once/EOS; order per partition | Có, theo retention | Không native | Cao | Event log, fan-out, stream |
RabbitMQ | Ack per message; queue ordering | Hạn chế | Có plugin/priority | Trung bình | Task queue, routing |
SQS/SNS | At-least-once; FIFO tùy chọn | Không (SQS) | Delay queue, DLQ | Thấp | AWS-native decoupling |
Pulsar | Queue/stream; subscription | Có | Tùy | Cao | Multi-tenant streaming |
NATS JetStream | At-least-once; persistence | Có | Hạn chế | Thấp–trung bình | Low-latency messaging |
Postgres outbox + queue | Transactional với DB | Có giới hạn | Tự xây | Thấp | Side effect exactly-once-ish |
Bảng này so sánh hành vi công bố, không phải benchmark. Không lựa chọn nào thắng mọi tiêu chí: RabbitMQ mạnh routing và per-message ack; SQS nhẹ vận hành; Pulsar mạnh multi-tenancy; NATS JetStream nhẹ và nhanh; Postgres outbox mạnh khi cần transactional với DB.
Phương án hybrid
Kafka thường là một phần của kiến trúc, không phải toàn bộ.
- Kafka làm event log; SQS/RabbitMQ làm task queue. Hai công cụ giải hai bài toán khác nhau.
- Kafka + Postgres outbox cho side effect transactional. Ghi outbox trong cùng transaction DB, rồi relay sang Kafka.
- Kafka + Kafka Streams/Flink cho stateful processing.
- Tránh dual-write: đừng ghi Kafka và DB trong hai transaction rời. Dùng outbox/CDC để biến hai lần ghi thành một luồng có thể phục hồi.

Checklist trước khi chọn Kafka
Trước khi tạo topic, trả lời bảy câu hỏi:
- Retention: cần replay bao lâu?
retention.ms/retention.bytesđủ chưa? - Key: đơn vị ordering là gì? Cardinality có tốt không? Có hot tenant/key?
- Partitions: parallelism tối đa cần bao nhiêu? Tăng partition sau này ảnh hưởng key/order thế nào? Số partition không giảm được.
- Consumer groups: có bao nhiêu group? Mỗi group có đủ consumer theo partition không?
- Ops: ai trực? ai upgrade? có monitoring lag/ISR/disk/controller không?
- Cost: RF=3 + retention + cross-AZ; so với managed service/queue chưa?
- Correctness: at-least-once hay EOS? Side effect có idempotent không? DLQ/retry ra sao?
Ví dụ tối thiểu cho topic orders:
kafka-topics.sh --bootstrap-server localhost:9092 \
--create --topic orders \
--partitions 12 \
--replication-factor 3 \
--config min.insync.replicas=2 \
--config retention.ms=604800000 \
--config cleanup.policy=deleteSố partition và replication factor là quyết định một chiều; đổi sau sẽ tốn kém.
Tín hiệu phải thiết kế lại:
- Lag tăng dù traffic không tăng.
- Rebalance storm hoặc consumer liên tục bị thu hồi partition.
- Một partition hot bất thường.
- Storage cost tăng nhanh hơn giá trị dữ liệu, hoặc không có owner vận hành.
Ba điều không nên làm:
- Dùng Kafka như database/query store.
- Dùng Kafka cho request/response đồng bộ.
- Giả định "
acks=all= không mất dữ liệu" mà không kiểm traminISRvà election policy.
Kết: chọn mô hình, không chọn API
Kafka không phải lựa chọn mặc định cho mọi async. Nó là lựa chọn cho event log có replay, fan-out và ordering theo key. Cái mua được là mô hình log; cái trả là partition planning, vận hành và một tập guarantee hẹp.
Nếu bài toán chỉ là chuyển task, queue hoặc DB phù hợp hơn và rẻ hơn. Nếu cần nhiều consumer đọc lại cùng một dòng sự kiện, Kafka thường là lựa chọn mạnh — miễn là đội ngũ hiểu rằng thứ tự chỉ đúng trong partition, và durability phụ thuộc vào cấu hình chứ không phải tên sản phẩm.
Chọn Kafka vì cần log, không vì cần một message broker. Bài tiếp theo đi vào con đường từ send() đến broker, nơi batch, retry và exactly-once bắt đầu.
Bài tiếp theo: Kafka Internals #2 — Producer: từ send() đến broker, và giới hạn của exactly-once.
Nguồn tham khảo
- Apache Kafka 4.3 — Design: https://kafka.apache.org/43/design/design
- Apache Kafka 4.3 — Topic config: https://kafka.apache.org/43/generated/topic_config.html
- Apache Kafka 4.3 — Producer config: https://kafka.apache.org/43/generated/producer_config.html
- Apache Kafka 4.3 — Consumer config: https://kafka.apache.org/43/generated/consumer_config.html
- Apache Kafka 4.0 release announcement (KRaft-only): https://kafka.apache.org/blog/2025/03/18/apache-kafka-4.0.0-release-announcement
- Apache Kafka 4.2 release announcement (KIP-932 production-ready): https://kafka.apache.org/blog/2026/02/17/apache-kafka-4.2.0-release-announcement
- KIP-932 — Queues for Kafka: https://cwiki.apache.org/confluence/display/KAFKA/KIP-932%3A+Queues+for+Kafka
- KIP-392 — Allow Consumers to Fetch from Closest Replica: https://cwiki.apache.org/confluence/display/KAFKA/KIP-392%3A+Allow+consumers+to+fetch+from+closest+replica
- Jay Kreps, "The Log: What every software engineer should know about real-time data's unifying abstraction": https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying
- RabbitMQ documentation: https://www.rabbitmq.com/docs
- Amazon SQS documentation: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html
- Apache Pulsar documentation: https://pulsar.apache.org/docs/
- NATS JetStream documentation: https://docs.nats.io/nats-concepts/jetstream