Tôi thử kafka-lite viết bằng Rust thay cho Kafka

Anh em mình cứ hễ nói đến message queue hay streaming là gần như auto-reply dùng Kafka. Hệ thống của tôi không lớn, tầm 15 microservices, 20 topic, peak cũng chỉ 80-100 msg/giây. Tôi chạy cụm 3 broker + 3 Zookeeper.

5db9b092-e035-497a-8ca8-8faedf19de9d

Nghe có vẻ bình thường, nhưng cái này đang ngốn của chúng tôi:

  • Hơn 400$/tháng chỉ để duy trình nó.
  • Thỉnh thoảng GC của JVM nhảy vọt không rõ lý do.
  • Consumer lag rất khó debug.
  • Mỗi lần muốn đổi một cái config là lại phải lôi cái kafka-configs.sh ra gõ, khá là phiền phức.

Vấn đề là, chúng tôi không cần một thứ có thể xử lý triệu-triệu message/giây. Chúng tôi chỉ cần nó… chạy ổn định. Thế là tôi bắt đầu tìm kiếm, và vớ được một dự án cực kỳ thú vị trên GitHub tên là mvillarrealb/kafka-lite.

kafka-lite

Nó là một server clone Kafka, viết 100% bằng Rust.

Điểm mấu chốt đã thuyết phục tôi thử nó:

  1. Một file binary duy nhất: Tải về, chmod +x, và chạy.
  2. Không ZooKeeper: Đây là thứ giúp phần lớn nhất về vận hành.
  3. Không JVM: Nó là Rust native, không GC, không tuning heap size.
  4. Tương thích giao thức Kafka: Nó implement protocol Kafka (bản cũ v0.10-0.11). Nghĩa là producer/consumer cũ của mọi người cắm vào là chạy, không phải đổi code.
  5. Stateful, nhưng đơn giản: Nó tự quản lý log, append-only ra file local, y hệt Kafka gốc nhưng đã bị cắt đi để nhẹ hơn.

Kiến trúc của nó là sự tối giản của Kafka:

             ┌─────────────┐
             │  Producer   │ (Dùng thư viện Kafka bình thường)
             └─────┬───────┘
                   │ Kafka Protocol (TCP)
                   ▼
       ┌────────────────────────┐
       │ Server kafka-lite      │
       │ (Rust binary)          │
       │  - Vòng lặp Tokio      │
       │  - Ghi log ra file     │
       │  - Theo dõi offset     │
       └─────────┬──────────────┘
                 │ (Đọc/Ghi local disk)
                 ▼
       ┌────────────────────────┐
       │   /var/data/kafka-lite/│
       │   (Append-only logs)   │
       └────────────────────────┘

Setup và sử dụng

Không cần Ansible, không cần Docker Compose 5-6 service:

# Tải file binary từ GitHub
curl -L https://github.com/mvillarrealb/kafka-lite/releases/download/v0.1.0/kafka-lite -o /usr/local/bin/kafka-lite
chmod +x /usr/local/bin/kafka-lite

# Chỉ định thư mục chứa data
kafka-lite --data-dir /var/data/kafka-lite --port 9092

Nó khởi động trong chưa tới 200ms. Và lúc rảnh, nó tốn… 14MB RAM. So sánh với 512MB+ Heap của JVM cho Kafka là thấy một trời một vực.

Chúng tôi thử cắm code producer Python cũ vào:

# Code producer Python cũ, không cần sửa
from kafka import KafkaProducer

producer = KafkaProducer(
    bootstrap_servers='dia_chi_server_rust:9092',
    client_id='my-test-app'
)

print("Đang gửi message...")
# Gửi vào topic 'events'
producer.send("events", b"Hello tu con server Rust")
producer.flush() # Đẩy đi ngay
print("Gửi xong!")

Ngay lập tức. Message được ghi thẳng vào file trong /var/data/kafka-lite.

Nó nhanh và nhẹ

Nó chỉ làm đúng 2 việc cốt lõi của Kafka:

  1. Nhận request qua TCP dùng tokio, phân tích gói tin protocol Kafka.
  2. Nếu là ProduceRequest, nó append-only vào cuối file của topic đó.
  3. Nếu là FetchRequest, nó đọc file từ offset mà consumer yêu cầu và trả về.

Logic ghi file của nó minh họa bằng Rust:

// Minh họa hàm ghi file log (đã viết lại)
use std::fs::{File, OpenOptions};
use std::io::{Write, Result};
use std::path::Path;

/// Ghi một mảng byte vào cuối file log của topic
fn append_to_log(topic_data_dir: &Path, message: &[u8]) -> Result {

    // Đảm bảo thư mục topic tồn tại
    std::fs::create_dir_all(topic_data_dir)?;

    let log_path = topic_data_dir.join("000000.log");

    // Mở file ở chế độ append (ghi nối)
    let mut file = OpenOptions::new()
        .append(true)  // Đây là mấu chốt
        .create(true)  // Tạo file nếu chưa có
        .open(log_path)?;

    // Ghi message (có thể thêm độ dài, timestamp, v.v...)
    // Ở đây ta ghi thẳng cho đơn giản
    file.write_all(message)?;

    Ok(())
}

Nó nhanh vì nó tránh được toàn bộ gánh nặng của Kafka gốc:

  • Không GC: Vì là Rust.
  • Không ZooKeeper: Không cần quản lý cụm, controller, đồng bộ metadata.
  • Không Replication: Không cần đồng bộ ISR (In-Sync Replicas).
  • Không Compaction: Chỉ ghi nối.
  • Không JVM tuning: Không quan tâm Heap size.

Kafka vs kafka-lite

Team tôi chạy test 1 triệu message payload 200B và kết quả thế này:

Metric Apache Kafka (Cụm 3 node) kafka-lite (1 node)
Thời gian khởi động ~10 giây ~200ms
RAM (lúc rảnh) ~512MB+ (JVM Heap) 14MB
Tốc độ (1M msg) ~2.1 giây 1.2 giây
Disk (sau 1M msg) ~110MB (thêm index,…) 22MB (chỉ raw log)
Cần ZooKeeper? Không

Kết quả: Cụm Kafka 6 VM cũ được thay bằng một con VPS 5 đô/tháng. Latency trung bình từ ~10ms giảm còn ~0.7ms. Consumer lag gần như bằng 0.

Đánh đổi

kafka-lite là một sự đánh đổi cực lớn. Mọi người phải chấp nhận những gì nó thiếu:

  1. Không High-Availability: Đây là điểm chí mạng. Con server Rust này mà chết là… chết. Nó chạy 1 node, ghi ra disk local. Nếu con VPS 5$ đó hỏng ổ cứng, mọi người mất dữ liệu.
  2. Không Replication: Vì chỉ có 1 node, nên không có khái niệm replication factor.
  3. Không Compaction/Tiered Storage: Log cứ ghi mãi, file sẽ phình to. Mọi người phải tự viết script để dọn dẹp.
  4. Protocol cũ: Chỉ hỗ trợ v0.10-0.11. Nghĩa là mấy thứ hay ho như Kafka Streams hay các tính năng header mới là không chạy.
  5. Không bảo mật: Không SASL, không ACLs. Nó tin tưởng 100% mạng nội bộ.

Kết luận

Chúng tôi đã không thay thế Kafka ở production cho những hệ thống lõi. Rủi ro mất dữ liệu khi 1 node chết là quá lớn.

Nhưng chúng tôi đang dùng con kafka-lite này ở nơi khác:

  • Dev local: Anh em dev giờ chỉ cần chạy 1 file binary là có Kafka để code, thay vì chạy Docker Compose 4-5 container.
  • Chạy CI/CD: Build xong vứt vào pipeline test, siêu nhanh.
  • Pub/Sub Staging: Dùng cho các service không quá quan trọng ở môi trường staging.

Không phải lúc nào cũng cần giải pháp xịn nhất. Đôi khi, một giải pháp đơn giản, đúng protocol, giải quyết 80% bài toán là đủ, lại còn rẻ và nhanh hơn rất nhiều.

Thông tin nổi bật

Báo cáo quan trọng

Chia sẻ bài viết:
Theo dõi
Thông báo của
0 Góp ý
Được bỏ phiếu nhiều nhất
Mới nhất Cũ nhất
Phản hồi nội tuyến
Xem tất cả bình luận