Automatic Apache Kafka Migrations With Orbit

Bài tóm tắt WarpStream 2026 3. Quy mô lớn Độ khó: Khó

WarpStream · 2026 · 3. Quy mô lớn · Độ khó: Khó — bài gốc

Bài của nhà cung cấp, giới thiệu tính năng sản phẩm (Orbit Auto Migration). Cơ chế được mô tả chi tiết và có giá trị chung cho migration hệ log/queue; các nhận định về kết quả là theo WarpStream.

Bối cảnh

  • Chuyển một cụm Kafka sang WarpStream gồm ba phần: dữ liệu, consumer, producer. Một cụm thường phục vụ nhiều team.
  • Orbit (đã có) nhân bản topic và offset của consumer group từ cụm nguồn, giữ nguyên offset từng record. Consumer chỉ việc đổi bootstrap URL, từng nhóm chuyển khi sẵn sàng.
  • Producer là phần khó: quy trình cũ là dừng mọi producer của topic, chờ lag về 0, tắt nhân bản, khởi động lại producer trỏ sang WarpStream. Tức là có downtime, có người ngồi canh dashboard, và chỉ cần một producer bị quên còn ghi vào cụm cũ là mất dữ liệu, nên mọi team phải chuyển cùng lúc.
  • Một số khách tự làm bằng feature flag động hoặc dùng ACL trên cụm nguồn làm "tín hiệu" để ứng dụng đổi client. WarpStream không thể sửa ứng dụng của từng khách, còn "fat client" riêng thì khó với mọi ngôn ngữ.

Thay đổi chính: proxy chỉ chuyển tiếp produce

  • Producer đổi bootstrap URL sang WarpStream trước, theo nhịp riêng của từng team; Agent WarpStream chuyển tiếp produce request về cụm nguồn. Gom toàn bộ luồng ghi về một chỗ WarpStream kiểm soát được, nên tự động hoá được bước cutover.
  • Máy trạng thái cho mỗi topic (ở control plane): REJECT (đang nhân bản, cấm ghi trực tiếp) → PROXY (chuyển tiếp, có thể kéo dài nhiều tháng) → MIGRATING (trả lỗi retriable, producer giữ trong buffer và tự thử lại) → COMPLETE. Cửa sổ cutover thường vài giây. Không xong trong timeout thì tự quay về PROXY; có thể huỷ tay bất cứ lúc nào trước khi xong.
  • Làm lộ rủi ro sớm, trong giai đoạn còn quay lui được:
    • Giả lập latency: WarpStream ghi thẳng object storage nên ack chậm hơn Kafka dùng đĩa. Producer chỉnh cho vài ms sẽ thiếu buffer và nghẽn (định luật Little: throughput ≈ số request đang bay × kích thước / latency ack). Proxy cố ý giữ phản hồi lâu bằng thời gian WarpStream sẽ cần, để producer được chỉnh trước cutover. Theo WarpStream, cách này đã bắt được một producer cấu hình sai của khách.
    • Kiểm tra auth/ACL của WarpStream ngay ở proxy, dù ghi thật vẫn sang cụm nguồn.
    • Chỉ bắt đầu cutover khi lag theo thời gian đủ nhỏ (không dùng lag theo offset, vì một triệu record có thể là vài giây hoặc một tuần tuỳ topic).
    • Ưu tiên nhân bản cho topic đang cutover; giữa các topic thì topic ít lag xong trước (shortest-job-first), trong một topic thì partition nhiều lag chạy trước (longest-processing-time-first).
  • Producer bị quên: proxy gắn header nội bộ vào record đã chuyển tiếp; Orbit thấy record không có header thì báo tên topic. Producer chạy thưa (cron 12 giờ một lần) không bị bắt theo cách đó, nên sau khi xong vẫn theo dõi offset cuối của cụm nguồn thêm 24 giờ. Bắt lúc này là muộn, nhưng vẫn hơn mất dữ liệu âm thầm.
  • Mọi thay đổi trạng thái migration phát thành sự kiện để có lịch sử ai làm gì, mấy lần thử.

Những chỗ khó về tính đúng

  • Chuyển tiếp nguyên vẹn: không dùng Kafka producer client có sẵn (nó chia lại partition, gộp lại batch, nén lại, tự retry và đổi producer identity). Proxy tự tách request theo leader của từng partition, gửi nguyên batch gốc song song, rồi ráp phản hồi.
  • Khi nào được tắt nhân bản: nếu một record đã được ack trên cụm nguồn mà nhân bản đã tắt thì record đó bị bỏ lại. Control plane chờ mọi Agent xác nhận đã chặn ghi và đã xong mọi request đang bay (qua heartbeat); Agent không báo được thì chặn cutover.
  • Agent bị cô lập: quyền chuyển tiếp là một lease vài giây. Agent không được chuyển tiếp dựa trên cache trạng thái cũ hơn vài giây, và request chuyển tiếp không xong trong vài giây thì trả lỗi retriable dù có thể đã ghi. Control plane chờ hết khoảng đó rồi mới đo lag. Đánh đổi: chấp nhận trùng lặp thay vì mất dữ liệu (idempotent producer sẽ loại trùng).
  • Idempotent producer: producer ID do từng cụm cấp, nên Agent xin ID ở cả hai cụm, lưu cặp ánh xạ và đổi ID khi chuyển tiếp. Số thứ tự (sequence) của producer: WarpStream nhận số của batch đầu tiên sau cutover làm điểm xuất phát; vì không có ghi nào được ack trong lúc cutover nên số đó nối đúng chỗ. Batch đến lệch thứ tự thì client tăng epoch và gửi lại, tệ nhất là trùng chứ không mất.

Bài học cho SWE

  • Mẫu "đổi điểm vào trước, đổi nơi ghi sau": mọi client trỏ về hệ mới (đang làm proxy) theo nhịp riêng, rồi cutover được tự động và lặp lại được theo từng đơn vị nhỏ (topic) (Migration không downtime).
  • Làm cho giai đoạn proxy giống hệ mới nhất có thể (latency, auth) để lỗi lộ ra khi còn quay lui được; migration là cánh cửa một chiều.
  • Lag nên đo bằng thời gian, không bằng số message (Event-driven, message queue và Kafka).
  • Fencing bằng lease ngắn + trả lỗi retriable khi không chắc: đổi mất dữ liệu lấy trùng lặp, rồi dùng idempotency để loại trùng.

Liên quan