Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

Bài 28 — Streaming Data với Kafka

Technical Product Manager Bài 28/60

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn là PM của một ứng dụng gọi xe như Be hay Grab. Mỗi giây có hàng nghìn sự kiện xảy ra: tài xế bật app, khách đặt chuyến, vị trí GPS cập nhật, thanh toán hoàn tất. Câu hỏi đặt ra: hệ thống của bạn "biết" về những sự kiện này lúc nào — ngay tức khắc, hay một tiếng sau mới biết?

Sự khác biệt giữa "ngay tức khắc" và "một tiếng sau" chính là ranh giới giữa streamingbatch. Và ranh giới này quyết định rất nhiều thứ thuộc về sản phẩm: bạn có thể hiển thị tài xế gần nhất theo thời gian thực không? Bạn có phát hiện gian lận ngay khi giao dịch xảy ra, hay chờ báo cáo cuối ngày? Bạn có gửi push notification "bạn vừa nhận điểm thưởng" trong vòng 2 giây không?

Là Technical PM, bạn không cần viết code Kafka. Nhưng bạn bắt buộc phải hiểu khi nào nên dùng streaming, streaming "đắt" ở chỗ nào, và vì sao engineer của bạn cứ nhắc đến những từ như "topic", "partition", "consumer lag". Nếu không, bạn sẽ vẽ ra những roadmap kiểu "real-time dashboard cho mọi thứ" mà không hiểu rằng mình vừa yêu cầu một dự án hạ tầng tốn vài tháng. Bài này giúp bạn nói cùng ngôn ngữ với team data và đưa ra quyết định đúng về độ trễ (latency) mà sản phẩm thực sự cần.

Khái niệm cốt lõi

Batch vs Streaming — hai cách nhìn về dữ liệu

Batch processing là xử lý dữ liệu theo lô. Bạn gom dữ liệu lại trong một khoảng thời gian — một giờ, một ngày — rồi chạy một job để xử lý toàn bộ lô đó cùng lúc. Ví dụ kinh điển: mỗi đêm 2 giờ sáng, hệ thống chạy job tổng hợp doanh thu trong ngày, tính ra báo cáo, gửi email cho ban giám đốc. Đặc điểm của batch:

  • Độ trễ tính bằng phút đến giờ. Dữ liệu lúc 10 giờ sáng có thể tới tối mới được xử lý.
  • Đơn giản, rẻ, dễ vận hành. Chạy theo lịch (scheduled), nếu lỗi thì chạy lại cả lô.
  • Phù hợp cho báo cáo định kỳ, tổng hợp kế toán, huấn luyện mô hình ML hàng đêm.
Stream processing là xử lý từng sự kiện ngay khi nó xảy ra. Không chờ gom lô. Một event vừa phát sinh — ví dụ "khách hàng A vừa click vào sản phẩm X" — là hệ thống xử lý ngay, độ trễ tính bằng mili-giây đến vài giây. Đặc điểm của streaming:

  • Độ trễ rất thấp (low latency), gần như tức thời.
  • Phức tạp và tốn kém hơn để xây và vận hành.
  • Phù hợp cho phát hiện gian lận, gợi ý real-time, theo dõi vị trí trực tiếp, cảnh báo hệ thống.
Một cách ví von: batch giống như bạn rửa hết chén sau bữa ăn. Streaming giống như bạn rửa từng cái chén ngay khi vừa dùng xong. Cách nào "tốt hơn" hoàn toàn phụ thuộc vào nhu cầu — không phải lúc nào cũng cần rửa ngay.

Kafka là gì và giải quyết vấn đề gì

Apache Kafka là một nền tảng streaming phân tán (distributed streaming platform). Nói cho dễ hiểu, Kafka đóng vai trò "đường ống trung tâm" để các sự kiện chảy qua giữa các hệ thống. Trước khi có Kafka, các công ty thường gặp tình trạng "mạng nhện tích hợp": hệ thống đặt hàng phải kết nối trực tiếp tới hệ thống kho, hệ thống thanh toán, hệ thống email, hệ thống phân tích... Mỗi kết nối là một sợi dây. Với N hệ thống, bạn có thể có tới N×N sợi dây — không thể bảo trì nổi.

Kafka đảo ngược mô hình này. Thay vì các hệ thống nói chuyện trực tiếp với nhau, producer (hệ thống tạo sự kiện) chỉ cần đẩy sự kiện vào Kafka, và consumer (hệ thống cần dữ liệu) tự lấy ra đọc. Người gửi không cần biết ai sẽ đọc, người đọc không cần biết ai đã gửi. Đây gọi là kiến trúc publish-subscribe (pub/sub) — hay decoupling, tách rời các hệ thống.

Các thuật ngữ bạn nhất định phải hiểu

Khi ngồi họp với team data, bạn sẽ nghe những từ sau. Hiểu chúng giúp bạn không bị "ngợp":

  • Event (sự kiện): một mẩu dữ liệu mô tả điều gì đó vừa xảy ra. Ví dụ: {user_id: 123, action: "add_to_cart", product: "iPhone", time: "10:05:33"}. Event là bất biến — đã xảy ra thì không sửa được.
  • Topic: một "kênh" hay "danh mục" để nhóm các event cùng loại. Ví dụ topic orders chứa mọi sự kiện đơn hàng, topic payments chứa mọi sự kiện thanh toán. Producer ghi vào topic, consumer đọc từ topic.
  • Partition: mỗi topic được chia thành nhiều phần gọi là partition, để xử lý song song. Đây là chìa khóa giúp Kafka mở rộng (scale). Nếu topic orders có 10 partition, bạn có thể có 10 luồng đọc song song. Càng nhiều partition, càng xử lý được nhiều, nhưng cũng phức tạp hơn.
  • Producer / Consumer: bên ghi và bên đọc, như đã nói ở trên.
  • Consumer lag (độ trễ tiêu thụ): đây là chỉ số PM cần để mắt nhất. Lag là khoảng cách giữa "event mới nhất được ghi vào" và "event mới nhất được consumer xử lý". Lag cao nghĩa là hệ thống đang xử lý không kịp — dữ liệu real-time của bạn thực ra đang trễ. Khi engineer nói "consumer lag đang tăng", nghĩa là có vấn đề về năng lực xử lý.
  • Retention (thời gian lưu giữ): Kafka giữ event trong một khoảng thời gian (ví dụ 7 ngày) chứ không xóa ngay sau khi đọc. Điều này cho phép consumer đọc lại (replay) nếu cần — một tính năng cực kỳ giá trị mà bạn sẽ thấy trong ví dụ bên dưới.

Vì sao Kafka quan trọng với sản phẩm

Điểm mạnh sản phẩm của Kafka không chỉ là "nhanh". Mà là:

  • Một nguồn sự kiện, nhiều mục đích sử dụng. Cùng một luồng orders, team phân tích đọc để làm dashboard, team ML đọc để cập nhật gợi ý, team chống gian lận đọc để cảnh báo — tất cả độc lập, không ảnh hưởng nhau.
  • Khả năng replay. Nếu team ML phát hiện model gợi ý bị lỗi tuần trước, họ có thể "tua lại" event của tuần đó để xử lý lại. Với batch truyền thống nhiều khi dữ liệu đã mất.
  • Tách rời tốc độ. Hệ thống ghi nhanh không bị hệ thống đọc chậm kéo lại, vì Kafka làm bộ đệm (buffer) ở giữa.

Tình huống thực tế

Ví dụ 1 — Tiki và bài toán "tồn kho real-time" ngày sale 11.11

Giả định Tiki tổ chức sale 11.11. Một sản phẩm hot — tai nghe AirPods — chỉ còn 500 chiếc nhưng có 8.000 người cùng xem. Nếu hệ thống tồn kho cập nhật theo batch mỗi 5 phút, hậu quả là: trong 5 phút đó, hàng nghìn người vẫn thấy "còn hàng" và bấm mua, dẫn đến oversell — bán 1.200 đơn cho 500 sản phẩm. Khách bị hủy đơn, phẫn nộ, mạng xã hội bùng nổ chỉ trích.

Giải pháp streaming: mỗi sự kiện "đặt mua thành công" được đẩy vào topic inventory_events trong Kafka. Một consumer chuyên trừ tồn kho đọc từng event ngay lập tức, cập nhật số lượng còn lại trong vòng dưới 1 giây. Khi chạm 0, sản phẩm chuyển sang "hết hàng" gần như tức thời.

Diễn giải: ở đây latency không phải là chuyện "đẹp thì có", mà là yêu cầu nghiệp vụ cứng. Sai số 5 phút = mất tiền thật và mất uy tín. Là PM, bạn phải nhận ra: với các tình huống có cạnh tranh tài nguyên hữu hạn (vé, hàng giới hạn, slot đặt chỗ), batch gần như chắc chắn không đủ.

Bài học: Đừng hỏi "real-time có hay không". Hãy hỏi "sai số bao nhiêu giây thì sản phẩm vẫn chấp nhận được?". Câu trả lời đó định nghĩa kiến trúc.

Ví dụ 2 — Ví điện tử MoMo và phát hiện gian lận

Giả định một ví điện tử như MoMo cần phát hiện giao dịch bất thường. Một tài khoản vừa đăng nhập từ Hà Nội, 30 giây sau lại giao dịch từ một IP ở nước ngoài với số tiền lớn — dấu hiệu tài khoản bị chiếm đoạt.

Nếu dùng batch chạy mỗi đêm, hệ thống chỉ phát hiện gian lận sau 12 tiếng — lúc đó tiền đã bị rút sạch. Vô nghĩa. Với Kafka, mọi giao dịch chảy vào topic transactions. Một consumer của hệ thống chống gian lận (fraud detection) đọc từng giao dịch, chạy qua bộ quy tắc và model, và nếu phát hiện rủi ro thì khóa giao dịch trước khi nó hoàn tất hoặc cảnh báo trong vài giây.

Đáng chú ý: cùng topic transactions đó còn được consumer khác đọc để tính dashboard doanh thu, và consumer thứ ba đọc để gửi biên lai cho khách. Một nguồn dữ liệu, ba mục đích, hoàn toàn độc lập.

Diễn giải: đây là minh họa hoàn hảo cho sức mạnh decoupling của Kafka. Khi team chống gian lận nâng cấp logic của họ, họ không cần đụng tới hệ thống thanh toán hay dashboard. Mỗi team sở hữu consumer của mình.

Bài học: Khi bạn thấy nhiều team cùng cần một loại dữ liệu cho mục đích khác nhau, streaming qua Kafka thường là kiến trúc gọn gàng hơn nhiều so với việc mỗi team tự đi query database gốc — vốn sẽ làm quá tải database vận hành.

Ví dụ 3 — Startup giao đồ ăn và cái bẫy "real-time cho mọi thứ"

Một startup giao đồ ăn ở TP.HCM, mới gọi vốn, thuê được team kỹ thuật giỏi. PM hào hứng vẽ roadmap: "Mọi dashboard nội bộ đều phải real-time bằng Kafka." Team triển khai. Ba tháng sau: chi phí hạ tầng tăng vọt, cần thêm 2 kỹ sư chỉ để vận hành Kafka cluster, và... báo cáo doanh thu theo ngày cho kế toán vẫn chỉ được xem mỗi sáng một lần.

Họ đã dùng dao mổ trâu để giết gà. Báo cáo kế toán hàng ngày hoàn toàn không cần streaming — một job batch chạy lúc 1 giờ sáng là quá đủ, rẻ hơn nhiều và dễ bảo trì. Streaming chỉ thực sự cần cho theo dõi đơn hàng đang giao và phân bổ tài xế real-time.

Diễn giải: streaming không "xịn hơn" batch. Nó là một đánh đổi (trade-off). Đổi lấy độ trễ thấp, bạn trả bằng độ phức tạp vận hành, chi phí hạ tầng và nhân sự.

Bài học: PM giỏi không phải người chọn công nghệ mới nhất, mà người chọn đúng công cụ cho từng bài toán. Hãy phân loại từng tính năng theo nhu cầu latency thực sự, đừng "streaming hóa" cả công ty vì nó nghe sang.

Hướng dẫn từng bước

Khi đối diện một yêu cầu sản phẩm có yếu tố dữ liệu thời gian thực, đây là khung tư duy bạn nên đi qua:

Bước 1 — Xác định ngân sách latency. Hỏi rõ: tính năng này chấp nhận dữ liệu trễ bao lâu? Dưới 1 giây? Vài phút? Đến cuối ngày? Viết con số cụ thể vào spec. Đây là quyết định sản phẩm quan trọng nhất và chỉ PM mới trả lời được — không phải engineer.

Bước 2 — Phân loại batch hay stream. Nếu ngân sách latency tính bằng giờ/ngày và dữ liệu mang tính tổng hợp định kỳ → chọn batch. Nếu tính bằng giây và mỗi event cần phản ứng riêng lẻ → cân nhắc streaming.

Bước 3 — Liệt kê các "người tiêu dùng" của dữ liệu. Có bao nhiêu team/hệ thống cần luồng dữ liệu này? Nếu chỉ một, một pipeline đơn giản có thể đủ. Nếu nhiều, kiến trúc pub/sub kiểu Kafka cho thấy giá trị rõ rệt.

Bước 4 — Làm rõ yêu cầu về độ tin cậy. Hỏi engineer: nếu mất một event thì sao? Với event "lượt xem trang" mất một vài cũng không chết ai. Với event "thanh toán" thì tuyệt đối không được mất. Yêu cầu này (gọi là delivery guarantee) ảnh hưởng lớn đến độ phức tạp và chi phí.

Bước 5 — Thống nhất chỉ số giám sát. Đưa consumer lag vào như một chỉ số sức khỏe sản phẩm. Nếu lag tăng, trải nghiệm "real-time" của người dùng đang xấu đi dù UI vẫn chạy. Đặt ngưỡng cảnh báo cùng team.

Bước 6 — Định nghĩa schema của event. Mỗi event chứa trường gì, kiểu dữ liệu nào? Việc này liên quan chặt tới bài về Event Tracking và Schema Design — bạn cần phối hợp để event vừa phục vụ streaming vừa dùng được cho phân tích sau này.

Lỗi thường gặp & mẹo

Lỗi 1 — Nhầm "real-time" với "tốt hơn". Rất nhiều PM mặc định streaming là nâng cấp của batch. Không phải. Đó là hai công cụ cho hai bài toán. Mẹo: luôn bắt đầu bằng câu hỏi latency, để con số tự dẫn bạn tới lựa chọn.

Lỗi 2 — Bỏ qua consumer lag khi nghiệm thu. Tính năng "bản đồ tài xế real-time" demo rất mượt khi có 10 tài xế, nhưng tới giờ cao điểm 5.000 tài xế thì lag bùng nổ và bản đồ trễ 30 giây. Mẹo: yêu cầu test tải (load test) ở quy mô thực tế và đưa ngưỡng lag vào tiêu chí Done.

Lỗi 3 — Quên rằng event là bất biến và có thể đến không đúng thứ tự. Trong hệ thống phân tán, event đôi khi tới muộn hoặc lệch thứ tự. Nếu sản phẩm của bạn giả định "event luôn đến đúng trình tự", bạn sẽ gặp bug khó hiểu. Mẹo: hỏi engineer cách hệ thống xử lý event đến trễ (late-arriving events).

Lỗi 4 — Không thiết kế cho việc xử lý lại. Bug xảy ra. Khi consumer xử lý sai một loạt event, khả năng replay từ Kafka là cứu cánh. Mẹo: hỏi sớm "nếu logic sai, ta tua lại dữ liệu được không, retention bao lâu?".

Lỗi 5 — Đánh giá thấp chi phí vận hành. Một Kafka cluster sản xuất cần giám sát, scaling, xử lý sự cố. Mẹo: với startup nhỏ, cân nhắc dịch vụ Kafka quản lý (managed) như Confluent Cloud hoặc AWS MSK thay vì tự vận hành — đắt hơn về phí dịch vụ nhưng rẻ hơn nhiều về nhân sự và rủi ro.

Bài tập thực hành

  • Phân loại latency. Lấy chính sản phẩm bạn đang làm, liệt kê 6 tính năng có liên quan đến dữ liệu. Với mỗi tính năng, ghi rõ "ngân sách latency" (giây/phút/giờ/ngày) và kết luận nó nên dùng batch hay streaming. Mục tiêu: thấy rằng đa số tính năng không cần streaming.
  • Vẽ luồng event. Chọn một sự kiện cốt lõi trong sản phẩm (ví dụ "đơn hàng được tạo"). Vẽ sơ đồ: producer nào tạo ra event, event vào topic gì, và liệt kê tối thiểu 3 consumer khác nhau có thể cùng đọc topic đó cho 3 mục đích khác nhau.
  • Thiết kế chỉ số giám sát. Giả sử bạn sở hữu tính năng "thông báo đẩy khi có khuyến mãi". Viết ra: consumer lag bao nhiêu giây thì coi là chấp nhận được, bao nhiêu thì cảnh báo, và bạn sẽ giải thích cho stakeholder phi kỹ thuật ý nghĩa của con số đó như thế nào.
  • Tình huống trade-off. Một stakeholder yêu cầu "tất cả dashboard nội bộ phải real-time". Viết một đoạn phản biện 150 từ, dùng đúng ngôn ngữ batch/stream và chi phí vận hành, để thuyết phục họ phân loại nhu cầu thay vì streaming hóa toàn bộ.

Tóm tắt

Streaming và batch là hai cách xử lý dữ liệu, khác nhau cốt lõi ở độ trễ: batch gom dữ liệu theo lô và xử lý định kỳ (độ trễ phút/giờ), streaming xử lý từng event ngay khi xảy ra (độ trễ giây). Không cái nào "tốt hơn" — chúng là đánh đổi giữa độ trễ với độ phức tạp và chi phí.

Kafka là nền tảng streaming phổ biến nhất, hoạt động theo mô hình pub/sub: producer đẩy event vào topic, consumer đọc độc lập. Sức mạnh sản phẩm của nó nằm ở việc tách rời các hệ thống (decoupling), cho phép một nguồn dữ liệu phục vụ nhiều mục đích, và khả năng tua lại (replay) event. Các thuật ngữ then chốt cần nhớ: topic, partition, producer/consumer, consumer lag và retention.

Là Technical PM, đóng góp lớn nhất của bạn không phải chọn công nghệ, mà là xác định đúng ngân sách latency cho từng tính năng, nhận ra khi nào streaming thực sự cần thiết, và cảnh giác với cái bẫy "real-time hóa mọi thứ" tốn kém vô ích. Hãy để con số latency dẫn dắt quyết định, đưa consumer lag vào tiêu chí nghiệm thu, và luôn cân nhắc chi phí vận hành thật. Khi bạn làm được những điều đó, bạn sẽ là cầu nối đáng tin cậy giữa nhu cầu sản phẩm và năng lực hạ tầng của đội kỹ thuật.