Apache Kafka: Kiến Trúc Nền Tảng & Cơ Chế Hoạt Động Từ A-Z

Table of contents
- 📦 Apache Kafka: Khám Phá Kiến Trúc Và Cơ Chế Hoạt Động
- Tình huống thực tế: Hệ thống đặt vé máy bay lớn
- 🧠 Các Khái Niệm Cốt Lõi Trong Kafka
- 🔄 Dòng Chảy Dữ Liệu Trong Kafka (Đơn Giản)
- 💡 Tại Sao Kafka Mạnh Mẽ Đến Vậy?
- ⚙️ Đi Sâu Hơn Về Kiến Trúc Kỹ Thuật
- 🧪 Ví dụ Kỹ Thuật (Node.js) – Minh họa Cơ Chế
- 📌 Tổng Kết Các Thành Phần Cốt Lõi

📦 Apache Kafka: Khám Phá Kiến Trúc Và Cơ Chế Hoạt Động
Kafka đã trở thành trái tim của nhiều hệ thống xử lý dữ liệu lớn và real-time (thời gian thực). Nhưng chính xác thì Kafka là gì, và nó hoạt động như thế nào để xử lý hàng tỷ sự kiện mỗi ngày? Bài viết này sẽ giúp bạn hiểu tận gốc kiến trúc của Kafka qua những giải thích đơn giản và ví dụ cụ thể.
Tình huống thực tế: Hệ thống đặt vé máy bay lớn
Hãy tưởng tượng bạn đang quản lý một hệ thống đặt vé máy bay cực kỳ bận rộn. Mỗi giây có hàng nghìn lượt người dùng tìm kiếm chuyến bay, đặt vé, thanh toán, hủy vé... Mỗi hành động là một "sự kiện".
Để hệ thống hoạt động trơn tru, bạn cần một nơi đáng tin cậy để:
Thu thập tất cả các sự kiện này từ các nguồn khác nhau (ứng dụng web, app di động...).
Lưu trữ chúng một cách an toàn, có thứ tự và không bị mất.
Phân phối các sự kiện này tới các bộ phận xử lý khác nhau (dịch vụ thanh toán, dịch vụ gửi email xác nhận, dịch vụ cập nhật chỗ trống...).
Đây chính là lúc Apache Kafka tỏa sáng. Nó đóng vai trò như một Nền tảng Luồng Sự Kiện (Event Streaming Platform), giúp các dịch vụ gửi và nhận dữ liệu (sự kiện) theo thời gian thực một cách hiệu quả, bền vững và có khả năng mở rộng cực cao.
🧠 Các Khái Niệm Cốt Lõi Trong Kafka
Chúng ta sẽ cùng tìm hiểu các thành phần chính tạo nên Kafka:
1. Producer – "Người gửi" dữ liệu
Producer là những ứng dụng hoặc hệ thống tạo ra và gửi dữ liệu đến Kafka. Hãy nghĩ đến chúng như các thiết bị ghi nhận sự kiện trong hệ thống đặt vé của bạn:
Khi khách hàng nhấn nút "Đặt vé", hệ thống tạo ra một sự kiện "Đặt Vé Mới".
Khi thanh toán thành công, hệ thống tạo ra sự kiện "Thanh Toán Thành Công".
👉 Producer sẽ gửi các tin nhắn (message) này đến Kafka.
2. Topic – "Kênh" lưu trữ dữ liệu
Kafka không gửi tin nhắn lung tung. Mọi tin nhắn đều được gửi vào một Topic cụ thể. Bạn có thể hình dung Topic như một "kênh chuyên biệt" hoặc một "thư mục" nơi các tin nhắn cùng loại được lưu trữ.
Hình trên cho thấy một topic có 4 partitions, với phần ghi được thêm vào cuối mỗi partition. Kafka cung cấp khả năng dự phòng (redundancy) và khả năng mở rộng (scalability) thông qua các partitions. Mỗi partition có thể được lưu trữ trên một máy chủ khác nhau, điều đó có nghĩa là một topic có thể được mở rộng theo chiều ngang trên nhiều máy chủ để cung cấp hiệu suất vượt xa khả năng của một máy chủ.
Ví dụ:
dat_ve_moi
: Topic chứa tất cả các sự kiện đặt vé mới.thanh_toan_thanh_cong
: Topic chứa các sự kiện thanh toán thành công.huy_ve
: Topic chứa các sự kiện hủy vé.
👉 Mỗi Topic là một luồng dữ liệu độc lập và có tổ chức.
3. Broker – "Máy chủ" của Kafka
Broker là một server (máy chủ) vật lý hoặc ảo chạy dịch vụ Kafka. Mỗi Broker chịu trách nhiệm lưu trữ các Topic và xử lý việc gửi/nhận tin nhắn.
Một hệ thống Kafka thực tế thường có nhiều Broker hoạt động cùng nhau, tạo thành một Kafka Cluster (Cụm Kafka). Mục đích của việc này là:
Tăng tốc độ: Phân chia công việc cho nhiều máy.
Đảm bảo an toàn dữ liệu: Dữ liệu được sao lưu trên nhiều máy, tránh mất mát nếu một máy bị lỗi.
Dễ dàng mở rộng: Có thể thêm bớt Broker mà không ảnh hưởng hệ thống.
4. Consumer – "Người đọc" dữ liệu
Consumer là các ứng dụng hoặc hệ thống đọc dữ liệu từ Kafka. Chúng là các bộ phận xử lý trong hệ thống đặt vé của bạn:
Dịch vụ "Gửi Email Xác Nhận" sẽ đọc từ Topic
thanh_toan_thanh_cong
.Dịch vụ "Cập Nhật Chỗ Trống" cũng có thể đọc từ
thanh_toan_thanh_cong
vàhuy_ve
.Dịch vụ "Phân Tích Doanh Thu" sẽ đọc từ nhiều Topic để tổng hợp báo cáo.
Điểm đặc biệt của Consumer:
Consumer đọc dữ liệu theo thứ tự mà chúng được ghi vào Topic.
Kafka không xóa tin nhắn ngay sau khi Consumer đọc. Dữ liệu được giữ lại trong một thời gian (ví dụ: 7 ngày) để Consumer có thể đọc lại hoặc các Consumer khác cũng có thể đọc.
🔄 Dòng Chảy Dữ Liệu Trong Kafka (Đơn Giản)
+----------------+ +----------------+ +-----------------+
| Producer | -------> | Kafka Cluster | -------> | Consumer |
| (Gửi dữ liệu) | | (Lưu trữ & | | (Đọc & Xử lý) |
| | | phân phối) | | |
+----------------+ +----------------+ +-----------------+
Ví dụ đặt vé:
Khách hàng đặt vé: Ứng dụng web (Producer) gửi sự kiện "Đặt Vé Thành Công" tới Topic
dat_ve_moi
trong Kafka Cluster.Kafka lưu trữ: Tin nhắn "Đặt Vé Thành Công" được Kafka ghi lại một cách an toàn.
Xử lý tiếp theo:
Dịch vụ gửi email (Consumer) đọc tin nhắn này từ
dat_ve_moi
và gửi email cho khách.Dịch vụ cập nhật database (Consumer khác) cũng đọc tin nhắn này và ghi thông tin vé vào cơ sở dữ liệu.
💡 Tại Sao Kafka Mạnh Mẽ Đến Vậy?
Tốc độ cực nhanh (High Throughput): Kafka có thể xử lý hàng triệu tin nhắn mỗi giây, lý tưởng cho các hệ thống có lượng dữ liệu lớn.
Bền vững (Durability): Dữ liệu được lưu trữ an toàn trên đĩa của Broker và được sao lưu, đảm bảo không bị mất ngay cả khi có sự cố.
Chịu lỗi (Fault Tolerance): Nhờ cơ chế sao lưu (Replication), nếu một Broker bị lỗi, hệ thống vẫn tiếp tục hoạt động bình thường.
Mở rộng dễ dàng (Scalability): Bạn có thể dễ dàng thêm Broker để tăng khả năng xử lý mà không làm gián đoạn hệ thống.
Tách biệt (Decoupling): Các Producer và Consumer hoàn toàn độc lập với nhau. Chúng không cần biết về sự tồn tại của nhau, chỉ cần gửi/nhận qua Kafka. Điều này giúp hệ thống dễ dàng phát triển và bảo trì.
⚙️ Đi Sâu Hơn Về Kiến Trúc Kỹ Thuật
Để thực sự hiểu cách Kafka đạt được các tính năng trên, chúng ta cần tìm hiểu sâu hơn một chút về các khái niệm cốt lõi:
1. Partition – "Các mảnh" của Topic
Mỗi Topic được chia thành một hoặc nhiều Partition. Hãy tưởng tượng nếu Topic là một cuốn sổ ghi chép đơn hàng, thì Partition là các trang riêng biệt trong cuốn sổ đó, mỗi trang được ghi độc lập.
Lợi ích:
Song song hóa (Parallelism): Cho phép Kafka ghi và đọc dữ liệu cùng lúc từ nhiều Partition, tăng hiệu suất đáng kể.
Thứ tự tin nhắn: Trong một duy nhất Partition, các tin nhắn luôn được lưu giữ và đọc theo đúng thứ tự chúng được gửi. Tuy nhiên, giữa các Partition khác nhau thì thứ tự này không được đảm bảo.
Phân phối tin nhắn: Producer có thể chọn Partition để gửi tin nhắn (ví dụ: dùng ID khách hàng làm "key" để đảm bảo tất cả tin nhắn của cùng một khách hàng luôn vào cùng một Partition, từ đó giữ được thứ tự xử lý).
2. Offset – "Địa chỉ" của tin nhắn
Trong mỗi Partition, mỗi tin nhắn được gán một Offset duy nhất. Offset là một số nguyên tăng dần, giống như số thứ tự hoặc chỉ mục của tin nhắn trong Partition đó.
Vai trò quan trọng: Consumer sử dụng Offset để ghi nhớ vị trí cuối cùng đã đọc trong mỗi Partition. Khi Consumer xử lý xong một tin nhắn, nó sẽ "commit" (lưu lại) Offset của tin nhắn đó. Điều này giúp:
Nếu Consumer bị lỗi, khi khởi động lại, nó biết phải đọc tiếp từ đâu.
Các Consumer khác (trong cùng một nhóm) cũng biết vị trí đã được xử lý.
3. Replication – "Bản sao" để an toàn dữ liệu
Để dữ liệu không bị mất và hệ thống luôn hoạt động, mỗi Partition có thể được sao chép (replicate) trên nhiều Broker khác nhau.
Leader và Follower: Trong số các Broker chứa bản sao của một Partition, có một Broker được chỉ định làm Leader. Các Broker còn lại là Follower.
Producer chỉ ghi vào Leader.
Follower sao chép dữ liệu từ Leader để đảm bảo luôn đồng bộ.
Nếu Leader bị lỗi, một trong các Follower sẽ tự động được chọn làm Leader mới, đảm bảo dịch vụ không bị gián đoạn.
ISR (In-Sync Replicas): Là tập hợp các Follower đã sao chép và đồng bộ hoàn toàn với Leader. Kafka chỉ xác nhận rằng một tin nhắn đã được ghi thành công khi nó đã được ghi vào Leader và tất cả các Follower trong ISR. Điều này đảm bảo tính bền vững của dữ liệu.
4. Consumer Group – "Đội" Consumer xử lý song song
Consumer Group là một tập hợp các Consumer cùng làm việc để đọc dữ liệu từ một hoặc nhiều Topic. Chúng được thiết kế để chia sẻ và phân chia công việc đọc các Partition của một Topic.
Tăng hiệu suất & Cân bằng tải: Mỗi Partition trong một Topic sẽ chỉ được gán cho một Consumer duy nhất trong cùng một Consumer Group. Điều này giúp:
Tin nhắn trong một Partition được xử lý theo đúng thứ tự.
Công việc được phân chia đều giữa các Consumer trong Group.
Nếu bạn cần xử lý nhanh hơn, chỉ cần thêm Consumer vào Group.
Tính sẵn sàng cao (High Availability): Nếu một Consumer trong Group bị lỗi, các Partition mà nó đang xử lý sẽ tự động được chuyển giao cho các Consumer khác trong cùng Group (quá trình này gọi là rebalancing).
5. Zookeeper – "Bộ não" quản lý Cluster (Trong các phiên bản cũ)
Trong các phiên bản Kafka cũ hơn (trước Kafka 2.8), Apache Zookeeper là một thành phần riêng biệt dùng để quản lý trạng thái của Kafka Cluster. Nó giống như một người quản lý trung tâm lưu trữ thông tin về các Broker, Topic, Partition và vị trí đọc của Consumer Group.
- Lưu ý quan trọng: Từ Kafka 2.8 trở đi, Kafka đã tích hợp chức năng này trực tiếp vào trong Kafka Broker thông qua KRaft (Kafka Raft), giúp đơn giản hóa kiến trúc và loại bỏ sự phụ thuộc vào Zookeeper. Tuy nhiên, Zookeeper vẫn còn phổ biến trong nhiều hệ thống Kafka hiện có.
🧪 Ví dụ Kỹ Thuật (Node.js) – Minh họa Cơ Chế
Producer gửi tin nhắn (minh họa Key và Partitioning):
const { Kafka } = require("kafkajs");
const kafka = new Kafka({
clientId: 'flight-booking-producer',
brokers: ['localhost:9092'] // Địa chỉ Kafka broker
});
const producer = kafka.producer();
async function sendBookingEvent(bookingId, userId, flightDetails) {
await producer.connect();
await producer.send({
topic: 'flight-booking-events',
// Sử dụng bookingId làm key. Kafka sẽ dùng key này để quyết định gửi tin nhắn
// vào Partition nào, đảm bảo các sự kiện của cùng một bookingId luôn vào cùng một Partition.
messages: [{
key: bookingId.toString(),
value: JSON.stringify({ userId, flightDetails, type: 'BOOKING_CREATED', timestamp: new Date().toISOString() })
}]
});
console.log(`Sự kiện đặt vé cho ID ${bookingId} đã được gửi thành công.`);
await producer.disconnect();
}
// Ví dụ: Gửi sự kiện đặt vé cho các booking khác nhau
sendBookingEvent('B12345', 'user_abc', { flightNum: 'VN123', seat: '12A' })
.catch(e => console.error(`[Lỗi Producer] ${e.message}`, e));
sendBookingEvent('B67890', 'user_xyz', { flightNum: 'VN456', seat: '3B' })
.catch(e => console.error(`[Lỗi Producer] ${e.message}`, e));
Consumer đọc tin nhắn (minh họa Consumer Group và Offset):
const { Kafka } = require("kafkajs");
const kafka = new Kafka({
clientId: 'flight-booking-consumer',
brokers: ['localhost:9092']
});
// Các Consumer cùng tham gia một Consumer Group 'booking-processors'.
// Nếu có nhiều Consumer trong cùng group, chúng sẽ chia nhau các Partition.
const consumer = kafka.consumer({ groupId: 'booking-processors' });
async function processBookingEvents() {
await consumer.connect();
// Đăng ký đọc từ topic 'flight-booking-events'. 'fromBeginning: true' nghĩa là đọc từ tin nhắn đầu tiên nếu đây là lần đầu tiên Group này đọc.
await consumer.subscribe({ topic: 'flight-booking-events', fromBeginning: true });
await consumer.run({
eachMessage: async ({ topic, partition, message }) => {
const eventData = JSON.parse(message.value.toString());
console.log(`[Consumer ${process.pid}] Nhận sự kiện từ Topic ${topic}, Partition ${partition}, Offset ${message.offset}:`);
console.log(` Key: ${message.key.toString()}, Giá trị: ${JSON.stringify(eventData)}`);
// Giả lập thời gian xử lý sự kiện
await new Promise(resolve => setTimeout(resolve, 500));
// Sau khi xử lý thành công, Consumer sẽ tự động commit (lưu lại) Offset của tin nhắn này.
// KafkaJS client sẽ tự động quản lý việc này để Consumer biết vị trí tiếp theo cần đọc.
console.log(` Đã xử lý sự kiện cho Booking ID: ${message.key.toString()}`);
},
// Bạn có thể tùy chỉnh cách commit Offset thủ công nếu muốn kiểm soát chặt chẽ hơn (mặc định là tự động commit sau mỗi khoảng thời gian).
// autoCommit: false, // Nếu bạn muốn commit thủ công
// Để commit thủ công: await consumer.commitOffsets([{ topic, partition, offset: (parseInt(message.offset) + 1).toString() }]);
});
}
// Để thấy Consumer Group hoạt động, bạn có thể chạy 2 hoặc 3 cửa sổ terminal và chạy script này.
// Mỗi Consumer sẽ tự động được gán các Partition khác nhau của topic 'flight-booking-events' để xử lý song song.
processBookingEvents().catch(e => console.error(`[Lỗi Consumer] ${e.message}`, e));
📌 Tổng Kết Các Thành Phần Cốt Lõi
Thành phần | Vai trò & Lý do quan trọng |
Producer | Người gửi dữ liệu (message) tới Kafka. Được thiết kế để gửi nhanh và hiệu quả. |
Topic | Kênh logic chứa các luồng dữ liệu liên quan. Hoạt động như một nhật ký (log) bất biến, nơi dữ liệu được ghi tuần tự và không bị xóa ngay lập tức. |
Partition | Các "mảnh" nhỏ của Topic, cho phép Kafka ghi/đọc song song. Đảm bảo thứ tự tin nhắn chỉ trong phạm vi mỗi Partition. Đây là chìa khóa để mở rộng khả năng xử lý của Kafka. |
Offset | Chỉ mục duy nhất của một tin nhắn trong một Partition. Consumer dùng Offset để theo dõi vị trí đã đọc, giúp phục hồi và đọc lại dữ liệu. |
Kafka Broker | Máy chủ vật lý/ảo chạy Kafka, nơi lưu trữ các Partition và xử lý tất cả các yêu cầu từ Producer/Consumer. |
Replication | Cơ chế tạo bản sao của Partition trên nhiều Broker khác nhau (Leader và Follower). Đảm bảo dữ liệu không bị mất và hệ thống luôn hoạt động (tính chịu lỗi và sẵn sàng cao). |
Consumer Group | Tập hợp các Consumer làm việc cùng nhau để đọc từ một Topic. Chúng chia sẻ các Partition để xử lý song song và cân bằng tải, đồng thời cung cấp tính sẵn sàng cao khi một Consumer bị lỗi. |
Zookeeper/KRaft | Zookeeper (Kafka < 2.8): Hệ thống quản lý và điều phối cho Kafka Cluster (lưu trữ metadata, bầu chọn Leader). KRaft (Kafka >= 2.8): Cơ chế tự quản lý metadata trực tiếp trong Kafka, giúp đơn giản hóa kiến trúc. |
Apache Kafka là một nền tảng Event Streaming vô cùng mạnh mẽ, không chỉ để truyền tải tin nhắn mà còn để xây dựng các hệ thống xử lý dữ liệu thời gian thực, có khả năng mở rộng và chịu lỗi cực tốt.
Subscribe to my newsletter
Read articles from Eminel directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Eminel
Eminel
Hello, my name is Eminel a software engineer specializing in scalable software architecture, microservices, and AI-powered platforms. Passionate about mentoring, performance optimization, and building solutions that drive business success.