Topic và Partition
Last updated
Last updated
Trong Kafka, Topic có thể được hiểu như một luồng dữ liệu hoặc một kênh chứa các bản ghi (records) thuộc cùng một chủ đề hoặc mục đích. Producer sẽ gửi dữ liệu vào Topic và Consumer sẽ đọc dữ liệu từ Topic để xử lý.
Đặc điểm của Topic:
Tên duy nhất: Mỗi topic có một tên duy nhất trong toàn bộ cluster Kafka.
Phân loại dữ liệu: Topic được sử dụng để tổ chức và phân loại dữ liệu theo logic nghiệp vụ. Ví dụ, bạn có thể có các topic như orders
, user_activities
, sensor_data
, v.v.
Immutable append-only log: Dữ liệu sau khi được ghi vào topic sẽ không thể bị thay đổi hoặc xóa (trừ khi cấu hình retention policy cho phép). Các bản ghi mới luôn được thêm vào cuối topic.
Trong Kafka, một topic là đơn vị logic để tổ chức dữ liệu, nhưng để xử lý dữ liệu hiệu quả trong một hệ thống phân tán, dữ liệu của topic cần được chia nhỏ thành các partition để tăng khả năng xử lý song song. Dưới đây là các lý do chính:
Phân tán dữ liệu (Data Distribution)
Mục đích: Khi dữ liệu được gửi đến một topic, nếu tất cả dữ liệu chỉ được lưu trữ trong một đơn vị (ví dụ: một file hoặc một máy chủ), hệ thống sẽ nhanh chóng bị quá tải khi lưu lượng tăng. Việc chia topic thành nhiều partition cho phép dữ liệu được phân phối trên nhiều máy chủ (broker) trong cluster Kafka.
Cách hoạt động:
Mỗi partition là một phần độc lập của topic và được lưu trữ trên một broker riêng biệt (hoặc nhiều broker nếu có replication).
Ví dụ: Topic orders với 3 partition (orders-0, orders-1, orders-2) có thể được phân phối trên 3 broker khác nhau. Điều này giúp tránh tình trạng một broker duy nhất phải xử lý toàn bộ dữ liệu.
Lợi ích
Cân bằng tải (Load Balancing): Dữ liệu được chia đều, tránh bottleneck trên một máy chủ.
Khả năng mở rộng (Scalability): Khi lượng dữ liệu tăng, bạn có thể thêm broker và phân phối thêm partition mà không làm gián đoạn hệ thống.
Tăng khả năng xử lý song song (Parallel Processing)
Mục tiêu: Để xử lý dữ liệu nhanh chóng, đặc biệt trong các ứng dụng thời gian thực, Kafka cần tận dụng tối đa tài nguyên tính toán. Partition là chìa khóa để đạt được điều này.
Cách hoạt động:
Mỗi partition là một đơn vị dữ liệu độc lập, và Kafka cho phép nhiều consumer trong một consumer group đọc dữ liệu từ các partition khác nhau đồng thời.
Trong một consumer group, mỗi partition chỉ được gán cho một consumer duy nhất tại một thời điểm. Do đó, số lượng partition quyết định mức độ song song tối đa.
Ví dụ: Topic user-activity có 4 partition và một consumer group với 4 consumer. Mỗi consumer sẽ đọc từ một partition, cho phép xử lý dữ liệu song song trên 4 luồng.
Lợi ích:
Hiệu suất cao: Nhiều consumer cùng làm việc một lúc, tăng tốc độ xử lý dữ liệu.
Tối ưu tài nguyên: Tận dụng sức mạnh của nhiều CPU hoặc máy chủ để xử lý các luồng dữ liệu lớn.
Tuy nhiên, số partition không phải càng nhiều càng tốt bởi các lý do sau:
Quản lý metadata phức tạp:
Mỗi partition trong Kafka đều cần được quản lý bởi hệ thống. Khi số lượng partition tăng lên, lượng metadata (thông tin về partition, broker, leader, v.v.) cũng tăng theo, gây áp lực lên hệ thống.
Ví dụ: Nếu bạn có 1000 partition, Kafka cần theo dõi vị trí của từng partition, leader của từng partition, và các bản sao (replica) của chúng. Điều này làm tăng độ phức tạp và tiêu tốn tài nguyên.
Độ trễ khi rebalance consumer group:
Khi một consumer group thực hiện rebalance (ví dụ: thêm hoặc bớt consumer), Kafka cần phân bổ lại các partition cho các consumer. Số lượng partition càng lớn, thời gian rebalance càng lâu.
Ví dụ: Nếu bạn có 1000 partition và 10 consumer, Kafka cần tính toán để phân bổ 1000 partition cho 10 consumer. Quá trình này sẽ tốn thời gian và có thể gây gián đoạn trong quá trình xử lý dữ liệu.
Tiêu tốn tài nguyên hệ thống:
Mỗi partition cần tài nguyên để lưu trữ dữ liệu, quản lý offset, và xử lý các yêu cầu đọc/ghi. Nếu số lượng partition quá lớn, hệ thống sẽ tiêu tốn nhiều CPU, RAM, và ổ cứng hơn.
Cách chọn số lượng partition phù hợp
Dựa trên throughput yêu cầu:
Nếu bạn cần xử lý nhiều dữ liệu cùng lúc, bạn có thể tăng số lượng partition để tăng khả năng song song hóa.
Ví dụ: Nếu bạn cần xử lý 10,000 message/giây và mỗi consumer chỉ xử lý được 1,000 message/giây, bạn cần ít nhất 10 partition.
Dựa trên số lượng consumer:
Số lượng partition nên lớn hơn hoặc bằng số lượng consumer trong nhóm để đảm bảo mỗi consumer có partition để xử lý.
Ví dụ: Nếu bạn có 5 consumer, bạn nên có ít nhất 5 partition.
Cân bằng giữa hiệu suất và độ phức tạp:
Không nên tạo quá nhiều partition nếu không cần thiết. Thông thường, số lượng partition từ 10 đến 100 là phù hợp cho hầu hết các trường hợp.
Thứ tự trong một partition
Trong một partition, Kafka đảm bảo thứ tự của các message. Các message được lưu trữ theo thứ tự thời gian và được gán một offset duy nhất. Kafka chỉ đảm bảo thứ tự của những message đã được ghi vào log (tức là những message đã "tới" Kafka). Giả sử nếu message A được Producer 1 gửi trước message B của Producer 2 nhưng do vấn đề mạng mà B lại tới trước thì B vẫn được ghi trước vào Topic.
Ví dụ: Trong partition P0, các message có offset 1, 2, 3,... sẽ được đọc theo đúng thứ tự đó. Trường hợp nhiều Producer được minh hoạ bên dưới, có thể 0 được Producer 1 gửi đi trước nhưng vẫn có thể tới sau 1 của Producer 2.
Thứ tự giữa các partition
Kafka không đảm bảo thứ tự toàn cục giữa các partition khác nhau trong cùng một topic.
Ví dụ: Nếu topic "A" có 3 partition (P0, P1, P2), một message trong P1 có thể được gửi trước một message trong P0, nhưng consumer có thể đọc message từ P0 trước P1. Ví dụ 2 có thể được gửi trước 3 nhưng consumer đọc Partition P0 có thể đọc 3 trước consumer đọc 2 của Partition P1.
Vậy giả sử trường hợp ta cần đảm bảo nghiêm ngặt các thứ tự của các message liên quan đến 1 chủ thể nào đó. Ví dụ: khi một đơn hàng được tạo, hệ thống cần xử lý các sự kiện theo đúng thứ tự:
Tạo đơn hàng (Order Created)
Thanh toán đơn hàng (Order Paid)
Vận chuyển đơn hàng (Order Shipped)
Hoàn thành đơn hàng (Order Completed)
Nếu thứ tự bị đảo lộn (ví dụ: đơn hàng được vận chuyển trước khi thanh toán), hệ thống sẽ gặp lỗi nghiêm trọng.
Hướng giải quyết:
Sử dụng 1 partition duy nhất
Tạo một topic có 1 partition duy nhất.
Tất cả các message về đơn hàng sẽ được gửi vào partition này.
Consumer sẽ đọc message từ partition này theo đúng thứ tự.
Ưu điểm:
Đảm bảo thứ tự tuyệt đối của tất cả các message.
Nhược điểm:
Chỉ có 1 consumer có thể đọc dữ liệu, dẫn đến hiệu suất thấp nếu lượng dữ liệu lớn.
Sử dụng key để đảm bảo thứ tự
Tạo một topic với nhiều partition.
Sử dụng key để đảm bảo tất cả các message liên quan đến cùng một đơn hàng được gửi vào cùng một partition.
Ví dụ: Key là order_id.
Ưu điểm:
Đảm bảo thứ tự của các message cùng key (cùng order_id
).
Có thể xử lý song song nhiều đơn hàng khác nhau (mỗi đơn hàng được xử lý bởi một partition riêng).
Nhược điểm:
Chỉ đảm bảo thứ tự trong phạm vi một key (một đơn hàng), không đảm bảo thứ tự giữa các key (giữa các đơn hàng khác nhau).
Một số ví dụ cần thứ tự nghiêm ngặt
Hệ thống tài chính:
Ví dụ: Xử lý giao dịch ngân hàng. Thứ tự các giao dịch (nạp tiền, rút tiền) phải được đảm bảo để tránh sai sót.
Hệ thống đặt hàng:
Ví dụ: Đơn hàng phải được tạo trước khi thanh toán, và thanh toán trước khi vận chuyển.
Hệ thống log hoặc audit:
Ví dụ: Các sự kiện audit (kiểm tra) phải được ghi lại theo đúng thứ tự thời gian để đảm bảo tính minh bạch.