Kafka คืออะไร? พร้อมตัวอย่างการใช้งานด้วยภาษา Golang
Kafka เป็น Message Queue ที่ทำหน้าที่เป็นตัวกลางสำหรับการรับส่งข้อมูลจาก Producer ไปยัง Consumer หรือเปรียบเสมือนพนักงานส่งของที่รับข้อมูลจากหลายแหล่ง (Producer) รวบรวม จัดระเบียบ และส่งต่อข้อมูลไปยังผู้รับปลายทางที่ต้องการ (Consumer) โดยที่ Kafka มีจุดเด่นในการจัดการข้อมูลขนาดใหญ่ที่เข้ามาอย่างรวดเร็วและต่อเนื่องโดยทำงานในลักษณะของ Distributed System ที่ช่วยให้สามารถขยายระบบได้ตามต้องการ นอกจากนี้ Kafka ยังมีคุณสมบัติที่ช่วยให้ข้อมูลมีความคงทนและเชื่อถือได้ โดยการเก็บข้อมูลในรูปแบบของ Log ที่สามารถเรียกใช้ย้อนหลังได้ตามต้องการ

องค์ประกอบหลักของ Kafka
- Producer: เป็นผู้ที่ส่งข้อมูลเข้าสู่ Kafka อาจจะเป็นแอปพลิเคชันหรือบริการที่ผลิตข้อมูล
- Consumer: เป็นผู้ที่รับข้อมูลจาก Kafka และนำข้อมูลไปใช้งานต่อ อาจจะเป็นแอปพลิเคชันหรือบริการที่ต้องการข้อมูลจาก Kafka
- Broker: เป็นเซิร์ฟเวอร์ที่ทำหน้าที่จัดการและเก็บข้อมูลจาก Producer และส่งข้อมูลไปให้ Consumer
- Topic: เป็นช่องทางหรือหมวดหมู่สำหรับการจัดเก็บและส่งข้อมูลใน Kafka ผู้ใช้งานสามารถกำหนด Topic ได้ตามต้องการ
การทำงานเริ่มต้นจากการที่ Producer ส่งข้อมูลไปยัง Topic ที่ได้กำหนดไว้ใน Kafka หลังจากนั้น ตัว Kafka Broker จะทำการเก็บข้อมูลที่ได้จาก Producer เป็นรูปแบบ Log ไฟล์ที่จัดเก็บอยู่ใน Topic นั้น ๆ หากมีการขอดึงข้อมูลจาก Consumer จาก Topic ที่ต้องการ Kafka Broker จะเป็นคนส่งข้อมูลให้ Consumer โดยสามารถรองรับการส่งข้อมูลแบบ Real-Time หรือแบบ Batch ก็ได้
การใช้งาน Kafka ในงานต่าง ๆ
- เว็บไซต์ขายสินค้า: เมื่อลูกค้าสั่งซื้อสินค้า ข้อมูลการสั่งซื้อจะถูกส่งไปยัง Kafka ในฐานะ Producer จากนั้นระบบ Back-End ของเว็บไซต์จะทำหน้าที่เป็น Consumer ดึงข้อมูลการสั่งซื้อจาก Kafka ไปประมวลผลต่อ เช่น การจัดส่งสินค้า การอัปเดตสต็อก และการแจ้งเตือนการชำระเงิน
- แพลตฟอร์มโซเชียลมีเดีย: โพสต์และข้อความต่าง ๆ บนโซเชียลมีเดียสามารถถูกส่งไปยัง Kafka ในฐานะ Producer จากนั้นระบบวิเคราะห์ข้อมูลจะทำหน้าที่เป็น Consumer ดึงข้อมูลจาก Kafka ไปวิเคราะห์เพื่อดู Sentiment ของผู้ใช้ และติดตามเทรนด์ต่าง ๆ
ข้อดีของการใช้ Kafka
- Kafka ถูกออกแบบมาให้สามารถจัดการกับข้อมูลปริมาณมากและรวดเร็วได้
- Kafka มีระบบการจัดการข้อมูลที่ทำให้มั่นใจได้ว่าข้อมูลจะไม่สูญหาย และสามารถส่งข้อมูลไปยัง Consumer ได้อย่างถูกต้อง
- การใช้ Kafka ช่วยให้การสื่อสารระหว่างบริการเป็นแบบ Asynchronous ซึ่งทำให้ระบบไม่ต้องรอการตอบสนองทันที ลดปัญหาการรอคอยและเพิ่มประสิทธิภาพในการทำงานของระบบโดยรวม
ตัวอย่างการใช้ Kafka ในภาษา Golang

เตรียมความพร้อม
ก่อนอื่นเลย Kafka จำเป็นต้องใช้ Zookeeper หรือ Distributed Service ตัวอื่น ๆ ร่วมด้วย เนื่องจาก Zookeeper ทำหน้าที่สำคัญในการจัดการและประสานงานระหว่าง Broker ต่าง ๆ ในคลัสเตอร์ของ Kafka โดยในการใช้งานสามารถสร้างไฟล์ docker-compose.yml แล้วก็ run ผ่าน Docker Compose
version: '3.9'
services:
zookeeper:
image: zookeeper
container_name: zookeeper
volumes:
- .zookeeper:/data
kafka:
image: bitnami/kafka
container_name: kafka
ports:
- 9092:9092
volumes:
- .kafka:/bitnami/kafka/data
environment:
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092
- KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
depends_on:
- zookeeper
docker compose up
go get github.com/Shopify/sarama
ตัวอย่างการส่งข้อความ (Producer)
package main
import (
"log"
"github.com/Shopify/sarama"
)
func main() {
// กำหนด Kafka Brokers
brokers := []string{"localhost:9092"}
// สร้าง Producer
producer, err := sarama.NewSyncProducer(brokers, nil)
if err != nil {
log.Fatalf("Failed to start producer: %v", err)
}
defer producer.Close()
// สร้างข้อความที่จะส่ง
message := &sarama.ProducerMessage{
Topic: "example-topic",
Value: sarama.StringEncoder("Hello, Kafka!"),
}
// ส่งข้อความ
partition, offset, err := producer.SendMessage(message)
if err != nil {
log.Fatalf("Failed to send message: %v", err)
}
log.Printf("Message sent to partition %d with offset %d\n", partition, offset)
}
ตัวอย่างการรับข้อความ (Consumer)
package main
import (
"log"
"github.com/Shopify/sarama"
)
func main() {
// กำหนด Kafka brokers
brokers := []string{"localhost:9092"}
// สร้าง Consumer
consumer, err := sarama.NewConsumer(brokers, nil)
if err != nil {
log.Fatalf("Failed to start consumer: %v", err)
}
defer consumer.Close()
// เลือกพาร์ติชั่นที่ต้องการอ่าน
partitionConsumer, err := consumer.ConsumePartition("example-topic", 0, sarama.OffsetNewest)
if err != nil {
log.Fatalf("Failed to start partition consumer: %v", err)
}
defer partitionConsumer.Close()
// อ่านข้อความจากพาร์ติชั่น
for message := range partitionConsumer.Messages() {
log.Printf("Message received: %s\n", string(message.Value))
}
}
ทดสอบผลลัพธ์


