← все видео

100K QPS với Kafka + Outbox + Saga: Senior Backend làm gì để không mất dữ liệu? | Phần 2

Tips Javascript · 2026-05-27 · 11м 56с · 2 706 просмотров · YouTube ↗

Топики: durable-execution

🎧 Аудио

📝 Summary

model=deepseek-v4-flash · prompt=summary-v7 · 6 752→1 581 tokens · 2026-07-20 15:03:45

🎯 Главная суть

В Kafka существуют два разных механизма acknowledgement (подтверждения): один для producer (гарантирует доставку сообщения до broker), второй для consumer (подтверждает обработку сообщения). Для Outbox-паттерна update флага published должен выполняться на стороне producer после получения ack от broker, а не на consumer — это сохраняет границы сервисов. Consumer использует commit offset для отметки обработанных сообщений, а при ошибках broker автоматически повторяет отправку.

Различие acknowledgement producer и consumer в Kafka

Producer acknowledgement (acks) подтверждает только запись сообщения на диск broker — consumer никак не участвует. Consumer acknowledgement в Kafka работает иначе, чем в RabbitMQ: consumer не подтверждает каждое сообщение по отдельности, а фиксирует номер обработанного offset. Например, consumer обработал сообщение с offset 31 — он отправляет broker сигнал «я обработал всё до 31 включительно, присылай offset 32». Следующее обработанное сообщение смещает коммит на 33 и так далее. Это двухуровневая система: producer ack — для гарантии записи, consumer ack — для гарантии обработки.

Где обновлять publish=true: только на стороне producer

Update флага published в таблице Outbox-событий должен выполняться исключительно в том же instant (JVM), который создал запись — то есть в producer. Consumer почти всегда работает в другом сервисе (другом инстансе) и не должен иметь прямого доступа к базе данных producer. Если разрешить consumer самостоятельно обновлять Outbox-таблицу producer, это нарушает service boundary — границы ответственности сервисов. Такой подход считается антипаттерном в микросервисной архитектуре, поскольку смешивает логику и создаёт прямую связанность между независимыми сервисами.

Когда обновлять publish=true: после producer acknowledgement

Оптимальный момент для установки published=true — сразу после того, как producer получил acknowledgement от broker. При этом consumer может упасть или обработать сообщение с ошибкой — это не повлияет на флаг. Если consumer упадёт, broker не получит его acknowledgement и запустит retry: будет повторно отправлять сообщение до тех пор, пока consumer не обработает успешно и не закоммитит offset. Таким образом, Outbox-паттерн не отвечает за доставку до consumer — это задача механизма retry внутри Kafka. Флаг published лишь обозначает, что сообщение гарантированно попало в broker.

Три конфигурации acks (0, 1, all) и их влияние на throughput

Kafka позволяет настроить уровень подтверждения для producer через параметр acks:

Consumer acknowledgement: commit offset и retry при ошибках

Consumer в Kafka не подтверждает каждое сообщение отдельно — он коммитит offset, указывая, какие сообщения уже обработаны. Если consumer упал при обработке сообщения с offset 31, он не успел закоммитить offset, и broker при перебалансировке или новом poll начнёт отправлять сообщения с того же offset 31 (или с последнего закоммиченного). Это даёт автоматический retry: сообщение будет доставляться снова, пока consumer явно не обработает его и не закоммитит offset. Таким образом, комбинация Outbox-паттерна (гарантирующего запись в broker) и механизма commit offset в consumer обеспечивает надёжную доставку сообщений даже при сбоях потребителя.

📜 Transcript

vi · 2 830 слов · 26 сегментов · clean

Показать текст транскрипта
Người mới học rất là hành nhầm hoặc là anh em từ RebizMQ qua cũng rất là hành nhầm về vấn đề này. Thật ra trong KFK nó có cái hai loại acknowledgement. Một bên là producer và một bên consumer. Thì để tôi giải thích một chút trước khi mà chúng ta đi đi sâu hơn một chút nha. Có hai loại acknowledgement nha anh chị. Tính nghĩa là S hoặc là SK cũng được. Nói lại một chút nha. Accounting của thằng producer thì nó đảm bảo việc tin nhắn một cái message tới broker. Hết. Tính nghĩa là tin nhắn được ghi vào disk. acknowledgement của consumer thì nói như thế nào? Tôi nghĩ là từ thằng consumer đây, nó sẽ báo đến producer là welcome các anh chị quay trở lại với kênh Tiếp Java, một trong những kênh trong nội trình thái của Tiếp Java Script, tôi là Analystic. Bây giờ chúng ta đi tiếp tục cái story về DDD, ban vẽ tổng tích 2 concurrency. Ở video trước, tôi và các anh chị đã bàn luận về Saga, Apox, Button và C, CDC Stream. Thì video mà giải thích cái vấn đề đó được triển khai trên cộng đồng. Và có rất nhiều anh chị phản hồi một cách rất là tích cực. Có nghĩa là tại sao không kết hợp giữa Apox button và CCDC. Hoặc là đưa ra những cái nhận định nếu như sử dụng Apox button thì nó có những cái nhược điểm như thế này như thế kia. Kiến trúc đầu tiên các anh chị sẽ nhận dạng ra là Apox có những nhược điểm này. Kiến trúc thứ hai chúng ta sử dụng CCDC này là cũng có những nhược điểm khác nhau đúng không? Ở đây là chúng ta sẽ public vào cái binh lock và chạy luôn. Và cái cách thứ ba. mà anh em mình thảo luận đó chính là kết hợp cầm ba giữa cái việc mà sử dụng Outpost Event và đọc từ cái Outpost Event đó thì cách này nó có thể nói là một trong những cách mà có thể tốt nhất nhưng đổi lại nó rất là phức tạp và dành cho các hệ thống mà có thể anh em mình chưa vơi tới được. Traffic rất là cao. Ở đây thay vì chúng ta đọc binh log thì nó sẽ đưa vào cái Outpost Event và ở đây chúng ta có thể đọc những cái dữ liệu nó từ Outpost Event mà thôi. Cái việc này chúng ta sẽ nói sau ha tại vì ở đây nó có một cái lợi thức là nó không cần query. và nó không cần update nữa đúng không? Nó không cần query đọc select ở đây và nó cũng không cần phải update lại cái round này. Nói tóm lại khi mà video đó ra thì tôi cảm thấy rất nhiều anh chị có tư duy giải quyết vấn đề thật là tốt đồng nghĩa với việc nó level của anh chị mình đã tập trung khá là cao trong cái việc triển khai dự án lần này. Thì video này một mặt là chúng ta sẽ tích hợp cái việc Outbox button vào các API mà đặt hàng bất đồng bộ thì việc sử dụng Outbox button nó diễn ra một cách rất là xôn xẻ. Chút nữa chúng ta sẽ xem hệ thống hoạt động một cách trơn tru như thế nào khi có Outbox button và cái nhược điểm phải đánh đổ như thế nào. Theo như anh em thảo luận, cách đầu tiên chúng ta sử dụng một cái Outpost, Outpost Event. Thì cái nhược điểm của nó ở đây nếu như hệ thống mà có lượng traffic cao hoặc là throughput cao thì đây chắc chắn chính là một cái bottleneck của database. Tức nghĩa là khi mà insert liên tục liên tục thì nó tạo ra các nhiều connect khác nhau. Mặc dù cái tỷ lệ ghi nó rất là nhanh chóng để hoàn thành việc đóng connect. Nhưng cái việc mà sử dụng database nó không chỉ dành riêng cho thằng Outpost Event. mà nó còn dành cho business khác nữa cái nhận điểm thứ hai anh em nói đúng đó chính là khi mà mình sử dụng cái Outpost button này mà select lên thì nó có độ lấy latency rất là cao đúng không tại vì mỗi lần chúng ta lập Blitz schedule một giây bắt đầu nó chảy giả dự trong một giây đó có hàng ngàn dữ liệu ở trong đó thì cái việc mà handle rất là khó khăn và cái thứ ba chúng ta cần thảo luận đây chính là việc update publish bằng true cái việc update publish bằng true này Nó phải diễn ra Tại vì nếu như cái tính nhắn này nếu như không được only bằng true thì nó sẽ bằng phone mic và nó cứ tiếp tục gửi liên tục liên tục liên tục Vì vậy ở đây nó sẽ sinh ra một cái đó là tính indempotence Đúng không? Tính bất biến Trước khi chúng ta nói về tính bất biến tôi có một câu hỏi ở đây À mà thật ra đây cũng không phải là câu hỏi của tôi mà câu hỏi của các anh em khi mà xem xong cái video đầu tiên về Outpost button cũng như là Saga thì anh em có thể xem những câu hỏi ở đây này Trong đây có một câu hỏi mà chúng ta cần phải suy nghĩ đó là cái việc mà cái message nó được update tại đâu? Và vì sao? Thì tôi sẽ trả lời cơ hội này đầu tiên cho các anh chị ha. Nó nằm ở provider hay là nó nằm ở consumer? Vậy anh chị chọn 1 hay là 2? Nó nằm ở đâu? Và vì sao? Thì anh chị có thể comment lại để mà thảo luận cái vấn đề này. Nếu như tôi đưa ra cái sự lựa chọn thì tôi chắc chắn trả lời đó là phía, phía public là phía provider. Chúng ta sẽ triển khai ở phía provider. Vì sao? Có những cái khía cạnh không nên triển khai tại consumer. Một, cái public này á. nó sẽ sử dụng gì? nó sẽ sử dụng S ở đây chính là AACC, Agnelemon. Đúng không? Thì ở đây này, tôi biết có nhiều lập trình viên sử dụng RaybitMQ quen rồi. Nhưng mà khi qua sử dụng Kafka, thì cái Agnelemon này nó sẽ khác nha. Nó sẽ khác nha. Chứ không phải nó giống RaybitMQ. Cho nên một số hiểu lầm mà trong vòng phỏng vấn anh chị đưa ra tôi nhận thấy sai rất rất là nhiều khi mà nhân định về S này, Agnelemon này. Quay trở lại cái việc vì sao mà không triển khai tại Consumer. Thì anh chị cũng có thể thấy này. Tất cả các hệ thống khi mà sử dụng consumer đều nằm ở hệ thống khác chứ không phải nằm trong một cái Instant GVM của chúng ta. Tức cái này nó nằm ở một cái Instant khác nha. Vì vậy thằng này không có quyền nó connect đến database của anh em mình, của database của bên thằng này để mà tự động update những cái tin nhắn publish bằng tool này. Không cho phép. Nó chính xác hơn á, consumer này thường là một cái, cái gì? Cái survey khác. Nếu consumer này nó phải update bảng Outtop Event. Trong cái database của browser Thì nó sẽ gì? Nó sẽ vi phạm cái service boundary Trong cái solid nó cũng giải thích rất là kỹ về cái vấn đề này Nó sẽ tạo một thói quen tức là nó phải có quyền truy cập vào database của browser Đây là người ta nói là một cái vấn đề nghiêm trọng trong Microsoft có nghĩa là anti pattern Người ta chia ra để người ta bảo vệ hệ thống của mình Người ta chia ra để người ta độc lập những instant mà cuối cùng anh chị lại sử dụng chung như vậy là Do đó điều quan trọng là update Nó phải nằm trong producer này Nằm trong instant này Ok chưa Đó là cái thứ 3 Câu hỏi tiếp theo đây Khi nào chúng ta sẽ sử dụng update publish bằng true Với cái điều kiện nào Đó chính là sẽ ra cái sự kiện ac key Hoặc là chúng ta đọc ac cũng được ac Hoặc là ac Nolement Trong thằng Rebill MQ Cái thằng này được định nghĩa rất là rõ Có nghĩa là gì Có nghĩa là khi mà consumer nó xử lý xong Thì nó xác nhận, tao đã xử lý xong cái message này. Và trong producer nhận được acknowledgement có nghĩa là đúng. Nhưng mà trong KfK, nó có hai loại acknowledgement. Người mới học rất là hành nhầm, hoặc là anh em từ RebizMQ qua cũng rất là hành nhầm về vấn đề này. Thật ra trong KfK, nó có cái hai loại acknowledgement. Một bên là producer và một bên consumer. Thì để tôi giải thích một chút. Trước khi mà chúng ta đi đi sâu hơn một chút nha. Có hai loại đô la mần nha anh chị. Tức là S hoặc loại CK cũng được. Loại đầu tiên có nghĩa là gì? Loại đầu tiên khi mà P tức là producer. Nó sẽ send một cái message ở đây. Và nó đến gì anh chị? Nó chưa đến consumer đâu. Nó đến gì? KFK broker. Nó phải đến KFK broker. Thì thằng KFK broker này. Nó sẽ xác nhận được rằng tao đã nhận được một cái message này rồi. Thì nó sẽ trả vì thằng này là đô la mần. Chính là cái việc này. Cách đầu tiên, tức nghĩa là khi producer nó gửi một cái tin nhắn, mà nó nhận được cái acknowledgement này, thì acknowledgement này có nghĩa là thằng broker nó đã nhận và ghi message vào, vào disk. Nó không liên quan gì đến consumer nha anh chị. Thì ngay lúc này đây, khi mà nhận được một cái acknowledgement, thì chúng ta hãy update cái thằng publish bằng true. Thì ở đây có một số người em sẽ tư nhí nhận ra rằng, ủa anh tiếp ơi, nếu như mà cái message này nó trả bằng true, thì nó đâu có quan tâm đến cái việc consumer nó sẽ xử lý như thế nào. Nếu như consumer nó bị sai hoặc bị fail, thì cái tin nhắn này nó sẽ bị mất hay là sao? Tại vì bên Apple Button nó update đã bằng true rồi. Cái cơ hội này rất là kinh điển. Khi mà consumer nó không hoạt động như ý hoặc là nó bị crash hoặc là nó bị gãy dưới chân chẳng hạn đi. Thì tức nghĩa là cái acknowledgement này nó không được active. Đúng không? Không được active có nghĩa rằng thằng broker nó sẽ không nhận được cái vấn đề là consumer này nó đã được xử lý cái message này hay không? Nếu như nó không xử lý được vaccine 1, 2, 3 chẳng hạn đi. Broker nó sẽ có cơ chế retry. Nó sẽ gửi lại một lần nữa. Đến khi nào mà thật consumer nó sẽ ra một hoạt động acknowledgement. Thì lúc đó cái commit upset nó sẽ nhảy lên. Thì cho nên đây là một cái điểm mạnh khi mà mình dùng Kfk. Lúc này outpock pattern nó không liên quan đến vấn đề này nữa. Anh chị bị hiểu ha. Tức là consumer nó bị fail thì nó sẽ retry lại, retry lại. Tại cái commit upset đó. Chứ không phải là nó sẽ bỏ qua. Do đó các anh chị có yên tâm mà sử dụng Kfk. Đây là những kiến thức mà anh chị phải cố gắng nắm bắt khi mà sử dụng KFK chứ không phải là sử dụng cho có. Đến đây một số anh chị sẽ nói, vậy chắc chắn là nó sẽ đến broker hay là không. Thì trong tầng KFK nó có 3 câu hình Adolman để chúng ta có thể lựa chọn. Bằng 0, bằng 1 là bằng All. Đây là 3 cái giá trị mà câu hình. Nếu như bằng 0 có nghĩa là cái message này nó có thể mất nếu như broker bị crash. Tức nghĩa là nó không chờ Adolman. Điều đó có nghĩa là cái gì? Điều đó có nghĩa là cái sự việc mà Theraput nó được nâng lên. Nếu như bằng 1, Thì nó sẽ xác nhận rằng nó sẽ chờ cái thằng broker chính để nhận Adolman. Điều này có nghĩa là khi mà chế độ replication, thằng cha nó có, thằng cha nó có nha. Nhưng mà thằng con nó chưa chắc nó có. Tại vì nó bị crash trước khi vận chuyển thằng con. Là cơ chế bằng 1. Còn cơ chế bằng on, có nghĩa là nó chờ tất cả cái gì? Chờ tất cả cái nhắn replay mà trả về Adolman rồi mới có thể xử lý tiếp. Thì loại này là an toàn nhất. Khi mà trong dùng production, tức như là nó phải bắt buộc là thằng cha, thằng con, thằng cháu, thằng chết phải nhận được một cái business để đánh. Rồi nó mới trả lại cái acknowledgement. Do đó, khi mà sử dụng cái thằng này, thì độ throughput nó thấp một chút. Thằng này thấp hơn một chút và thằng này cao. Tại vì nó không cần quan tâm mất hay không. Tao chỉ cần gửi thôi. Có 3 loại con phí anh chị nhớ thôi. Vậy consumer ở đây, nó có chế độ acknowledgement hay không? Nó có anh chị. Nó vẫn có là acknowledgement ở đây. Nhưng nó sẽ khác cái việc mà từ producer đến KFK broker. Có nghĩa là gì? Thì trong cái consumer nó không acknowledgement từng message như RebicamQ đâu mà thay vào đó nó consumer vào cái gì? Vào comment offset cái này thì anh chỉ phải xem cái video về tôi đã giải thích comment offset là cái gì Có nghĩa như thế này Giả sử chúng ta gửi một cái message ID là bằng 31 đi Và nó sẽ xử lý xong 31 tức là tao nhận rồi, tao xử lý rồi và tao đánh cái dấu là acknowledgement Thì nó sẽ gửi về cho thằng broker này Nó sẽ gửi về cho thằng broker, nó sẽ báo rằng Tao làm việc thứ 31 rồi nha, đừng có gửi lại nha, nếu mà có gửi, gửi thứ 32 cho tao Đây chính là acknowledgement của thằng consumer Anh chị hiểu chưa? acknowledgement của consumer nó thông báo cho rằng tao đã xử lý được đến cái round thứ 31 rồi Đừng có gửi round 31 lại nữa mà bắt đầu round 32 gửi cho tao để tao xử lý Cứ như vậy nó bắt đầu 32 xử lý xong thì gửi 33 Cứ như vậy đây là acknowledgement của thằng consumer Còn ngược lại acknowledgement của thằng producer đó chính là tao đã gửi tới broker mà thôi, đã ghi vào chỗ disk rồi Như vậy anh chị hiểu hai cái giai đoạn acknowledgement của hai thằng khác nhau nha Nói lại một chút nha acknowledgement của thằng producer thì nó đảm bảo việc tin nhắn một cái message tới broker hết tức nghĩa là tin nhắn được ghi vào vào disk acknowledgement của consumer thì nó như thế nào tức nghĩa là từ thằng consumer đây nó sẽ báo đến broker là tao đã xử lý được 31 và tao gửi một cái chế độ acknowledgement thì mày làm sao lần sau gửi là gửi 32 offset limit là vậy 33 34 mày đừng có gửi thứ 31 nữa tại vì tao đã Tại vì tao đã gửi một cái signal Adolman cho mày rồi, thì mày gửi cho tao nó bắt đầu từ 32. Thì 32 xử lý xong Adolman, thì bắt đầu là quay trở lại gửi 33. Không bao giờ gửi 32 nữa. Đây là hai chế độ của Adolman. Bây giờ chúng ta sẽ triển khai cái code và tôi sẽ nói thêm những cách mà triển khai về schedule chạy bao nhiêu một lần, rồi cách triển khai publish như thế nào, rồi cách update như thế nào để cho nó vệnh toàn dữ liệu. Tiếp theo chúng ta sẽ quay trở lại cái việc phát triển code trong cái dự án High Concurrency, FlexShare. trong những thời điểm mà cao điểm thì chúng ta đã thông nhất với nhau cái việc mà sử dụng đặc hàng bất đồng bộ sử dụng KFK đúng không thì đây chính là cái hàm

⚙️ Pipeline jobs

StageStatusAtt.UpdatedError
download done 1/3 2026-07-20 15:03:10
transcribe done 1/3 2026-07-20 15:03:26
summarize done 1/3 2026-07-20 15:03:45
embed done 1/3 2026-07-20 15:03:47

📄 Описание YouTube

Показать
100K QPS với Kafka + Outbox + Saga: Senior Backend làm gì để không mất dữ liệu? | Phần 2

👉 Link Discord: https://youtu.be/hcz1-Srwh6k

👉 HOT HOT Link Member backend NESTJS: https://www.youtube.com/playlist?list=PLw0w5s5b9NK7HkcQUBIxjcHPB2DS4UKDg

Trong video này mình sẽ chia sẻ cách các Senior Backend Engineer xử lý bài toán mất dữ liệu khi chạy hệ thống distributed ở scale lớn với Kafka, Outbox Pattern và Saga Pattern.

Chúng ta đã đi qua:

Vì sao Outbox vẫn có thể mất event
Retry như thế nào để không duplicate dữ liệu
Idempotency trong Kafka consumer
Exactly-once có thật sự “exactly”?
Transaction Boundary trong microservice
Dead Letter Queue (DLQ)
Consumer lag và backpressure
Event ordering khi scale partition
Các lỗi production thường gặp ở hệ thống high throughput
Kinh nghiệm thực chiến khi chạy hệ thống 100K QPS

Nếu bạn đang học:
Java, Spring Boot, Kafka, Microservices, Distributed System, System Design, Event Driven Architecture, Saga Pattern, CQRS hoặc Outbox Pattern thì video này dành cho bạn.

Tham gia làm hội viên của kênh này để được hưởng đặc quyền:
https://www.youtube.com/channel/UCky92hx0lZxVBi2BJ6Zm2Hg/join

👉 Link Member backend Go: https://www.youtube.com/playlist?list=PLw0w5s5b9NK6qiL9Xzki-mGbq_V8dBQkY

👉 Link Member backend Nodejs: https://www.youtube.com/playlist?list=PLw0w5s5b9NK4ucXizOF-eKAXKvn9ruCw8

👉 Link Member backend Java: https://www.youtube.com/channel/UCky92hx0lZxVBi2BJ6Zm2Hg/join

🚩  Subscribe  ➜https://www.youtube.com/c/TipsJavascript
#anonystick #backend 
✅  Follow Me:
Blog: https://anonystick.com
Ticktok: https://www.tiktok.com/@tips.javascript
Github: https://github.com/anonystick/anonystick
Facebook: https://www.facebook.com/TipJS/
Youtube: https://www.youtube.com/c/TipsJavascript