1M messages per second: Applying E2EE to Apache Kafka in the LINE app

Bài tóm tắt LINE (LY Corp) 2026 3. Quy mô lớn Độ khó: Trung bình

LINE (LY Corp) · 2026 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc

Wiki chỉ ghi phần liên quan tới vận hành và migration; phần mật mã tóm tắt ngắn.

Bối cảnh

  • Một topic Kafka lớn của LINE, tới 1 triệu message/giây, do một team publish và nhiều team consume, chứa dữ liệu cá nhân nhạy cảm.
  • TLS, SASL, ACL bảo vệ đường truyền và quyền truy cập, nhưng không bảo vệ plaintext nằm trên broker. LY Corp thêm mã hoá đầu-cuối giữa producer và consumer như một lớp phòng thủ nữa.

Thiết kế

  • Mã hoá từng record (không theo batch) để dùng được điểm mở rộng chuẩn của Kafka (interceptor, serializer) mà không sửa client; đổi lại nén kém hơn và tốn CPU hơn.
  • DEK/KEK: payload mã hoá bằng khoá đối xứng (DEK, AES-GCM); DEK mã hoá bằng khoá công khai (KEK, ECC) lấy từ KMS. Metadata (KEK ID, DEK đã mã hoá) nằm trong header của message, không cần kho ngoài.
  • Cache DEK một khoảng thời gian ở producer; consumer cache cặp DEK mã hoá → DEK giải mã.
  • Một KEK dùng chung cho mọi consumer: nếu mỗi consumer một khoá thì header phình theo số consumer, batch chứa ít record hơn, tốn băng thông và CPU. Đánh đổi lấy kích thước ổn định; giảm rủi ro bằng phân quyền KMS và xoay khoá định kỳ.

Migration không downtime

  • Plaintext fallback: deserializer có header thì giải mã, không có thì đọc như cũ. Thứ tự: deploy consumer trước, rồi mới bật mã hoá ở producer, theo dõi tới khi tỉ lệ plaintext về 0%.
  • Rollout theo tỉ lệ bằng cấu hình động: 1% → 10% → 50% → 100% theo CPU, latency, tỉ lệ lỗi; có bất thường thì đặt về 0% để quay lui. Lên 100% trong khoảng hai tuần, không sự cố nào.
  • Xoay khoá không downtime: producer poll KMS; khi có KEK mới, header chứa DEK mã hoá bằng cả khoá cũ lẫn khoá mới. Consumer chọn entry khớp khoá của mình. Chỉ tắt khoá cũ sau khi metric xác nhận consumer đã dùng khoá mới.
  • Benchmark trước: tái hiện RPS và kích thước message lớn nhất của production trên phần cứng giống hệt; CPU tăng dưới khoảng 1% mỗi instance, nên không cần thêm server. Production cũng đúng như dự đoán.

Bài học cho SWE

  • Đổi định dạng dữ liệu trên một luồng nhiều consumer: người đọc phải hiểu cả hai định dạng trước khi người ghi đổi (Migration không downtime).
  • Rollout theo phần trăm với nút quay về 0% là cách an toàn cho thay đổi chạm mọi message.
  • Xoay khoá cũng là một migration: giai đoạn chồng lấn cũ/mới, chỉ gỡ cũ khi có bằng chứng.
  • Đo overhead bằng benchmark sát production trước khi tranh luận lý thuyết.

Liên quan