Trong thế giới của các hệ thống phân tán và xử lý dữ liệu hiện đại, Apache Kafka (gọi tắt là Kafka) nổi lên như một nền tảng mạnh mẽ và được áp dụng rộng rãi để xử lý luồng dữ liệu thời gian thực (real-time) và xử lý sự kiện. Đặc biệt, Apache Kafka được ứng dụng nhiều trong các hệ thống microservices.
Đọc thêm: Giới thiệu kiến trúc Microservice
Cho dù bạn là developer (nhà phát triển), data engineer (kỹ sư dữ liệu), hay system architect (kiến trúc sư hệ thống), việc hiểu các khái niệm và chức năng cốt lõi của Kafka là điều cần thiết để tận dụng tối đa khả năng của nó.
Trong bài viết này, chúng ta sẽ đi sâu vào phân tích các thành phần của Kafka, khám phá cách thức hoạt động của Kafka, tìm hiểu ưu/nhược điểm và ứng dụng của Kafka trong cuộc sống.
1. Kafka là gì?
Apache Kafka là một nền tảng phân phối sự kiện phân tán mã nguồn mở được phát triển bởi Apache Software Foundation và được viết bằng Java và Scala.
“Apache Kafka is an open-source distributed event streaming platform used by thousands of companies for high-performance data pipelines, streaming analytics, data integration, and mission-critical applications.”
Nguồn: Trang chủ Kafka
Kafka ban đầu được phát triển bởi LinkedIn và sau đó được mở nguồn cho Quỹ phần mềm Apache (Apache Software Foundation) vào đầu năm 2011. Jay Kreps (đồng sáng lập và CEO của Confluent), Neha Narkhede (đồng sáng lập và cựu CTO của Confluent) và Jun Rao (đồng sáng lập Confluent) là các đồng sáng lập nền tảng phần mềm Kafka. Jay Kreps chọn cái tên “Kafka” (Franz Kafka - một nhà văn Đức vĩ đại thế kỷ 20) vì theo anh cái tên này có những đặc điểm phù hợp để đại diện cho công nghệ của họ.
Kafka được tạo ra để giải quyết những thách thức trong việc xử lý lượng dữ liệu khổng lồ trong thời gian thực (real-time), cho phép các ứng dụng xuất bản (publish), đăng ký (subscribe), lưu trữ (store) và xử lý (process) các luồng bản ghi (streaming event) một cách hiệu quả.
2. Apache Kafka hoạt động như thế nào? Các thành phần chính trong Apache Kafka
Chúng ta sẽ cùng tìm hiểu cách hoạt động của Kafka thông qua việc phân tích các thành phần chính trong Kafka.
2.1. Kafka Events
Một Kafka event (sự kiện) ghi lại thực tế rằng "điều gì đó đã xảy ra" trên thế giới hoặc trong doanh nghiệp của bạn. Nó còn được gọi là record (bản ghi) hoặc message (thông điệp). Trong nhiều tài liệu về Kafka, việc sử dụng 3 thuật ngữ event, record và message mang nghĩa tương đương nhau.
Việt đọc và ghi dữ liệu trong Kafka thực hiện thông qua event. Mỗi event chứa một key (khoá), value (giá trị) và metadata (nếu có).
Ví dụ về một event chứa key, value và metadata (timestamp):
2.2. Kafka Topics
Các event được tổ chức và lưu trữ lâu dài trong các topics (chủ đề). Có thể coi một topic ví như một thư mục (folder) trong hệ thống tập tin (filesystem), còn mỗi event là một tập tin (file) nằm bên trong thư mục đó.
Hình dưới 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ủ.
2.3. Kafka Brokers và Kafka Clusters
Kafka được chạy dưới dạng một Kafka cluster gồm một hoặc nhiều Kafka server có thể mở rộng trên nhiều data center hoặc cloud. Một Kafka server này tạo thành lớp lưu trữ, được gọi là Kafka broker.
Brokers chịu trách nhiệm quản lý bộ lưu trữ, xử lý các yêu cầu đọc và ghi cũng như sao chép dữ liệu trên toàn cluster (cụm).
Trong mỗi cluster sẽ có một broker sẽ hoạt động như một cluster controller (bộ điều khiển cụm), chịu trách nhiệm chỉ định phân vùng cho brokers và theo dõi lỗi của brokers.
2.4. Kafka Partitions và Kafka Replication
Các topic được chia thành các partitions (phân vùng), là đơn vị cơ bản của tính song song và phân phối trong Kafka. Mỗi phân vùng được lưu trữ trên một broker duy nhất và nhiều phân vùng cho phép mở rộng quy mô theo chiều ngang và cải thiện hiệu suất.
Mỗi event trong một partition được gán một offset duy nhất, bắt đầu từ 0 cho event đầu tiên trong partition và tăng dần một cho mỗi event tiếp theo. Offset được sử dụng để xác định vị trí của event trong một partition.
Kafka đảm bảo độ bền của dữ liệu bằng cách sao chép dữ liệu (replication) trên nhiều brokers. Mỗi partition có thể có một hoặc nhiều replica (bản sao) trên các brokers khác nhau, ngăn ngừa mất dữ liệu trong trường hợp broker lỗi.
Mỗi partition có một broker được chỉ định làm leader, nắm quyền sở hữu partition đó, trong khi các brokers còn lại lưu trữ các replicas (bản sao) của phân vùng đó được gọi là followers.
Nếu leader broker xảy ra lỗi, một trong những followers có dữ liệu cập nhật sẽ được chọn làm leader mới. Quá trình này được gọi là leader failover (chuyển đổi dự phòng lãnh đạo), nhằm đảm bảo tính khả dụng của dữ liệu.
2.5. Kafka Producers
Kafka Producer là một client appication (ứng dụng khách), publish (xuất bản) event vào một topic cụ thể trong Kafka và luôn ghi vào leader broker. Theo mặc định, producers không quan tâm tới event được ghi ở partition nào mà sẽ publish đều event trên tất cả partition của một topic. Trong vài trường hợp, một producer sẽ gửi trực tiếp event tới các partition cụ thể.
Producers kết nối tới Kafka Brokers thông qua giao thức mạng TCP. Đây là kết nối hai chiều (bi-directional connection).
Hình vẽ dưới đây mô tả tổng quan về các thành phần trong Kafka producers.
Quá trình gửi event từ Kafka producers tới Kafka brokers bao gồm 4 bước.
- Bước 1: Tạo ProducerRecord
Producer publish event tới Kafka bằng cách tạo một ProducerRecord, trong đó bắt buộc có topic và value, và không bắc buộc có partition và key.
- Bước 2: Serializer
Trước khi gửi ProducerRecord qua network, producer sẽ serialize (tuần tự hoá) key và value thành ByteArrays (mảng các bytes).
- Bước 3: Xác định số partitions
Sau bước Serializer, dữ liệu được gửi tới một Partitioner. Nếu chúng ta chỉ định sẵn partition thì partitioner sẽ trả về partition được chỉ định, còn không thì partitioner sẽ chọn một partition dựa vào ProducerRecord key.
- Bước 4: Brokers xử lý events và trả về kết quả cho producers
Khi biết event cần được gửi tới topic và partition nào, producer sẽ thêm event vào một lô các bản ghi (a batch of records). Từ đó, chúng sẽ được gửi đi cùng topic và partition. Một thread độc lập chịu trách nhiệm gửi các lô bản ghi tới Kafka brokers phù hợp.
Broker sẽ gửi lại một response khi nhận được events. Nếu event được ghi thành công vào Kafka, broker sẽ gửi lại một object chứa RecordMetadata bao gồm topic, partition và offset của record bên trong partition. Còn nếu không thành công thì broker trả về lỗi. Khi producer nhận được lỗi, event sẽ được gửi lại (retry) vài lần trước khi bỏ cuộc và trả về lỗi.
2.6. Kafka Consumers
Kafka consumer là một client application (ứng dụng khách), subscribe (đăng ký) một hoặc nhiều Kafka topics và đọc các bản ghi theo thứ tự chúng được tạo ra. Consumers đọc dữ liệu theo thời gian thực hoặc theo tốc độ của riêng chúng, cho phép các ứng dụng phản ứng với các sự kiện khi chúng xảy ra.
Consumers kết nối tới Kafka Brokers thông qua giao thức mạng TCP. Đây là kết nối hai chiều (bi-directional connection).
Consumers hoạt động trong một consumer group, làm việc cùng nhau để xử lý dữ liệu từ các partitions, cung cấp khả năng mở rộng theo chiều ngang và cho phép nhiều phiên bản của cùng một ứng dụng xử lý dữ liệu đồng thời.
Khi một consumer group đọc các event từ các partitions, chúng ta có 3 trường hợp xảy ra như sau:
- Trường hợp 1: Consumer group có số consumers nhỏ hơn số partitions của một topic.
- Trường hợp 2: Consumer group có số consumers bằng số partitions của một topic.
- Trường hợp 3: Consumer group có số consumers lớn hơn số partitions của một topic.
Trường hợp 1: Consumer group có số consumers nhỏ hơn số partitions của một topic.
Consumer 1 và 2 lần lượt đọc các event từ 4 partitions của Topic T1.
Trường hợp 2: Consumer group có số consumers bằng số partitions của một topic.
Nếu ta thêm 2 consumers vào Consumer Group 1, số consumer bằng với số partition, mỗi consumer sẽ đọc event từ một partition tương ứng. Trong trường hợp consumers thực hiện các hoạt động có độ trễ cao như ghi vào database hoặc tính toán tốn thời gian trên dữ liệu, tăng số consumers lên sẽ chia tải, giúp việc đọc dữ liệu từ một topic nhanh hơn.
Trường hợp 3: Consumer group có số consumers lớn hơn số partitions của một topic.
Chúng ta không nên để số consumer nhiều hơn số partition của một topic vì một vài consumers có thể trở nên nhàn rỗi do tất cả partitions đều bận rộn, dẫn tới event bị bỏ sót hoặc chưa đọc.
2.7. Zookeepers
ZooKeeper là một dịch vụ điều phối phân tán mã nguồn mở thuộc Apache Software Foundation, nhằm duy trì thông tin cấu hình, đặt tên, cung cấp đồng bộ hóa phân tán và cung cấp dịch vụ nhóm trong hệ thống phân tán. Cái tên ZooKeeper lấy cảm hứng từ câu nói "Điều phối các hệ thống phân tán giống như làm việc trong sở thú" ("Because Coordinating Distributed Systems is a Zoo")
ZooKeeper is a distributed, open-source coordination service for distributed applications.
Nguồn: Trang chủ ZooKeeper
ZooKeepers được sử dụng để quản lý, lưu trữ metadata của clusters và điều phối các consumers.
Lưu ý: Apache Kafka phiên bản 2.8.0 (phát hành vào tháng 5 năm 2021), Kafka đã giới thiệu một tính năng gọi là chế độ KRaft (Apache Kafka Raft) cho phép Kafka hoạt động mà không phụ thuộc vào ZooKeeper.
Đọc thêm: KIP-500: Replace ZooKeeper with a Self-Managed Metadata Quorum
2.8. Kafka APIs
Apache Kafka APIs bao gồm 5 loại APIs chính:
- Kafka Producer API cho phép các ứng dụng gửi luồng dữ liệu đến các Topics trong Kafka clusters.
- Kafka Consumer API cho phép các ứng dụng đọc luồng dữ liệu từ các Topics trong Kafka clusters.
- Kafka Streams API cho phép chuyển đổi luồng dữ liệu từ Topic đầu vào sang Topic đầu ra.
- Kafka Connect API cho phép triển khai các trình kết nối liên tục kéo từ một số hệ thống nguồn hoặc ứng dụng vào Kafka hoặc đẩy từ Kafka vào một số hệ thống hoặc ứng dụng background.
- Kafka Admin API cho phép quản lý và kiểm tra các Topics, Brokers và các đối tượng Kafka khác.
3. Các tích hợp nâng cao dùng với Kafka
3.1. Kafka Connect
Kafka Connect là một công cụ để truyền dữ liệu có thể mở rộng và đáng tin cậy giữa Kafka và các hệ thống khác. Kafka Connect có thể nhập toàn bộ cơ sở dữ liệu hoặc thu thập số liệu từ tất cả các máy chủ ứng dụng của bạn vào các chủ đề Kafka, làm cho dữ liệu có sẵn để xử lý luồng với độ trễ thấp.
3.2. Kafka Streams
Kafka Streams là một thư viện máy khách để xây dựng các ứng dụng và microservices có dữ liệu đầu vào và đầu ra được lưu trữ trong các Kafka clusters. Nó kết hợp sự đơn giản của việc viết và triển khai các ứng dụng Java và Scala tiêu chuẩn ở phía client (máy khách) với những lợi ích của server-side cluster (công nghệ cụm phía máy chủ) của Kafka.
3.3. Schema Registry
Schema registry là một quá trình máy chủ độc lập (standalone server process) chạy trên một thiết bị bên ngoài Kafka brokers. Schema registry cung cấp một kho lưu trữ tập trung để quản lý và xác thực các schemas cho dữ liệu event trong topic, đồng thời tuần tự hóa và giải tuần tự hóa dữ liệu qua mạng.
Schema Registry cung cấp API cho phép producers và consumers dự đoán liệu event mà họ sắp sản xuất hoặc tiêu thụ có tương thích với các phiên bản trước hay không. Nếu một consumer đọc một event không tương thích với version nó kỳ vọng, Schema registry sẽ yêu cầu ngừng sử dụng event này.
4. Ưu điểm của Kafka
- Scalability (Khả năng mở rộng): Kiến trúc phân tán của Kafka cho phép khả năng mở rộng liền mạch. Nó có thể xử lý khối lượng lớn dữ liệu và tăng thông lượng dữ liệu bằng cách thêm nhiều brokers và partitions.
- Durability (Độ bền): Kafka đảm bảo độ bền của dữ liệu thông qua sao chép. Dữ liệu được sao chép trên nhiều brokers, ngăn ngừa mất dữ liệu ngay cả khi các brokers bị lỗi. Bên cạnh đó, bằng cách tuân thủ nguyên tắc Append only commit log, Kafka commit log cung cấp độ bền dữ liệu, khả năng chịu lỗi và xử lý thông báo hiệu quả.
- Real-time processing (Xử lý theo thời gian thực): Kafka cho phép truyền và xử lý dữ liệu theo thời gian thực, làm cho nó phù hợp với các ứng dụng yêu cầu phân tích và truyền dữ liệu có độ trễ thấp.
- Open-source (Mã nguồn mở): Kafka là phần mềm mã nguồn mở, cung cấp quyền tự do sửa đổi, tùy chỉnh và mở rộng chức năng của nó để đáp ứng các yêu cầu cụ thể. Kafka có thể được sử dụng mà không phải trả phí cấp phép, giúp giảm chi phí liên quan đến phần mềm độc quyền. Kafka chạy được đa nền tảng và tích hợp được với nhiều công cụ, thư viện khác nhau, tạo thành một ecosystem lớn.
- Long polling: Mặc dù long polling không phải là một tính năng tích hợp sẵn của Kafka, nhưng khái niệm này có thể được áp dụng cho cách Kafka consumers tương tác với các Kafka brokers để đạt được mức tiêu thụ dữ liệu hiệu quả.
5. Nhược điểm của Kafka
- ZooKeepers dependency (Phụ thuộc vào Zookeepers): Trong các phiên bản cũ hơn của Kafka, có sự phụ thuộc vào Apache ZooKeeper để điều phối cụm, làm tăng thêm độ phức tạp và chứa các điểm lỗi tiềm ẩn.
- Complexity (Cài đặt, cấu hình và quản lý phức tạp): Bản chất phân tán của Kafka có thể gây ra sự phức tạp trong thiết lập, cấu hình và quản lý, đòi hỏi chuyên môn để triển khai và bảo trì hiệu quả. Bên cạnh đó, học cách sử dụng hiệu quả Kafka và các thành phần hệ sinh thái của nó có thể cần thời gian và công sức, đặc biệt đối với người dùng mới sử dụng hệ thống phân tán.
- Resource requirement (Yêu cầu tài nguyên): Quản lý Kafka clusters yêu cầu tài nguyên phần cứng đáng kể, bao gồm bộ nhớ, dung lượng lưu trữ và dung lượng mạng.
6. Ứng dụng của Kafka
- Activity tracking (Theo dõi hoạt động): Ứng dụng đầu tiên của Kafka ở LinkedIn là theo dõi hoạt động của người dùng. Người dùng tương tác với ứng dụng, hệ thống sẽ ghi lại thông tin như số lượt xem, số lượt click hoặc thông tin người dùng tạo trên hồ sơ của họ. Những thông tin này được gửi tới một hoặc nhiều topic, để các ứng dụng backend xử lý sau đó.
- Metrics and Logging (Số liệu và ghi nhật ký): Kafka có thể xử lý dữ liệu thông lượng cao từ các ứng dụng và hệ thống khác nhau, làm cho nó có giá trị để theo dõi và phân tích hiệu suất của hệ thống.
- Stream processing (Xử lý luồng): Kafka thường được sử dụng để truyền và xử lý dữ liệu thời gian thực, chẳng hạn như tương tác của người dùng, đọc cảm biến và giao dịch tài chính.
- Event Sourcing (Tìm nguồn sự kiện): Các kiến trúc hướng sự kiện được hưởng lợi từ khả năng nắm bắt và lưu trữ các sự kiện của Kafka đại diện cho các thay đổi trạng thái, cho phép triển khai tìm nguồn sự kiện đáng tin cậy và có thể mở rộng.
- Data Integration (Tích hợp dữ liệu): Kafka đóng vai trò là cầu nối giữa các hệ thống khác nhau, cho phép tích hợp dữ liệu trơn tru giữa các ứng dụng và cơ sở dữ liệu.
- Commit Log: Kafka có thể phục vụ như một loại commit log bên ngoài cho hệ thống phân tán. Log giúp sao chép dữ liệu giữa các nodes và hoạt động như một cơ chế đồng bộ hóa lại để các nodes bị lỗi khôi phục dữ liệu của chúng. Tính năng log compaction (nén nhật ký) trong Kafka giúp hỗ trợ việc sử dụng này, tương tự như Apache BookKeeper.
7. Tổng kết
Apache Kafka đã tái định nghĩa cách các tổ chức xử lý luồng dữ liệu (data streaming) và xử lý sự kiện (event processing). Kiến trúc phân tán, khả năng chịu lỗi và khả năng mở rộng biến Kafka trở thành một công cụ mạnh mẽ để quản lý những thách thức của dữ liệu thời gian thực. Từ việc thu thập và phân tích các tương tác của người dùng đến xây dựng các ứng dụng hướng sự kiện, khả năng của Kafka là rất lớn và có tác động mạnh mẽ.
Khi bạn tiếp tục hành trình của mình trong thế giới xử lý dữ liệu hiện đại, việc hiểu các khái niệm và khả năng cốt lõi của Kafka chắc chắn sẽ là một tài sản, giúp bạn khai thác tiềm năng của các luồng dữ liệu thời gian thực.
Bài viết liên quan
Grafana Loki là gì? So sánh Loki và Elasticsearch
Nov 16, 2024 • 6 min read
Webhook là gì? So sánh Webhook và API
Nov 15, 2024 • 8 min read
Two-Factor Authentication (2FA) là gì? Vì sao chỉ Mật khẩu thôi là chưa đủ?
Nov 13, 2024 • 7 min read
ELK là gì? So sánh hiệu suất giữa ELK và PLG
Nov 06, 2024 • 9 min read
Docker Best Practices: Tối ưu Dung lượng Docker Image
Oct 30, 2024 • 8 min read
SQL Injection là gì? Những cách phòng ngừa SQL Injection
Oct 25, 2024 • 10 min read