Home > Blog > tech

Stream Processing คืออะไร? สอน Kafka Streams, Apache Flink สำหรับ Real-time Data 2026

streaming event processing kafka flink guide
Stream Processing Kafka Flink Guide 2026
2026-04-11 | tech | 3600 words

ในยุคที่ข้อมูลถูกสร้างขึ้นทุกมิลลิวินาที ไม่ว่าจะเป็นการคลิกบนเว็บไซต์ การทำธุรกรรมทางการเงิน ข้อมูลจากเซ็นเซอร์ IoT หรือ Log จากเซิร์ฟเวอร์ การประมวลผลแบบ Batch ที่รันวันละครั้งไม่เพียงพออีกต่อไป ธุรกิจต้องการวิเคราะห์และตอบสนองต่อข้อมูลแบบ Real-time เพื่อตรวจจับการทุจริต แนะนำสินค้าแบบทันที หรือแจ้งเตือนความผิดปกติก่อนที่จะสายเกินไป

บทความนี้จะพาคุณเข้าใจ Stream Processing ตั้งแต่แนวคิดพื้นฐาน ไปจนถึงเครื่องมือหลักอย่าง Kafka Streams และ Apache Flink รวมถึง Pattern ที่ใช้ในการออกแบบ Real-time Data Pipeline สำหรับระบบจริง

Batch vs Stream Processing

ก่อนจะเข้าใจ Stream Processing ต้องเข้าใจความแตกต่างกับ Batch Processing ก่อน ทั้งสองเป็นวิธีการประมวลผลข้อมูลที่ต่างกันโดยสิ้นเชิง

คุณสมบัติBatch ProcessingStream Processing
ข้อมูลชุดข้อมูลที่เก็บไว้แล้ว (bounded)ข้อมูลที่ไหลเข้ามาต่อเนื่อง (unbounded)
เวลาประมวลผลนาทีถึงชั่วโมงมิลลิวินาทีถึงวินาที
ตัวอย่างสรุปยอดขายรายวันตรวจจับ Fraud ทันที
เครื่องมือSpark Batch, Hadoop MapReduceKafka Streams, Flink, Spark Streaming
ความซับซ้อนต่ำกว่าสูงกว่า (state, ordering, fault tolerance)
Latencyสูงต่ำมาก

Stream Processing ไม่ได้มาแทนที่ Batch Processing ระบบจริงมักใช้ทั้งสอง เรียกว่า Lambda Architecture หรือ Kappa Architecture ขึ้นอยู่กับการออกแบบ

แนวคิดพื้นฐานของ Stream Processing

Event Time vs Processing Time

นี่คือแนวคิดที่สำคัญที่สุดใน Stream Processing:

การเลือกใช้ Event Time หรือ Processing Time มีผลต่อความถูกต้องของผลลัพธ์อย่างมาก ตัวอย่างเช่น ถ้าคุณนับจำนวนการคลิกต่อนาที การใช้ Processing Time อาจทำให้ Event ที่เกิดขึ้นในนาทีเดียวกันถูกนับคนละนาทีได้ เพราะ Event มาถึงช้า

Watermarks

Watermark คือกลไกที่บอกระบบว่า เราไม่น่าจะได้รับ Event ที่มี Event Time ก่อนเวลานี้อีกแล้ว เป็นวิธีจัดการกับ Event ที่มาสาย (Late Event) ถ้า Event มาหลังจาก Watermark ผ่านไปแล้ว ระบบจะจัดการตามนโยบายที่ตั้งไว้ อาจจะทิ้ง อาจจะ Update ผลลัพธ์ หรืออาจจะส่งไป Side Output

Windows

Window คือการแบ่ง Stream ที่ไม่มีที่สิ้นสุดออกเป็นกลุ่มย่อยที่จัดการได้ มีหลายแบบ:

State Management

Stream Processing ที่มีประโยชน์จริงต้องเก็บ State ไว้ได้ เช่น การนับจำนวน การรวม Aggregate หรือการ Join ข้อมูลจากหลาย Stream ระบบที่ดีต้องจัดการ State ให้ Fault-tolerant หมายความว่าถ้า Node ล่ม State จะไม่หาย และสามารถ Recover ได้

Apache Kafka Streams

Kafka Streams เป็น Library สำหรับ Java/Kotlin ที่ช่วยให้ประมวลผล Stream ได้โดยใช้ Kafka เป็น Backbone ข้อดีเด่นคือ ไม่ต้องมี Cluster แยก แค่เขียน Java Application ธรรมดาที่อ่านจาก Kafka Topic ประมวลผล แล้วเขียนกลับไป Kafka Topic อื่น

สถาปัตยกรรม Kafka Streams

Kafka Streams ทำงานเป็น Library ภายใน Application ของคุณเอง ไม่ต้องติดตั้ง Framework แยก ไม่ต้องมี Cluster Manager ทำให้ Deploy ง่ายมาก สามารถ Scale ด้วยการเพิ่ม Instance ของ Application แล้ว Kafka จะจัดการ Partition Rebalancing ให้อัตโนมัติ

KStream vs KTable

// Kafka Streams Example (Java)
StreamsBuilder builder = new StreamsBuilder();

// อ่าน Stream จาก Topic
KStream<String, String> orders = builder.stream("orders");

// กรองเฉพาะ Order ที่มูลค่าสูง
KStream<String, String> highValue = orders.filter(
    (key, value) -> parseAmount(value) > 10000
);

// นับจำนวน Order ต่อลูกค้า (Windowed)
KTable<Windowed<String>, Long> orderCounts = orders
    .groupByKey()
    .windowedBy(TimeWindows.ofSizeWithNoGrace(Duration.ofMinutes(5)))
    .count();

// เขียนผลลัพธ์ไป Topic ใหม่
highValue.to("high-value-orders");

// สร้างและ Start Application
KafkaStreams streams = new KafkaStreams(builder.build(), props);
streams.start();

Joins ใน Kafka Streams

Kafka Streams รองรับ Join หลายแบบ ซึ่งเป็นสิ่งที่ยากมากใน Stream Processing:

Exactly-Once Semantics

Kafka Streams รองรับ Exactly-once Processing ซึ่งหมายความว่า แม้จะมี Failure เกิดขึ้น ทุก Record จะถูกประมวลผลเพียงครั้งเดียวเท่านั้น ไม่ซ้ำ ไม่ขาด เปิดใช้งานง่ายมากแค่ตั้งค่า processing.guarantee=exactly_once_v2

Apache Flink

Apache Flink เป็น Distributed Stream Processing Framework ที่ออกแบบมาเพื่อ Stream Processing โดยเฉพาะตั้งแต่แรก (ไม่ได้เริ่มจาก Batch แล้วเพิ่ม Streaming ทีหลังเหมือน Spark) ทำให้มีสถาปัตยกรรมที่เหมาะกับ Stream Processing อย่างแท้จริง

สถาปัตยกรรม Flink

Flink มีสถาปัตยกรรมแบบ Master-Worker:

// Flink DataStream API Example (Java)
StreamExecutionEnvironment env =
    StreamExecutionEnvironment.getExecutionEnvironment();

// อ่านจาก Kafka
DataStream<String> stream = env.addSource(
    new FlinkKafkaConsumer<>("events", new SimpleStringSchema(), props)
);

// Parse และ Filter
DataStream<Event> events = stream
    .map(json -> parseEvent(json))
    .filter(event -> event.getType().equals("purchase"));

// Windowed Aggregation
DataStream<Result> result = events
    .keyBy(Event::getUserId)
    .window(TumblingEventTimeWindows.of(Time.minutes(5)))
    .aggregate(new PurchaseAggregator());

// เขียนไป Kafka
result.addSink(
    new FlinkKafkaProducer<>("results", new ResultSerializer(), props)
);

env.execute("Purchase Analytics");

Flink SQL / Table API

Flink รองรับ SQL สำหรับ Stream Processing ทำให้สามารถเขียน Query แบบ SQL บน Real-time Data ได้เลย ไม่ต้องเขียน Java Code ซับซ้อน เหมาะสำหรับ Data Analyst ที่คุ้นเคยกับ SQL

-- Flink SQL Example
-- สร้าง Table จาก Kafka Topic
CREATE TABLE orders (
    order_id STRING,
    user_id STRING,
    amount DECIMAL(10,2),
    order_time TIMESTAMP(3),
    WATERMARK FOR order_time AS order_time - INTERVAL '5' SECOND
) WITH (
    'connector' = 'kafka',
    'topic' = 'orders',
    'properties.bootstrap.servers' = 'localhost:9092',
    'format' = 'json'
);

-- Real-time Aggregation
SELECT
    user_id,
    TUMBLE_START(order_time, INTERVAL '5' MINUTE) AS window_start,
    COUNT(*) AS order_count,
    SUM(amount) AS total_amount
FROM orders
GROUP BY
    user_id,
    TUMBLE(order_time, INTERVAL '5' MINUTE)
HAVING SUM(amount) > 10000;

Spark Structured Streaming (เปรียบเทียบ)

Apache Spark Structured Streaming เป็นอีกทางเลือกหนึ่งที่นิยม ทำงานบนพื้นฐานของ Micro-batch โดยจะรวบรวม Event เป็นกลุ่มเล็กๆ แล้วประมวลผลเป็น Batch ข้อดีคือใช้ Spark API ที่คุ้นเคย แต่ Latency จะสูงกว่า Flink ที่ประมวลผลทีละ Event

# Spark Structured Streaming (Python)
from pyspark.sql import SparkSession
from pyspark.sql.functions import window, count, sum

spark = SparkSession.builder.appName("StreamApp").getOrCreate()

# อ่านจาก Kafka
df = spark.readStream     .format("kafka")     .option("kafka.bootstrap.servers", "localhost:9092")     .option("subscribe", "orders")     .load()

# Windowed Aggregation
result = df     .withWatermark("timestamp", "5 minutes")     .groupBy(window("timestamp", "5 minutes"), "user_id")     .agg(count("*").alias("order_count"),
         sum("amount").alias("total_amount"))

# เขียนไป Console (หรือ Kafka, Database)
result.writeStream     .outputMode("update")     .format("console")     .start()     .awaitTermination()

Kafka Streams vs Flink: เปรียบเทียบแบบละเอียด

คุณสมบัติKafka StreamsApache Flink
ประเภทLibrary (ไม่ต้องมี Cluster)Framework (ต้องมี Cluster)
DeployJAR ธรรมดา, ContainerYARN, K8s, Standalone Cluster
Input SourceKafka เท่านั้นKafka, Kinesis, Files, JDBC, และอื่นๆ
Exactly-Onceรองรับ (Kafka transactions)รองรับ (Checkpoint)
SQL Supportไม่มี (ใช้ ksqlDB แยก)Flink SQL ครบถ้วน
State ManagementRocksDB, In-memoryRocksDB, Heap, พร้อม Savepoint
Throughputสูงสูงมาก (Millions events/sec)
Latencyต่ำ (ms)ต่ำมาก (sub-ms possible)
Batch Processingไม่รองรับรองรับ (Unified batch+stream)
Learning Curveง่ายกว่ายากกว่า
เหมาะกับKafka-centric, ทีมเล็กComplex processing, ข้อมูลหลาย Source
เลือกอะไรดี? ถ้าข้อมูลอยู่ใน Kafka หมดแล้ว และต้องการความง่ายในการ Deploy ใช้ Kafka Streams ถ้าต้องการ SQL ต้องการอ่านจากหลาย Source หรือต้องการ Throughput สูงมาก ใช้ Flink

Stream Processing Patterns

Event-Time Join

การ Join สอง Stream ตาม Event Time เช่น Match Impression event กับ Click event ภายใน 30 นาทีหลัง Impression เพื่อคำนวณ Click-through Rate แบบ Real-time Pattern นี้ซับซ้อนเพราะ Event อาจมาไม่เรียงลำดับ ต้องใช้ Watermark และ Window ร่วมกัน

Sessionization

การจัดกลุ่ม Event เป็น Session ของผู้ใช้แต่ละคน โดยกำหนดว่า Session จะจบเมื่อไม่มี Activity ภายในเวลาที่กำหนด เช่น 30 นาที ทำให้สามารถวิเคราะห์พฤติกรรมผู้ใช้แบบ Real-time ได้ ใช้ Session Window ของ Flink หรือ Kafka Streams ในการ Implement

Anomaly Detection

ตรวจจับความผิดปกติแบบ Real-time เช่น ธุรกรรมที่ผิดปกติ Server ที่ใช้ CPU สูงเกินไป หรือ Login ที่น่าสงสัย วิธีทำคือเก็บ State ของ Baseline ปกติ แล้วเปรียบเทียบ Event ใหม่กับ Baseline ถ้าเบี่ยงเบนเกินค่าที่กำหนดก็แจ้งเตือน สำหรับระบบที่ต้องตรวจจับ Pattern ซับซ้อน อาจใช้ Machine Learning Model ร่วมกับ Stream Processing

Materialized View

สร้าง View ของข้อมูลที่ Update แบบ Real-time เช่น Dashboard ที่แสดงยอดขายล่าสุด จำนวน Active Users หรือ Inventory ปัจจุบัน ทำได้โดยใช้ KTable ใน Kafka Streams หรือ Flink SQL ที่ Write ผลลัพธ์ลง Database ที่ Query ได้เร็ว เช่น Redis หรือ Elasticsearch

Real-time Analytics Pipeline Architecture

สถาปัตยกรรมของ Real-time Analytics Pipeline ที่ใช้ในระบบจริงประกอบด้วยหลายส่วน:

Data Sources              Message Broker         Stream Processor         Sink
┌──────────┐             ┌──────────┐           ┌──────────────┐        ┌──────────┐
│ Web App  │────────────>│          │           │              │───────>│ Database │
│ Mobile   │────────────>│  Apache  │──────────>│  Flink /     │───────>│ Redis    │
│ IoT      │────────────>│  Kafka   │           │  Kafka       │───────>│ Elastic  │
│ Server   │────────────>│          │           │  Streams     │───────>│ S3       │
└──────────┘             └──────────┘           └──────────────┘        └──────────┘
                              │                        │
                              │                   State Store
                              │                  (RocksDB/Checkpoint)
                              │
                    Schema Registry
                    (Avro/Protobuf)

แต่ละส่วนมีบทบาทดังนี้:

  1. Data Sources: ส่ง Event เข้า Kafka Topic ผ่าน Kafka Producer
  2. Schema Registry: จัดการ Schema ของข้อมูล เพื่อให้ Producer และ Consumer ใช้ Format เดียวกัน
  3. Stream Processor: อ่าน Event จาก Kafka ประมวลผล แล้วเขียนผลลัพธ์ไป Sink
  4. State Store: เก็บ State ที่จำเป็นสำหรับการประมวลผล เช่น Aggregate ที่กำลัง Compute
  5. Sink: ปลายทางของผลลัพธ์ อาจเป็น Database, Cache, Search Engine หรือ Object Storage

Stream-Table Duality

แนวคิดสำคัญใน Stream Processing คือ Stream กับ Table เป็นสิ่งเดียวกันที่มองต่างมุม Stream คือ Log ของ Change events ทั้งหมด ส่วน Table คือ State ล่าสุดที่ได้จากการ Replay Stream ทั้งหมด

ตัวอย่างเช่น ถ้ามี Stream ของการเปลี่ยนแปลงยอดเงินในบัญชี ซึ่งเป็น Changelog ที่บันทึกทุก Event เช่น ฝาก 1000 ถอน 500 ฝาก 2000 ถ้าเรา Replay Stream ทั้งหมดจะได้ Table ที่แสดงยอดคงเหลือล่าสุดของแต่ละบัญชี ในทางกลับกัน ถ้ามี Table และจับ Change events ทั้งหมดจะได้ Stream

แนวคิดนี้เป็นพื้นฐานของ KTable ใน Kafka Streams และ Dynamic Table ใน Flink SQL

CDC กับ Debezium + Stream Processing

Change Data Capture (CDC) เป็นเทคนิคการจับ Change events จากฐานข้อมูลแบบ Real-time โดยอ่านจาก Database Transaction Log เช่น MySQL Binlog หรือ PostgreSQL WAL แล้วส่งเข้า Kafka

Debezium เป็นเครื่องมือ CDC ที่นิยมที่สุด ทำงานเป็น Kafka Connect Source Connector ที่อ่านจากฐานข้อมูลแล้วส่ง Change events เข้า Kafka Topic

// Debezium MySQL Connector Config
{
  "name": "mysql-connector",
  "config": {
    "connector.class": "io.debezium.connector.mysql.MySqlConnector",
    "database.hostname": "mysql-host",
    "database.port": "3306",
    "database.user": "debezium",
    "database.password": "password",
    "database.server.id": "1",
    "topic.prefix": "myapp",
    "database.include.list": "mydb",
    "schema.history.internal.kafka.bootstrap.servers": "kafka:9092",
    "schema.history.internal.kafka.topic": "schema-changes"
  }
}

เมื่อ Change events อยู่ใน Kafka แล้ว สามารถใช้ Kafka Streams หรือ Flink ประมวลผลต่อได้ ใช้กรณีที่พบบ่อย เช่น Sync ข้อมูลไปหลาย Database สร้าง Search Index ใน Elasticsearch หรือ Invalidate Cache แบบ Real-time

Testing Stream Processing

การทดสอบ Stream Processing เป็นสิ่งที่ท้าทาย เพราะต้องจัดการกับ Time, State และ Ordering เครื่องมือและวิธีการที่ใช้ได้:

// Kafka Streams Unit Test (Java)
@Test
void testHighValueFilter() {
    TopologyTestDriver driver = new TopologyTestDriver(topology, props);

    TestInputTopic<String, Order> input =
        driver.createInputTopic("orders", stringSerde, orderSerde);

    TestOutputTopic<String, Order> output =
        driver.createOutputTopic("high-value-orders", stringSerde, orderSerde);

    // ส่ง Order มูลค่าสูง
    input.pipeInput("key1", new Order("user1", 50000));

    // ตรวจสอบว่าผ่าน Filter
    assertFalse(output.isEmpty());
    assertEquals(50000, output.readValue().getAmount());

    // ส่ง Order มูลค่าต่ำ
    input.pipeInput("key2", new Order("user2", 500));

    // ตรวจสอบว่าถูกกรองออก
    assertTrue(output.isEmpty());
}

Monitoring & Observability

Stream Processing ต้องมี Monitoring ที่ดี เพราะถ้าระบบมีปัญหาจะกระทบ Real-time ทันที Metrics ที่ต้องดูมีดังนี้:

เครื่องมือที่ใช้ Monitoring ได้แก่ Prometheus + Grafana สำหรับ Metrics, Kafka Manager หรือ Confluent Control Center สำหรับ Kafka, และ Flink Web UI สำหรับ Flink Job สำหรับระบบที่ต้อง Monitor ข้อมูลแบบ Real-time การวางระบบ Observability ที่ดีเป็นสิ่งจำเป็น

เมื่อไหร่ควรใช้เครื่องมือไหน

การเลือกเครื่องมือที่เหมาะสมขึ้นอยู่กับหลายปัจจัย:

คำแนะนำ: เริ่มจากเครื่องมือที่ง่ายที่สุดที่ตอบโจทย์ได้ ถ้า Kafka Streams พอแล้ว ไม่ต้องใช้ Flink อย่า Over-engineer ระบบที่ต้องดูแลรักษาในระยะยาว ความเรียบง่ายช่วยลดปัญหาในอนาคตได้มาก

สรุป

Stream Processing เป็นทักษะที่จำเป็นมากขึ้นเรื่อยๆ สำหรับ Data Engineer และ Backend Developer ในปี 2026 เพราะธุรกิจต้องการข้อมูล Real-time มากกว่าเดิม ไม่ว่าจะเป็นการตรวจจับ Fraud การแนะนำสินค้า หรือการแจ้งเตือนทันที

Kafka Streams เหมาะสำหรับการเริ่มต้นเพราะ Deploy ง่ายและไม่ต้องมี Cluster แยก ส่วน Apache Flink เป็นทางเลือกที่ทรงพลังกว่าสำหรับ Use case ที่ซับซ้อน สิ่งสำคัญคือเข้าใจแนวคิดพื้นฐานอย่าง Event Time, Watermarks, Windows และ State Management เพราะแนวคิดเหล่านี้ใช้ได้กับทุกเครื่องมือ

เริ่มจากการทดลองเขียน Kafka Streams Application ง่ายๆ ที่อ่านจาก Topic ประมวลผล แล้วเขียนกลับไป Topic อื่น จากนั้นค่อยเพิ่มความซับซ้อนด้วย Windowing, Join และ State เมื่อคุ้นเคยแล้วจะเข้าใจว่าการประมวลผลข้อมูลแบบ Real-time เปลี่ยนวิธีการทำงานของระบบไปอย่างสิ้นเชิง


Back to Blog | iCafe Forex | SiamLanCard | Siam2R