Intro to Apache Kafka Universe: Kafka คืออะไร ?

Burasakorn Sabyeying
Mils’ Blog
Published in
6 min readApr 17, 2022

ครั้งแรกของการเข้ามาสู่โลกของ Kafka เรารู้สึกเลยว่าหัวข้อนี้ไม่ใช่หัวข้อทั่วไป มีอะไรหลายอย่างข้างในนั้นเยอะมาก เลยอดไม่ได้ที่จะศึกษาและลองสรุปดู

บทความนี้เราจึงจะมาเล่าว่าเบสิคของ Apache Kafka ว่า Kafka คืออะไร ใช้เพื่ออะไรและมี concept ยังไง

Streaming Data คืออะไร

Streaming data หรือ event คือข้อมูลเล็กๆ (ขนาดสัก Kilobytes) และถูกสร้างขึ้นแบบต่อเนื่องๆ โดยพอมันไหลเข้ามาในระบบ เราก็นำข้อมูลมา process ทันที เพื่อนำข้อมูลนี้ไปใช้แบบ real-time หรือ near real-time ยกตัวอย่างเช่น

  • ข้อมูลการเงินใน stock market
  • ข้อมูล sensor จากรถขนส่ง เพื่อส่งไปหา streaming application ว่ารถถึงไหนแล้ว
  • ข้อมูลเวลาเราใช้ Lyft, Grab app พวกนี้จะหาว่าเราอยู่ locationไหน, มี traffic เป็นยังไง, คำนวนราคาแบบ real-time ณ เวลานั้น
  • ข้อมูล social media feeds
  • ข้อมูลของการเล่นของ playerในเกมที่นำมาวิเคราะห์แบบ real-time

Kafka คืออะไร

Apache Kafka คือ open-source distributed event-streaming platform โดยทุกวันนี้ Kafka ถูกนำไปใช้สร้าง real-time data pipeline และ streaming apps

Kafka นั้นถูกสร้างโดย LinkedIn แต่ปัจจุบันนี้กลายมาเป็น open source project ภายในปี 2011 แต่ตอนนั้นยังเป็น Apache Incubator ก่อน (เล่าง่ายๆคือ โปรเจคฟักไข่ ก่อนจะแปลงร่างเป็น Apache Software Foundation เต็มตัว) หนึ่งในผู้พัฒนาตอนนั้นซึ่งก็คือ Jay Kreps จึงตั้งชื่อ Kafka โดยตั้งตามนักเขียนที่ชื่อ Franz Kafka

จนตอนนี้ก็กลายมาเป็นหนึ่งใน Apache Software Foundation เต็มตัว เขียนด้วยภาษา Java และ Scala ที่ไว้เพื่อทำ high-throughput และ low latency platform สำหรับ real-time data

Kafka Core concept

streaming data หรือ event ที่เราเล่าเมื่อกี้ จะถูกสร้างโดย producer เพราะ producer เป็นคน write event data นี้ขึ้นมาแล้วส่งไป Kafka

Producer ดึงมาจาก external system อย่าง web server, components of applications , IoT devices, monitoring agents

ตัวอย่างเช่น มี user เข้ามา register ในเว็บก็นับเป็น event หนึ่ง หรือว่า weather sensor ที่ประกอบด้วยข้อมูลอุณหภูมิ, ความชื้น, แรงลม ก็นับเป็น event หนึ่ง พูดง่ายๆว่าเป็นใครก็ได้ที่สร้าง event นี้ขึ้นมา

Consumer มีหน้าที่ดึงข้อมูลมาใช้จาก producers และจะนำข้อมูลนี้ไปสู่ปลายทางอื่นๆ เช่น database, data lake, หรือ data analytics application พูดง่ายๆว่าเป็นคน consume data

ส่วน Kafka พระเอกหลักของเรา จะทำหน้าที่เป็นคนกลางคั่นระหว่าง producer และ consumer ซึ่ง Kafka system นี้จะเรียกกว่า Kafka Cluster

ใน Cluster จะมีหลาย nodes ซึ่ง node ใน Kafka เราจะเรียกว่า broker ซึ่งเป็นที่มาว่าทำไม Kafka ถูกจัดว่าเป็น distributed system

producer จะเป็นคน publish event ไปหา Kafka topics ซึ่ง consumer นั้นจะ subscribe จาก topic ที่ต้องการ โดยที่ topic นั้นจะมีหลาย consumer ก็ได้

ดังนั้น producer มักจะถูกเรียกว่า publisher และ consumer ก็จะเรียกว่า subscribers เหมือนกัน จึงมักจะจัดว่าทั้ง Kafka เป็น publish/subscribe messaging system

แล้ว Publish/subscribe messaging คืออะไรนะ?

Publish/subscribe messaging หรือ pub/sub messaging คือ pattern หนึ่งในการส่งข้อมูลจาก ผู้ส่ง (publisher) ไปหา ผู้รับ (subscriber) โดยจะส่งเป็น piece of data (message) แต่ความพิเศษคือ Publisher จะไม่ได้ระบุเป็นพิเศษว่า subscriber ต้องเป็นใคร และสามารถส่งไปหาหลาย subscriber ก็ได้

คราวนี้เราจะมาเจาะลึกแต่ละ Part ของ Kafka กัน

Kafka Topics

Producer จะเป็นคน write data ไปลง topics (จินตนาการว่า topic เหมือน file system)

  • Topics นั้นจะถูก identified ด้วย name
  • รับ any kind of message format
  • sequence of message จะเรียกว่า data stream
  • ไม่สามารถ query data ได้ แต่จะใช้ producer มา write data และ consumer มา read data

โดย topic จะถูกแบ่งเป็น partitions และในแต่ละ partition แต่ละ message ก็จะได้รับ id หรือเรียกว่า offset

ข้อควระวังคือ

  • ข้อมูลใน offset เดียวกัน ไม่ใช่ข้อมูลเดียวกัน กล่าวคือข้อมูล Partition 0 ที่ offset 1 ไม่ได้เท่ากับ partition 1 ที่ offset 1
  • ข้อมูลที่ถูก write ใน partition จะไม่สามารถเปลี่ยนแปลงได้ (immutable)
  • การเรียง order จะทำได้แค่ภายใน partition เท่านั้น

Kafka Producer

Producer จะเป็นคนส่ง message ไปหา topics และ message จะถูกกระจายไปตาม partition

ซึ่งการกระจายนี้ ทำได้ 2 แบบ คือจะเป็นกระจายแบบ round robin (partition 0, partition 1, ..) ก็ได้ หรือจองว่าต้องอยู่ partition เดิมก็ได้

ในขั้นตอนการเก็บข้อมูลนี้ Kafka จะมีสิ่งที่เรียกว่า Message Serializer คือการแปลงข้อมูลจาก objects มาเป็นข้อมูล bytes เพื่อที่จะส่ง bytes ไปหา consumer อีกที

Kafka Consumer

Consumer จะทำหน้าที่อ่านข้อมูลจาก topic ด้วยการ pull message มา

  • ความฉลาดของมันคือ consumer จะรู้ว่าควรอ่านข้อมูลจาก broker ไหน
  • วิธีอ่านของ consumer คือจะอ่านไล่จาก offset ต่ำไปสูงในแต่ละ partition
  • ถ้า broker failed ขึ้นมา consumer ก็จะรู้ว่าต้องกลับไปอ่านจากจุดไหน ด้วยการดูจาก offset
  • ในกรณีที่ consumer อ่านมากกว่า 1 partition จะไม่การันตีว่า order ของ message จะเรียงกันข้าม partition
  • เมื่อกี้ producer มีการทำ serializer ดังนั้นฝั่ง consumer ก็จะมี deserializer เช่นกัน โดยจะแปลงข้อมูลในรูป byte กลับมาเป็น objects

Consumer group

คราวนี้ Consumer มี Consumer group ที่จะรวม consumer หลายตัวเข้าด้วยกัน เพื่อช่วยกันอ่าน message ในแต่ละ partition

  • Kafka จะเก็บ offset ว่า consumer group อ่านถึงไหนแล้ว ชื่อ __consumer_offsetsอยู่ใน topic
  • เพราะด้วยเหตุนี้ ถ้า consumers ตาย มันก็จะกลับไปอ่านต่อจาก offsets เดิมได้ (committed offset)

Replication

เราได้เล่า core concept ในแต่ละ part ไปแล้ว ยังมีสิ่งที่น่าสนใจอีกเช่น

  • Topics จะมีการทำ replication factor ด้วย คือ partitions จะถูกเก็บไว้ที่ broker อื่น หาก broker นั้นตายขึ้นมา ก็ยังมีสำรองไว้อยู่อีก broker นึง
  • มี concept ของ Leader ในแต่ละ partitionจะมีเพียง 1 broker ที่เป็น leader สำหรับ partition นั้นๆ
  • เวลา producer จะส่งข้อมูลหา broker ก็จะส่งแต่ตัวที่เป็น leader แล้ว broker ตัวที่เป็น follower ก็จะ replicate ตาม leader ไป

Kafka vs RabbitMQ

ในทางเดียวกันหลายครั้งที่ Kafka มักถูกเปรียบเทียบกับ traditional messaging queue (Message broker) เสมอ เช่น RabbitMQ, IBM MQ, และ Microsoft Message Queue

Message broker นั้นมี concept คือทำให้ application, services ภายใน system เขาคุยกันและแลกเปลี่ยนข้อมูลกันได้ โดยทำหน้าที่เป็นคนคั่นระหว่าง sender กับ receiver โดยที่ sender ไม่ต้องรู้ว่าจะต้องส่งหา receiver ตัวไหน มีการทำ route, store, deliver message

นั้นไง ฟังดูเหมือนกับ Kafka เลย

แต่แตกต่างตรงที่ Kafka จะยังคงเก็บ message ไว้ช่วงระยะเวลาหนึ่ง (default คือ 7 วัน) ในขณะที่ RabbitMQ จะลบ message ทั้งๆที่ consumer (subscriber) ได้รับแล้ว ดังนั้นหากมีหลาย consumer ฝั่ง consumerของ Kafka จะได้รับ messageนั้นหมดหาก subscribe ไว้ แต่ถ้าเป็นฝั่ง consumer ของ RabbitMQ จะไม่ได้รับ message เดียวกัน เพราะมันถูกลบไปแล้ว

RabbitMQ จะใช้วิธี push message ไปหา consumer, คำนวนว่า consumer จะ process message ยังไง (broker ฉลาด, consumer ไม่คิดอะไรเลย)

ในขณะที่ Kafka จะให้ consumer มา pull message มากกว่า โดยที่ consumer จะรู้ว่าต้อง pull จากจุดไหน offset ที่เท่าไร (broker ไม่คิดอะไรเลย, consumer ฉลาด)

Kafka นั้นจะ scale แบบ horizontally (คือเพิ่ม node ขึ้นเรื่อยๆ) ในขณะที่ RabbitMQ จะ scale vertically (เพิ่ม performance ให้กับ node เดิม)

Kafka และ Zookeeper

Zookeeper เป็นคนที่ทำหน้า manage brokerให้กับ Kafka เช่น

  • ในการเลือกว่า broker ไหนจะเป็น leader
  • เก็บ config ของ topic และ permission
  • ส่ง notification ไปบอก Kafka ว่ามี topic เกิดใหม่, brokerตาย, broker กลับมาแล้ว etc.

แต่ Zookeeper นั้นอยู่คู่กับ Kafka มานาน แต่ Zookeeper จะไม่ได้ไปต่อ แถม Kafka ก็ develop ให้ตัวเองค่อยๆถอดการพึ่งพา ZooKeeper เรื่อยๆ

  • ใน Kafka ver. 2 จะทำงานไม่ได้หากไม่มี Zookeeper
  • ใน Kafka ver. 3 สามารถทำงานโดยไม่มี Zookeeper ได้ / Kafka in KRaft
  • ใน Kafka ver. 4 จะไม่มี Zookeeper อีกต่อไป

ทำไมถึงถอด ZooKeeper ออก?

เพราะเกิด bottleneck ในการ scaling ขึ้นมา ซึ่งมีหลายจุดมาก เช่น

  • Kafka cluster สร้าง partition ได้จำกัด (ได้แค่ 200,000 partitions)
  • Security ใน ZooKeeper ต่ำ
  • Metadata ใน Kafka กับ ZooKeeper ไม่ sync กัน

ยังมีอีก หากอยากศึกษารายละเอียด ลองอ่านใน KIP-500 และ Doc นี้ ต่อได้

ควรใช้ Zookeeper อยู่ไหม?

ณ ปัจจุบัน ตอนที่เรากำลังเขียนอยู่นี้ Kafka ver. 4 ยังไม่พร้อมสำหรับ production เขาจึงแนะนำว่ายังต้องมีอยู่ แต่สำหรับ best practice ในการ develop ก็ให้หลีกเลี่ยงการทำงานที่ based on ZooKeeper แทน

Kafka in KRaft mode

ปี 2019, Kafka แพลนจะย้าย Zookeeper ออก เพราะมีปัญหา scaling ในกรณีที่ Kafka clusters มีมากกว่า 100,000 partitions พอเอา Zookeeper ออก, Kafka ก็จะ scale ถึง millions partitions ได้ (โหดจัด)

และการจัดการที่ง่ายขึ้น พอสละออกไปแล้ว

ดังนั้นใน Kafka 3.x สร้าง Raft protocol (KRaft) เพื่อจะมาแทนที่ Zookeeper แทน

ถัดไป เราจะมาลองเล่น Kafka บนเครื่องของเรากัน

Install Kafka

Prerequisite:

- Docker

เราจะทดลองติดตั้ง Kafka แบบยังมี ZooKeeper อยู่ (แต่จะเลี่ยงการ rely on ZooKeeper ซึ่งจะอธิบายในส่วนถัดไป)

เราเอาไฟล์ docker-compose.yml จาก Bitnami

version: "3"
services:
zookeeper:
image: "bitnami/zookeeper:latest"
ports:
- "2181:2181"
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
kafka:
image: "bitnami/kafka:latest"
ports:
- "9092:9092"
environment:
- KAFKA_BROKER_ID=1
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://127.0.0.1:9092
- KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
- ALLOW_PLAINTEXT_LISTENER=yes
depends_on:
- zookeeper

แล้วก็ทำการเข้าไปใน container และเข้าไปสู่ path ที่เก็บไฟล์ binary ของ Kafka

$ docker exec -it <kafka_container> bash
$ cd /opt/bitnami/kafka/bin

Create Topics

เราจะลอง list ดูว่ามี topic ใน Kafka ไหม ด้วยคำสั่ง

kafka-topics.sh --bootstrap-server localhost:9092 --list

แน่นอนว่าตอนนี้เราไม่มี topic แน่ๆ

สังเกตว่าเราจะใช้ --bootstrap-server แทนที่จะเป็น --zookeeper เพื่อเป็นการบอกว่า Kafka Consumer เราจะไปหา offset จาก Kafka Brokers แทน zookeeper

ถัดมาเราจะสร้าง topic ด้วยคำสั่ง

kafka-topics.sh --bootstrap-server localhost:9092 --create --topic first_topic --partitions 3

Create Producer

สร้าง Producer ด้วยคำสั่ง

kafka-console-producer.sh --bootstrap-server localhost:9092 --topic first_topic

แล้วเราก็พิมพ์ message ลงไป

> Hello I'm Mils
> Hello world
>eiei
>

(ถ้าส่ง message เสร็จแล้วก็ ctrl+C เพื่อ exit ได้เลยแต่เราจะค้างไว้ก่อน)

Create Consumer

kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic first_topic

คราวนี้เราพิมพ์อะไรในproducer ก็จะเห็นได้ว่า message ถูกส่งไปยัง consumer ด้วย

Create Consumer Group

ให้ cancel ตัว consumer ตัวเมื่อกี้ แล้วคราวนี้เราจะสร้าง consumer group ด้วยคำสั่ง

kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic first_topic --group my-first-consumer-group

โดยเราจะรัน command นี้เป็น 3 หน้าต่างใน terminal เลย เพื่อบอกว่าเราจะสร้าง consumer 3 ตัวใน consumer group นี้

ตอนเราส่ง message จาก topic เดิม จะเห็นได้ว่าทุกครั้งที่ส่ง message มันจะถูกส่งไป consumer ตัวนั้น ตัวนี้ กระจายๆกัน

สรุป

ทุกคนได้รู้ Kafka ไปใช้ทำอะไรได้ และเข้าใจ core concept ของ Kafka ทั้ง Streaming data, Pub/sub messaging system และเข้าใจองค์ประกอบอย่าง Producer, Consumer, Topics, ZooKeeper และ KRaft

อีกทั้งเรายังทดลองติดตั้ง Kafka บน local โดยใช้คำสั่งต่างๆ โดยที่เราเสนอ command หลักๆในการใช้สร้าง topic, producer, และ consumer

ความจริงแล้ว Kafka นั้นประกอบด้วยหลายส่วนมาก (เราถึงบอกว่ามันคือ universe)

  • Kafka connect — เอาไว้ต่อจาก external system เพื่อจะย้ายข้อมูลจากที่นึงไปอีกที่
  • Kafka streams — เอาไว้ทำ processing แบบ streaming

ซึ่งไว้มีโอกาส เราจะมาเล่า 2 ตัวทีหลัง

ขอบคุณที่อ่านถึงตรงนี้ หากมีข้อเสนอแนะ สามารถติดต่อมายัง FACEBOOK PAGE : https://www.facebook.com/mesodiar ได้เลยนะคะ

ref:

  • Kafka: The Definitive Guide, 2nd Edition
  • https://www.conduktor.io/kafka/what-is-apache-kafka
  • https://aws.amazon.com/streaming-data/
  • https://aws.amazon.com/msk/what-is-kafka/
  • https://www.upsolver.com/blog/apache-kafka-use-cases-when-to-use-not
  • https://www.upsolver.com/blog/kafka-versus-rabbitmq-architecture-performance-use-case

--

--

Burasakorn Sabyeying
Mils’ Blog

Data engineer at CJ Express. GDE in Cloud. Women Techmakers Ambassador. Co-lead GDG Cloud Bangkok. Other channel > Mesodiar.com