PipeCraft

Roadmap Progress

ข้อมูลเบื้องต้นเกี่ยวกับวิศวกรรมข้อมูล (Introduction to Data Engineering) Python สำหรับ Data Engineering พื้นฐาน Linux & CLI สำหรับวิศวกรข้อมูล Git สำหรับระบบงานข้อมูลและทีมพัฒนา พื้นฐานเครือข่าย เว็บเทคโนโลยี และระบบกระจายศูนย์ (Web Fundamentals, Networking & Distributed Systems) SQL ขั้นสูง (Window Functions & Optimization) ฐานข้อมูลไม่ใช่เชิงสัมพันธ์ (NoSQL Databases & Modern Stores) การออกแบบโครงสร้างข้อมูล (Star/Snowflake & SCD) โครงสร้างพื้นฐานเครือข่ายระบบคลาวด์ (Cloud-based Networking) สถาปัตยกรรม Data Lakehouse (Apache Iceberg & MinIO) Local-first Data Engineering ด้วย DuckDB โครงสร้างพื้นฐานในรูปแบบโค้ด (IaC ด้วย Terraform) การแปลงข้อมูลระดับโปรด้วย dbt-core ข้อตกลงร่วมด้านข้อมูล (Data Contracts) การบริการและการส่งต่อข้อมูลวิเคราะห์ (Data Serving & Reverse ETL) การประมวลผลข้อมูลขนาดใหญ่แบบกระจายด้วย Apache Spark ระบบจัดการเวิร์กโฟลว์ข้อมูล (Airflow, Dagster & Prefect) การประมวลผลข้อมูลแบบเรียลไทม์ด้วย Kafka & Redpanda การจัดการคอนเทนเนอร์และคลัสเตอร์ (Containers & Kubernetes) ระบบ CI/CD และการเฝ้าระวังคุณภาพข้อมูล (CI/CD, Monitoring & Testing) ระบบความปลอดภัยและการควบคุมข้อมูล (Security, Governance & Privacy) ระบบปฏิบัติการและประมวลผลโมเดล (Machine Learning & MLOps) รากฐานของ AWS VPC การจัดการเส้นทางขั้นสูงและ NAT Gateway การเชื่อมต่อหลาย VPC และ Hybrid Cloud VPC Endpoints (PrivateLink) ระบบรักษาความปลอดภัยขอบเขตเครือข่าย สถาปัตยกรรมเครือข่ายสำหรับ EKS IPv6 และการจัดการ IP Address สถาปัตยกรรมเครือข่ายระดับโลก แก่นแท้ของสถาปัตยกรรม Kubernetes สถาปัตยกรรมเครื่องและคอมโพเนนต์ เลเยอร์ที่เชื่อมต่อได้ (Pluggable Layers) การรันบนโปรดักชันระดับองค์กร Apache Flink Stateful Stream Processing Real-Time CDC & Event Sourcing at Scale Low-Latency Stream-Table Joins & Windowing Data Lineage & Metadata Graph Engineering Statistical Anomaly Detection & Data Drift Data Incident Management & Automated DLQ Remediation Cloud Data FinOps & Cost Optimization Mechanics Data Mesh & Multi-Tenant Platform Architecture Vector Databases & AI-Ready Data Infrastructure API Fundamentals, Architectures & Core Components API Versioning, Docs, Real-Time & Microservices Production Reliability, Security & Resiliency World-Class Master Architecture & Traffic Management
บทที่ 8: สถาปัตยกรรมประมวลผลสตรีมมิ่งเรียลไทม์ขั้นสูง (Real-Time Streaming Engine)

Apache Flink Stateful Stream Processing

เจาะลึก Stateful Streaming ใน Apache Flink

เรียนรู้ความสามารถเชิงลึกของ Apache Flink ในการประมวลผลสตรีมมิ่งแบบมีสถานะ (Stateful) โดยเน้นที่การจัดการเวลา, Watermarking, Complex Event Processing (CEP), และการสเกลสถานะด้วย RocksDB

Technical Architecture Diagram
Click to Zoom
🖼️ 3D Isometric Architecture Breakdown:
  • Step 1: Data Ingestion & Event Processing
  • Step 2: Distributed Computation & State Management
  • Step 3: Orchestration & Resource Allocation

1. Event Time vs. Processing Time & Watermarking

ทฤษฎีและกลไกการทำงาน

Learning Progression

  • 🟢 Basic Level: ปูพื้นฐานภาษาเข้าใจง่าย - เข้าใจคอนเซปต์ภาพรวมและการทำงานเบื้องต้นแบบไม่ซับซ้อน
  • 🟡 Intermediate Level: โค้ด/คอนฟิกไวยากรณ์จริง - การเขียนโค้ดและตั้งค่าพารามิเตอร์เพื่อใช้งานในระบบจริง
  • 🔴 Professional Level: Under-the-hood & Performance/FinOps - กลไกเบื้องลึก การจูนประสิทธิภาพ และการจัดการทรัพยากร

🏢 Real-World Enterprise Scenario

เคสระบบการเงิน/Big Tech: การรองรับ Transaction จำนวนมหาศาลต่อวินาทีพร้อมประกัน Data Integrity สูงสุด ลด Latency และประหยัดค่าใช้จ่ายผ่าน FinOps practices

ในการประมวลผลสตรีม การจัดการเวลาเป็นสิ่งสำคัญ Processing Time คือเวลาปัจจุบันของเครื่องเซิร์ฟเวอร์ที่กำลังรันโค้ด ซึ่งทำงานเร็วแต่ผลลัพธ์อาจไม่สม่ำเสมอหากนำข้อมูลมาประมวลผลใหม่ Event Time คือเวลาที่เหตุการณ์นั้นเกิดขึ้นจริง (มักแฝงมาในตัวข้อมูล) เพื่อรองรับข้อมูลที่มาถึงไม่เรียงตามลำดับ (Out-of-order) ใน Event Time, Flink ใช้ Watermarks เพื่อบอกระบบว่าเวลาได้เดินไปถึงไหนแล้ว และคาดว่าจะไม่มีข้อมูลที่เก่ากว่า Watermark ส่งมาอีก

ตัวอย่างโค้ดหรือการตั้งค่า


// กำหนด Watermark Strategy สำหรับจัดการ Event Time
WatermarkStrategy<MyEvent> strategy = WatermarkStrategy
    .<MyEvent>forBoundedOutOfOrderness(Duration.ofSeconds(5)) // ยอมให้ข้อมูลมาช้าได้ 5 วินาที
    .withTimestampAssigner((event, timestamp) -> event.getEventTime());

DataStream<MyEvent> stream = env.addSource(new MyEventSource())
    .assignTimestampsAndWatermarks(strategy);
        

Use Case ในชีวิตจริง

ระบบคำนวณปริมาณการซื้อขายหุ้นทุกๆ นาที ปัญหาเน็ตเวิร์กอาจทำให้คำสั่งซื้อส่งมาถึงเซิร์ฟเวอร์ช้า การใช้ Event Time และ Watermark ที่หน่วงเวลา 5 วินาที จะทำให้ระบบคำนวณยอดของนาทีที่ 10:00-10:01 ได้ถูกต้อง แม้คำสั่งของเวลา 10:00:59 จะมาถึงระบบตอน 10:01:04 ก็ตาม

ข้อควรระวังและวิธีแก้

Pitfall: การตั้งเวลาหน่วงของ Watermark นานเกินไปจะทำให้ระบบหน่วง (Latency สูง) และเปลือง Memory ในการเก็บ State รอข้อมูล ส่วนถ้าตั้งน้อยไป ข้อมูลจะถูกทิ้ง (Dropped) เยอะ
Mitigation: ตรวจสอบพฤติกรรมความล่าช้าของข้อมูลจริง และใช้ฟีเจอร์ Side Output ของ Flink เพื่อเก็บข้อมูลที่มาช้า (Late Data) ไปบันทึกแยกไว้โดยไม่กระทบ Pipeline หลัก

2. Complex Event Processing (CEP)

ทฤษฎีและกลไกการทำงาน

Flink CEP ช่วยให้เราสามารถค้นหารูปแบบ (Pattern) ของเหตุการณ์ที่ซับซ้อนในกระแสข้อมูลที่หลั่งไหลมาไม่ขาดสาย โดยใช้ State Machine ในการติดตามลำดับ เช่น "พบ Event A แล้วตามด้วย Event B ภายใน 10 วินาที" ระบบจะตรวจสอบเงื่อนไขที่ตั้งไว้แบบ Real-time ทันที

ตัวอย่างโค้ดหรือการตั้งค่า


// กำหนด Pattern: ล็อกอิน 'ล้มเหลว' แล้วตามด้วยล็อกอิน 'ล้มเหลว' อีกครั้งภายใน 10 วินาที
Pattern<LoginEvent, ?> pattern = Pattern.<LoginEvent>begin("first_fail")
    .where(new SimpleCondition<LoginEvent>() {
        @Override
        public boolean filter(LoginEvent event) {
            return !event.isSuccess();
        }
    })
    .next("second_fail")
    .where(new SimpleCondition<LoginEvent>() {
        @Override
        public boolean filter(LoginEvent event) {
            return !event.isSuccess();
        }
    })
    .within(Time.seconds(10));

PatternStream<LoginEvent> patternStream = CEP.pattern(loginStream, pattern);
        

Use Case ในชีวิตจริง

ระบบความปลอดภัยของ E-commerce ใช้ CEP ดักจับพฤติกรรมสวมรอย (Account Takeover) หากพบการล็อกอินผิดพลาดจาก IP เดียวกันหลายครั้ง ตามด้วยการล็อกอินสำเร็จและเปลี่ยนรหัสผ่านทันทีภายใน 2 นาที ระบบจะแจ้งเตือนและระงับบัญชีชั่วคราวแบบอัตโนมัติ

ข้อควรระวังและวิธีแก้

Pitfall: การเขียน Pattern ที่กว้างเกินไปและมีระยะเวลา (within) นานเกินไป จะทำให้ระบบต้องเก็บสถานะที่เป็นไปได้ทั้งหมดไว้จนเกิด State Explosion
Mitigation: ควรกำหนดเงื่อนไขให้เฉพาะเจาะจง ใช้ระยะเวลาที่สั้นที่สุดเท่าที่เป็นไปได้ และต้องมีการจัดกลุ่มข้อมูล (keyBy(userId)) เสมอ เพื่อจำกัดขอบเขตการคำนวณให้อยู่ภายในผู้ใช้แต่ละราย

3. RocksDB State Backend

ทฤษฎีและกลไกการทำงาน

Flink จำเป็นต้องมี State Backends เพื่อเก็บข้อมูลระหว่างการประมวลผล RocksDB State Backend จะเก็บ State ลงใน RocksDB (Database ฝังตัวแบบ Key-Value) ซึ่งเซฟลงดิสก์ของ TaskManager แทนที่จะเก็บใน RAM (เหมือน HashMap) ทำให้ Flink สามารถจัดการ State ขนาดใหญ่ระดับ Terabytes ได้โดยไม่เจอโจทย์ Out of Memory (OOM)

ตัวอย่างโค้ดหรือการตั้งค่า


# ตั้งค่าในไฟล์ flink-conf.yaml
state.backend.type: rocksdb
state.backend.rocksdb.localdir: /data/flink/rocksdb
state.checkpoints.dir: hdfs://namenode:9000/flink-checkpoints
state.backend.incremental: true # เปิดใช้งาน Incremental Checkpoints
        

Use Case ในชีวิตจริง

แอปเรียกรถ (Ride-hailing) ต้องจดจำตำแหน่งและสถานะของคนขับนับล้านคนตลอดเวลา เมื่อ State สะสมมากขึ้นจนเกิน RAM 32GB ของแต่ละโหนด RocksDB จะช่วยเขียนข้อมูลลง SSD ทำให้ระบบสามารถประมวลผลต่อไปได้อย่างเสถียร ไม่ล่ม

ข้อควรระวังและวิธีแก้

Pitfall: การอ่านเขียน State ถี่มากอาจทำให้เกิดคอขวดที่ Disk I/O และทำให้ระยะเวลาทำ Checkpoint นานขึ้นมาก
Mitigation: ควรใช้ดิสก์ SSD NVMe ที่มีความเร็ว I/O สูงๆ และต้องเปิดใช้งาน Incremental Checkpoints เพื่อให้ Flink แบ็กอัปเฉพาะไฟล์ RocksDB SST ที่เปลี่ยนแปลงเท่านั้น ซึ่งช่วยลดเวลาการทำ Checkpoint ได้มหาศาล

Weekend Sandbox Challenge 🚀

สร้างระบบตรวจจับการทุจริต: เขียนแอปพลิเคชัน Flink แบบสตรีมมิ่งเพื่อดักจับธุรกรรมต้องสงสัย

  • สร้างข้อมูลจำลองของธุรกรรม (userId, amount, location, timestamp)
  • สร้าง Event Time Watermark Strategy โดยยอมให้มาช้าได้ 2 วินาที
  • ใช้ Flink CEP ค้นหา Pattern ที่ผู้ใช้โอนเงิน > $1000 ในประเทศหนึ่ง แล้วโอนอีกครั้งในอีกประเทศหนึ่งภายในระยะเวลา 10 นาที
  • ตั้งค่าให้แอปใช้ RocksDB และทดลองรันสั่ง Savepoint

คำถามสัมภาษณ์ระดับ Senior (Interview Q&A)

Q: Watermarks แก้ปัญหาข้อมูลที่มาถึงช้า (Late-arriving data) ได้อย่างไร และจะเกิดอะไรขึ้นกับข้อมูลที่มาช้ากว่า Watermark?

A: Watermark คือตัวบอกเวลาของระบบประมวลผล เพื่อยืนยันว่าระบบจะไม่รอข้อมูลที่เก่ากว่าเวลานี้แล้ว ทำให้ Operator เช่น Window สามารถปิดและสรุปผลลัพธ์ออกไปได้ ข้อมูลที่เก่ากว่า Watermark จะถือว่าเป็น "Late Data" ซึ่งโดยค่าเริ่มต้น Flink จะทิ้ง (Drop) ข้อมูลเหล่านั้น แต่เราสามารถตั้งค่า allowed lateness เพื่ออัปเดตผลลัพธ์ย้อนหลังได้ หรือโยนข้อมูลเข้า Side Output ไปจัดการแยกเพื่อไม่ให้ข้อมูลสูญหาย

Q: ในสถานการณ์ใดที่คุณจะเลือกใช้ RocksDB State Backend แทน HashMap State Backend?

A: เราจะใช้ HashMap สำหรับระบบที่ State ไม่ใหญ่มากและต้องการความเร็วระดับ Microsecond แต่จะเปลี่ยนไปใช้ RocksDB เมื่อ State เริ่มใหญ่เกิน Memory ของ JVM (เช่น มี Key จำนวนมาก, หรือคำนวณ Window ข้ามสัปดาห์) แม้ RocksDB จะมีความหน่วงจากกระบวนการ Serialize/Deserialize และ Disk I/O (ระดับ Millisecond) แต่ก็แลกมาด้วยความสามารถในการ Scale ได้อย่างไร้ขีดจำกัดและไม่เกิด OutOfMemory Error