Kafka là một nền tảng distributed event streaming cho phép người dùng thu nhận và xử lý các event, message real time. Nó hoàn toàn có thể là xương sống cho ngành bán lẻ nơi mà khách hàng luôn cần thông tin và phản hồi ngay lập tức kể cả trong việc xem hàng, mua hàng hay thanh toán. Nó cũng có thể là phần hậu phương đủ lớn cho việc phân tích, xử lý data với các nền tảng IOT, big data. Vậy thì, để làm được những điều phi thường đó, kafka đã làm như thế nào?
Từ đâu mà Kafka được tạo nên?
Kafka được vận hành trên ý tưởng về async programing và message driven programing.
Ý tưởng về async programing sinh ra nhằm giải quyết bài toán khi có nhiều services trong 1 hệ thống cùng contact lẫn nhau, services A và B cùng gọi tới service C thì cái nào sẽ được giải quyết trước? Cũng như con người, khi 2 người cùng đưa ra yêu cầu tới một nhân viên chăm sóc KH, họ giải quyết cho KH A mất thời gian quá lâu sau đó tới giờ nghỉ trưa thì KH B có thể tới ngày hôm sau mới được chăm sóc, hoặc mất luôn KH B. Để giải quyết bài toán đó có 2 cách. Cách số 1: tăng thêm nhân viên chăm sóc KH. Điều này sẽ dẫn tới phối hợp 1 – 1 và làm cho công ty không scale được khi có thêm KH. Cách số 2 cũng là cách mà async programing based trên: cho phép xử lý song song cả 2 request bởi cùng 1 người. Điều này sẽ tránh được việc blocking request.
Cụ thể, async programming là cách tách biệt giữa request và response giữa các services:
Service A request tới service B
Service C request tới service B
Service B nhận 2 request, phản hồi lại với A và C là đã nhận request
Service B xử lý request A và C tùy cái nào tới trước sau đó response lại
Service A và C trong lúc chờ đợi sẽ tiếp tục gửi request tới service B và cuốn chiếu tracking response trở về.
Ý tưởng về asynchronous programming không phải toàn năng, nó sẽ gặp vấn đè nếu server chung (ví dụ như service B) quá tải và ngừng hoạt động. Lúc đó service C hay A sẽ phải retry gửi lại request và càng lúc càng bị đầy request lên. Vấn đề thứ 2, async giải quyết được 1 service nhận nhiều request, nhưng không tính tới tình huống 1 request gửi đi nhiều service khác nhau và track response. Đó là lúc có message driven programing ra đời.
Message-driven programing là lập trình điều hướng các message. Khi có nhiều request từ nhiều services có nhu cầu gửi tới nhiều servies khác, sẽ phải có 1 cái gì đó điều phối ở giữa để đảm bảo tất cả các request đều tới đích và nhận được response phù hợp. Client và server sẽ không giao tiếp trực tiếp với nhau nữa, 2 service cũng không thông trực tiếp với nhau mà sẽ qua 1 bên điều phối thứ 3 gọi là message broker.
Message broker bản thân như một môi giới trong bất kỳ ngành nghề gì, kết nối người mua - người bán một mặt hàng nào đó với nhau. Cùng 1 lúc 1 môi giới BĐS có thể đưa 10 KH khác nhau match với 10 căn nhà khác nhau thành công. Message broker cũng như vậy, tiếp nhận message từ client, từ services, từ KH, từ mọi nguồn và phân phối nó tới chỗ nó cần tới trong 1 system.
Trên thị trường có rất nhiều message broker như RabbitMQ, ActiveMQ thậm chí là Redis, nhưng, Kafka Apache có những unique selling point nếu so sánh với phần đông thị trường. Không chỉ phân phối được message (như mọi loại message queue), Kafka có các lợi thế sau nếu so sánh với các loại sản phẩm khác:
Đảm bảo việc gửi nhận không bị gián đoạn
Có cơ chế xử lý lỗi
Performance cao
High availability
Scalability
Dựa trên các ý tưởng trên, Kafka được phát triển ra và khẳng định sức mạnh của mình ở khoản performance mạnh mẽ trong việc điều phối data. Tiếp theo sẽ là cách mà kafka vận hành.
Các thuật ngữ trong Kafka
Để hiểu cách Kafka vận hành, có 2 loại khái niệm cần phải nắm được. Loại khái niệm đâu tiên chia theo chiều đi của message: message được gửi từ đâu tới đâu. Chiều thứ 2 là kafka có những component nào để vận hành. Khái niệm theo cách thức vận hành:
Topic:
Là các luồng data chạy trên kafka (bản chất là 1 chuỗi các message chạy liên tục). Các topic được chia thành các partition và các message được lưu thành các offset trên partition (xem mục partition và offset). Một topic sẽ có các đặc điểm sau:
Xếp hàng: Khi có event/message mới ghi vào topic, message/event đó sẽ được nối vào cuối log của topic.
Bất biến: Message/event được ghi vào sẽ không thể bị chỉnh sửa.
Tuần tự: Consumer (tham khảo ở dưới) sẽ đọc log bằng cách đi tìm các offset và đọc các entries ghi theo lượt tuần tự
Nhân bản: mỗi topic của kafka luôn là multi-producer và multi-subscriber: tức là cùng 1 lúc 1 topic có thể có nhiều nguồn gửi data vào và nhiều nguồn hứng data trong pipeline
Không giống như các hệ thống stream message khác, dữ liệu trên kafka sẽ không bị xóa đi sau khi đã truyền tới đích. Thay vào đó, kafka cho phép setup thời hạn expired data khi data đạt tới độ lớn hoặc một khoảng thời gian nhất định
Offset:
Message khi chảy vào 1 topic sẽ được lưu vào thành offset của 1 partition. 2 message khi chảy vào có thể ghi thày cùng 1 offset và cùng 1 offset có thể ghi ở nhiều partition khác nhau. Thứ tự của 1 offset chỉ được đảm bảo trong cùng 1 partition
Ví dụ: trong cùng partition 1, message có offset = 5 chắc chắn đến sau message có offset = 4.
Producer:
Là nơi tạo ra data/message/event cho các topics của Kafka (write). Các “producer” sẽ kiểm soát dữ liệu nào sẽ đi vào “partition” nào trong 1 topic. Rule phân bổ là theo round-robin để cân bằng tải hoặc theo rule set stream theo event key
Consumer:
Là nơi hứng các data/message/event sinh ra topics của Kafka (read). Thông thường, một consumer sẽ phải đọc 1 bản ghi sinh ra 1 cách tuần tự, tuy nhiên, kafka cho phép kiểm soát thứ tự bản ghi theo từng người dùng, dẫn tới việc mỗi consumer hoàn toàn có thể nhảy cóc thứ tự đọc nhằm đảm bảo tính real time của dữ liệu
VD: 1 consumer có thể tái sử dụng 1 bản ghi cũ để làm bản ghi mới hoặc có thể nhảy cóc qua các bản ghi đang sinh ra để đọc bản ghi gần nhất và ngay lập tức sử dụng bản ghi đó
Một Kafka consumer có thể vào đọc và sử dụng tài nguyên mà không ảnh hưởng tới cluster của các consumer khác.
Kết luận lại: multi-producers sẽ tạo (writre) ra nhiều message/event/data đẩy vào trong topic. Data đó sẽ được lưu thành các offset. Multi-consumer/subscriber vào check offsets để đọc (read), sau đó sẽ xử lý tiếp request.
Tiếp đến, kafka có các khái niệm bổ dọc theo tầng hệ thống:
Partition:
Các partition là các phần nằm bên trong 1 topic cho phép khi có nhiều offset cùng vào topic tại một thời điểm, các offset sẽ được chia cho nhiều partition để phân phối tới consumer.
Một partition sẽ độc lập với các partition khác. Số lượng partition cho mỗi topic thì tuỳ theo nhu cầu của ứng dụng do người dùng quy định.
Trong mỗi partition sẽ lưu nhiều offset, số lượng offset của mỗi partition có thể là khác nhau, tùy vào rule phân phối đã set vd theo round-robin hoặc event key rule.
Broker:
Message được lưu tại offset của partition, partition lưu ở trong topic. Các topic sẽ được lưu trên kafka broker
Bản thân 1 broker của kafka là 1 server nằm trong cụm cluster của kafka để lưu trữ dữ liệu
Thông thường theo mô hình truyền thống, 1 kafka server sẽ tương ứng với 1 cụm cluster dựng trên máy chủ vật lý. Khi server này chết thì toàn bộ dữ liệu sẽ mất cùng với nó luôn. Đây gọi là single-point failure. Cụm cluster Kafka sẽ phân tán các partition của cùng 1 topic ra nhiều broker nhất có thể để đảm bảo khi có 1 con broker chết, sẽ có con khác backup và giải quyết vấn đề không bị gián đoạn hệ thống
Tuy nhiên, việc chia broker và partition vẫn chưa giải quyết được hết single point failure do nếu data store trên 2 broker và cả 2 con cùng ngừng hoạt động thì bản chất vẫn là single point. Do đó, Kafka có khái niệm thứ 3: replication.
Replication:
Là bản sao của topic ở trên 1 broker sang 1 broker khác
VD: Có 3 topic và 3 brokers
Topic A lưu ở broker 1 và 2
Topic B lưu ở broker 2 và 3
Nếu broker 1 và 2 ngừng hoạt động thì Topic A cũng sẽ ngừng hoạt động
Do đó, kafka sẽ có replica topic A sang broker 3 để hệ thống vẫn stream bình thường.
Tương tác với topic B rồi C
Trên 1 broker sẽ có lưu 1 phần topic này và replica của topic kia để đảm bảo khi có 1 broker hoặc 1 cụm broker ngừng hoạt động thì vẫn sẽ có bản lưu ở 1 chỗ nào đó khác.
Kafka vận hành ra sao
Bên trên là một số các khái niệm cơ bản khi tìm hiểu về kafka. Tiếp theo, bài viết sẽ giới thiệu cụ thể cách kafka vận hành:
Input data from producers
Đầu vào của hệ thống nằm ở producer tạo ra (write) message gửi vào các topic trong cụm kafka cluster. Lập trình viên sẽ setup để producer write vào topic nào và dừng lại ở đó. Khi có message vào, producer tự động biết nên write vào broker nào và partition nào. Nếu ghi fail thì sẽ có cơ chế retry thành công
Việc “tự động” write được vào partition nào là do cơ chế round-robin của kafka: Có 3 brokers: message đầu tiên sẽ vào broker 1, message thứ 2 vào broker 2, message thứ 3 vào broker 3, message 4 sẽ vào broker 1,… Khi write vào partition, có cơ chế acks (acknowledgment) để báo producer biết message đã gửi thành công. Ack có 3 states:
Acks = 0: producer gửi message và không chờ phản hồi (có thể dẫn tới mất data)
Acks = 1: producer chờ tới khi nhận được phản hồi nhưng không lưu lại message sau khi write thành công. State này dẫn tới nếu broker đó chết, message sẽ mất theo
Acks = 2: producer chờ nhận phản hồi và chắc chắn phản hồi đã được lưu lại trên broker chính và toàn bộ các bản replica (sẽ có ảnh hưởng tới performance do phải chờ response write data thành công)
Processing data
Kafka implement message bằng cách chỉ định 1 replication bất kỳ làm leader. Cơ chế này là leader partition concept. Tại một thời điểm, mỗi partition có duy nhất 1 replication leader, các replication còn lại là ISR – In sync replica sẽ đồng bộ lại data đã ghi ở leader. Nếu replication leader ngừng hoạt động, hệ thống tự động chỉ định 1 ISR bất kỳ đứng lên làm leader. Việc chỉ định này được thông qua thuật toán của Kafka Zookeeper.
Với khái niệm replication như trên, 1 partition sẽ được nhân bản (replicate) lưu trên nhiều broker khác nhau. Vậy thì, khi producer write được data vào topic, data này bản thân được lưu ở đâu, lưu vào bản replica nào, theo rule gì?
Kafka Zookeeper là core dùng để quản lý metadata của kafka. Metadata này bao gồm:
Toàn bộ các action phát sinh trong hệ thống: CRUD topics, crud brokers, crud partitions, status,….
Brokers nào nằm ở cụm kafka cluster nào
Configuration, permissions của các topics
Việc kiểm soát các metadata này cho phép zookeeper tính toán để chỉ định các replication leader và ISR cũng như điều phối để các broker hoạt động một cách bình thường.
Khi các broker được điều hướng để hoạt động, các messages khi producers write xuống các topics sẽ được đảm bảo được tính tin cậy và bền vững. Các message được write thành các offset xếp theo thứ tự trên partition trong một topic lưu trên 1 broker và được replica sang các ISR khác. Tiếp theo, consumer sẽ vào để “sử dụng” các offset này.
Consume messages
Các consumer đọc message từ topic theo topic name. Tuy nhiên, như đã mô tả phía trên, 1 broker sẽ có các replica để store topic, vậy nên consumer sẽ đọc theo leader replication. Tiếp đến, nếu quá trình read gặp lỗi, kafka có cơ chế tự phục hồi để đảm bảo dữ liệu tới nơi toàn vẹn.
Việc đọc của consumer sẽ diễn ra tuần tự trong 1 partition, offset nào tới trước sẽ được đọc trước. Một consumer có thể đọc nhiều message trong nhiều partition khác nhau trong 1 topics. Do thứ tự message trong partition không thay đổi thứ tự nên khi read từ nhiều partition sẽ có những tình huống consumer đọc offset = 3 ở partition 1 - trước khi đọc được offset = 1 ở partition 3.
Tuy nhiên, kafka cho phép xử lý multi – multi, tức là multiple message được read bởi multiple consumer. Nếu như chỉ có 1 consumer đọc toàn bộ message của toàn bộ các partition thì sẽ xảy ra tình trạng quá tải. Vậy nên, kafka giải bài toán đó thông qua consumer group. 1 consumer group sẽ nhận toàn bộ data của các partition và chia cho các consumer bên trong quản lý. Mỗi consumer trong 1 group sẽ đọc toàn bộ data của một hoặc nhiều partition để đảm bảo messasge ordering. Một consumer có thể read message từ nhiều partition nhưng 1 partition sẽ không thể gửi message cho nhiều consumer trong 1 group. Cơ chế consumer group sinh ra nhằm đảm bảo không có consumer nào bị quá tải khi nhận message từ brokers.
Tổng kết lại message được sinh ra từ 1 producer, gửi topic. Topic được vận hành bởi các broker, trên các broker sẽ có replication leader của topic này và các ISR của topic khác. Việc phân phối chỉ định leader do Kafka Zookeeper phân phối. Message từ producer sẽ được ghi thành các offset trên partition trong topic. Consumer group nhận toàn bộ message từ partition và phân phối cho các consumer bên trong để sử dụng. Toàn bộ cơ chế trên chính là việc implement queue và topic trong message broker. Có 2 dạng phân phối message khi nói về message broker là queues (point-tpoint messaging) và topic (broadcast messaging)
Queue: là 1 dạng phân phối message quan hệ 1 – 1 (point to point messaging) giữa client và server (hoặc giữa các services). Mỗi message chỉ có 1 đầu vào và 1 điểm tới. Bản thân queueing trong kafka chính là việc message từ 1 topic A (bất kể có bao nhiêu partition) sẽ chỉ được gửi tới 1 consumer group B (bất kể có bao nhiêu consumer)
Broastcast messaging: một message được gửi tới nhiều địa chỉ, chỉ khi subscribe địa chỉ thì mới nhận được message đó. Trong kafka, khái niệm này chính là dạng 1 topic gửi message tới nhiều consumer groups. Consumer nào subscribe topic mới read được message đó.
Bên trên là toàn bộ các khái niệm cũng như basic cách kafka apache vận hành. Bằng cách cung cấp service Kafka, FPT Smart Cloud đồng thời cung cấp toàn bộ những ưu điểm của kafka apache như sự ổn định, tính bền vững và khả năng scaling cũng như performance mạnh mẽ của nền tảng này.
Đăng ký sử dụng thử miễn phí ngay: https://fptcloud.com/lien-he/
Nguyễn Quý Hiếu