Apache Kafka là gì? Làm thế nào để quản lý Schema & Avro Serialization trong Kafka? Nếu cũng có thắc mắc tương tự thì bài viết này là dành cho bạn.
Giới thiệu Apache Kafka
Apache Kafka là một nền tảng mã nguồn mở phân tán cho việc phát trực tuyến các sự kiện. Ban đầu được phát triển bởi LinkedIn và sau đó trở thành dự án mã nguồn mở của Apache vào năm 2011. Kafka xử lý dữ liệu streaming real-time, cho phép lưu trữ và xử lý dữ liệu luồng.
Với mô hình publish/subscribe, các ứng dụng gửi messages tới broker Kafka để xử lý bởi các ứng dụng khác (consumers).
Để hiểu rõ cụ thể Avro Schema và Serialization là gì, mọi người nên đọc qua bài Kafka hoạt động như thế nào của 200Lab để có được bức tranh khái quát Kafka là gì, Kafka giải quyết được những vấn đề gì trong thiết kế hệ thống thì có một câu hỏi đặt ra Producer và Consumer có mối liên hệ chặt chẽ thông qua những thành phần nào và điều gì xảy ra khi một trong hai thành phần trên phá vỡ quy ước định dạng ban đầu (có thể là thêm một field hoặc update field name, v..v).
Để hiểu thêm về Kafka cũng nhưng các kiến thức mới trong lập trình, bạn hãy thường xuyên theo dõi trang Blog và danh sách các khóa học của 200Lab nhé!
1. Avro là gì? Vì sao cần dùng Avro với Kafka
Hiện nay có rất nhiều định dạng dữ liệu như XML, JSON, ASN.1, v.v. Nhưng tại sao chúng ta chọn Avro? Tại sao định dạng này là một trong những lựa chọn tốt hơn cho dữ liệu luồng?
Avro là định dạng truyền dữ liệu mã nguồn mở giúp chúng ta trao đổi dữ liệu giữa các hệ thống. Một trong những điểm mạnh của Avro là xác định định dạng nhị phân của data cũng như ánh xạ nó vào ngôn ngữ lập trình mà ta chọn. Nó có mô hình dữ liệu giống JSON nhưng có thể được biểu diễn dưới dạng JSON hoặc dạng nhị phân
Có một số lý do khiến chúng ta cần xem xét về định dạng này:
- Nhanh
- Ánh xạ trực tiếp theo hai chiều đích và nguồn JSON, ngôn ngữ schema mở rộng trong pure JSON
- Có những liên kết ràng buộc cho nhiều ngôn ngữ lập trình vì thế ta có thể tạo ra các đối tượng Java giúp làm việc với dữ liệu sự kiện dễ dàng hơn
- Tương thích với việc phát triển dữ liệu theo thời gian.
2. Schema Registry: Hiểu rõ hơn về cơ sở dữ liệu Schema
Trong phạm vi bài viết này, 200Lab sẽ gọi tắt SR thay vì Schema Registry. SR sẽ lưu trữ các Schema Avro cho các Producer và Consumer Kafka. Hai thành phần trên sẽ sử dụng trình chuyển đổi cấu trúc dữ liệu (serialization) của Kafka để quản lý schema và các bản ghi sử dụng Avro
Trong quá trình tương tác với SR, Producer không cần phải gửi toàn bộ giá trị schema mà chỉ cần gửi ID schema. Consumer sẽ tiếp nhận giá ID và tìm kiếm trong kho lưu trữ schema của SR nếu nó chưa được lưu vào bộ nhớ cache. Chính vì vậy, chúng ta không cần phải gửi toàn bộ schema kèm với tập hợp bản ghi, điều này giúp tiết kiệm thời gian và tài nguyên
Cách tiếp nhận và xử lý schema giữa Producer và Consumer có một chút khác nhau. Với SR, quá trình kiểm tra tương thích sẽ được thực hiện và tiếp theo sau đó quá trình chuyển đổi dữ liệu sẽ diễn ra thông qua sự tiến hóa Schema Avro
3. Thay đổi dữ liệu dễ dàng với Avro Schema Evolution
Như đã đề cập phía trên đây là điểm đóng vai trò quan trọng trong quá trình chuyển đổi dữ liệu. Quá trình này chỉ xảy ra ở Consumer khi ta chuyển đổi dữ liệu byte sang các dữ liệu object (deserialization). Nếu một schema Avro được thay đổi sau khi dữ liệu đã được ghi vào kho lưu trữ bằng phiên bản cũ thì Avro có thể thực hiện sự tiến hóa schema khi ta cố gắng đọc dữ liệu
200Lab sẽ đưa ra một ví dụ cho các bạn dễ tiếp cận hơn:
{
"namespace": "com.200lab.avro.orders",
"type": "record",
"name": "Order",
"fields": [
{ "name": "orderid", "type": "string"},
{ "name": "amount", "type": "int"},
{ "name": "created",
"type": {
"type": "long",
"logicalType": "local-timestamp-millis"
}
},
{"name": "customer", "type": "string"},
{ "name": "discountamount", "type": "int", "default": 0},
]
}
Phiên bản trước của Order schema không có trường discountamount và sau đó đã được thêm trường này với giá trị mặc định là 0. Bây giờ, chúng ta có thể publish event với phiên bản mới của schema và Consumer vẫn sử dụng phiên bản trước đó không có trường discountamount
Producer sử dụng phiên bản mới của Order schema, tạo bản ghi com.200lab.avro.orders, đặt trường discountamount với giá trị là 2000 sau đó gửi nó đến topic Kafka my-topic-1. Consumer sẽ tiêu thụ các bản ghi từ chủ đề này với phiên bản trước đó nên nó loại bỏ trường discountamount trong quá trình giải mã
Ở một góc độ khác nếu ta tùy chỉnh trường discountamount không phải là tùy chọn (không có giá trị mặc định) SR có thể từ chối schema và Producer không thể sử dụng nó để publish event vào Kafka log
{ "name": "discountamount", "type": "int"}
4. Schema Compatibility: Đảm bảo dữ liệu luôn đồng nhất
Khi sử dụng Avro hoặc các định dạng khác, một trong những điều quan trọng nhất là quản lý các schema và sử dụng loại tương thích
Loại tương thích phù hợp sẽ xác định cách SR so sánh schema mới với các phiên bản trước của một schema, cho một chủ đề cụ thể. (Chủ đề được xác định là phạm vi mà các schema có thể phát triển). Chế độ tương thích mặc định của SR là BACKWARD. Để tìm hiểu tất cả các loại tương thích được mô tả chi tiết hơn trong phần này đây
Khi một schema được tạo lần đầu cho một chủ đề, nó sẽ được nhận một id duy nhất và version number, ví dụ, version 1. Khi schema được cập nhật (nếu nó pass qua kiểm tra tương thích), nó nhận một id duy nhất mới và số phiên bản tăng lên, ví dụ, phiên bản 2
SR cho phép chúng ta quản lý schema bằng những đầu endpoint sau:
Endpoint | Describe |
---|---|
GET /schemas/ids/{int: id} | Lấy định dạng schema theo id |
GET /schemas/types | Lấy tất cả loại schema trong Schema Registry |
GET /schemas/ids/{int: id}/versions | Lấy các version của sche được xác định theo id đầu vào |
... | ... |
5. Thực hành Kafka cùng 200Lab nhé!
Bài viết này sẽ hướng dẫn thực hành trên nền tảng ngôn ngữ Java và sử dụng Avro Gradle Plugin, cho phép chúng ta tạo Java POJO từ các Schema Avro.
- Trong file build.gradle, hãy thêm đoạn mã sau:
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.1'
id 'io.spring.dependency-management' version '1.1.0'
id "com.github.davidmc24.gradle.plugin.avro" version "1.3.0"
id 'idea' // (in which case you will be able to see a new task)
}
- Tiếp theo, các phụ thuộc sau cần được thêm vào:
dependencies {
implementation group: 'org.apache.avro', name: 'avro', version: '1.11.0'
implementation group: 'io.confluent', name: 'kafka-avro-serializer', version: '5.3.0'
implementation group: 'io.confluent', name: 'kafka-schema-registry-client', version: '5.3.0'
}
- Lưu ý, thêm dòng này vào phần "Repositories". Vì đối với kết nối HTTP không an toàn trong phiên bản Gradle 7+, chúng ta cần chỉ định một boolean allowInsecureProtocol là true cho MavenArtifactRepository closure, nếu không sẽ gặp lỗi
repositories {
mavenCentral()
maven {
allowInsecureProtocol = true
}
}
- Và cuối cùng trong file application.properties, ta cũng cần chỉ định group-id, serializer và schema-registry-url
spring.kafka.consumer.group-id=200lab-consumer-group-1
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=io.confluent.kafka.serializers.KafkaAvroDeserializer
spring.kafka.consumer.auto-offset-reset=latest
spring.kafka.consumer.properties.schema.registry.url=http://0.0.0.0:8081
6. Tổng kết
Trong bài viết này, chúng ta đã đi sơ lược về cách cấu hình và cài đặt khi publish một event định dạng Avro và consume message thông qua Kafka Schema Registry. Ngoài ra Avro còn cung cấp cách migrate schema, điều này thì hết sức quan trọng và cần thiết cho những kiến trúc lớn
Hy vọng bài viết này có thể giúp bạn có thể được nhiều kiến thức. Mọi người có thể tham khảo ở trang Github này
Giờ thì bạn đã hiểu sơ lược về Apache Kafka, cũng như cách quản lý Schema & Avro Serialization trong hệ thống rồi đấy! Hãy đọc thêm nhiều bài viết hay ho của 200Lab nhé!
Các bài viết có thể bạn sẽ thích:
Kafka cơ bản: Cách sử dụng Kafka với Confluent & Go
Flutter cơ bản: Điều cần biết khi lập trình ứng dụng đầu tiên
Web Developer là gì? Tìm hiểu về Web Development A - Z
Redux là gì? Tìm hiểu Redux cơ bản cho người mới bắt đầu
ReactJS là gì? Những điều bạn cần biết về ReactJS
Data Analysis trong Excel: Tổng hợp các kỹ thuật quan trọng
Cohort Analysis là gì? Ứng dụng phân tích Customer Retention
Bài viết liên quan
Cách Discord Lưu Trữ Hàng Nghìn Tỷ Tin Nhắn Với ScyllaDB
Dec 06, 2024 • 9 min read
Idempotent Consumer: Xử lý thông điệp trùng lặp trong Microservices
Dec 04, 2024 • 7 min read
Hướng dẫn tích hợp Redux và React Query trong dự án React Vite
Nov 22, 2024 • 8 min read
Giới thiệu Kiến trúc Backend for Frontend (BFF)
Nov 16, 2024 • 10 min read
Flask là gì? Hướng dẫn tạo Ứng dụng Web với Flask
Nov 15, 2024 • 7 min read
Webhook là gì? So sánh Webhook và API
Nov 15, 2024 • 8 min read