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.

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.shra 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ó:
- Một file binary duy nhất: Tải về,
chmod +x, và chạy. - Không ZooKeeper: Đây là thứ giúp phần lớn nhất về vận hành.
- Không JVM: Nó là Rust native, không GC, không tuning heap size.
- 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.
- 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:
- Nhận request qua TCP dùng
tokio, phân tích gói tin protocol Kafka. - Nếu là ProduceRequest, nó append-only vào cuối file của topic đó.
- 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:
use std::fs::{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...)
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? | Có | 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:
- 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.
- Không Replication: Vì chỉ có 1 node, nên không có khái niệm replication factor.
- 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.
- 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.
- 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.




