P
PipeCraft

Roadmap Progress

ข้อมูลเบื้องต้นเกี่ยวกับวิศวกรรมข้อมูล (Introduction to Data Engineering) Python สำหรับ Data Engineering พื้นฐาน Linux & CLI สำหรับวิศวกรข้อมูล Git สำหรับระบบงานข้อมูลและทีมพัฒนา ระบบเครือข่ายและระบบประมวลผลแบบกระจายศูนย์ (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)
บทที่ 1: รากฐานวิศวกรรมซอฟต์แวร์และระบบ (Foundations of Software & Systems)

ระบบเครือข่ายและระบบประมวลผลแบบกระจายศูนย์ (Networking & Distributed Systems)

1.5 ระบบเครือข่ายและระบบกระจายศูนย์ (Networking & Distributed Systems)

สถาปัตยกรรมคลังข้อมูลและเครื่องมือประมวลผลระบบกระจายศูนย์ (เช่น Spark, Kafka, Iceberg) ทำงานอยู่บนคลัสเตอร์โหนดคอมพิวเตอร์ที่เชื่อมต่อด้วยเครือข่าย วิศวกรข้อมูลระดับวิชาชีพจำเป็นต้องเข้าใจกลไกและทฤษฎีระบบกระจายศูนย์เพื่อแก้ไขและป้องกันความเสถียรของท่อส่งข้อมูล

1. ทฤษฎี CAP Theorem และการจัดสรรระบบจัดเก็บข้อมูลแบบกระจายศูนย์

ทฤษฎีและกลไกการทำงาน (How it works): ทฤษฎี **CAP Theorem** ระบุว่าระบบจัดเก็บข้อมูลแบบกระจายศูนย์สามารถรับประกันความเสถียรของเกณฑ์การทำงานได้เพียง 2 ใน 3 ประการพร้อมกันเมื่อเกิดสภาวะเครือข่ายตัดขาดชั่วคราว (Network Partition - P): - **Consistency (C - ความสอดคล้องข้อมูล)**: ทุกโหนดจะมองเห็นข้อมูลที่ตรงกันทุกประการในเวลาเดียวกัน หากเขียนค่าใหม่เสร็จสิ้น ทุกโหนดต้องตอบกลับค่าเดียวกัน - **Availability (A - ความพร้อมทำงาน)**: โหนดที่ไม่เสียหายต้องตอบกลับความต้องการใช้งานอ่านเขียนได้เสมอแม้เน็ตเวิร์กจะมีปัญหากับบางเครื่อง - **Partition Tolerance (P - ความทนทานต่อการตัดขาด)**: คลัสเตอร์ยังสามารถให้บริการอยู่ได้แม้เครือข่ายระหว่างโหนดจะหลุดขาดหายไป ในทางกายภาพ เมื่อเกิด Partition (P) ขึ้น เราจึงต้องเลือกสลับระหว่างระบบ **CP** (แลกคืนด้วยความถูกต้อง ห้ามเขียนหากโหนดซิงก์ไม่ได้) หรือ **AP** (แลกคืนด้วยความพร้อมทำงาน ยอมรับข้อมูลเขียนแล้วซิงก์ย้อนหลังในภายหลังด้วย Eventual Consistency)

# Example of choosing partition tolerance settings in distributed Cassandra (AP)
# Setting Consistency Level to QUORUM (requires majority confirmation) or ONE
from cassandra.cluster import Cluster
from cassandra.query import SimpleStatement, ConsistencyLevel

cluster = Cluster(['node1', 'node2', 'node3'])
session = cluster.connect('pipecraft_keyspace')

# Execute write query with QUORUM consistency to balance C and A in an AP database
query = SimpleStatement(
    "INSERT INTO user_events (event_id, user_id, action) VALUES (%s, %s, %s)",
    consistency_level=ConsistencyLevel.QUORUM
)
session.execute(query, ('uuid-1234', 42, 'login'))
                    

Use Case ในชีวิตจริง (Real-world Scenario): ระบบวิเคราะห์พฤติกรรมการคลิกสินค้าความถี่สูงต้องการระบบเก็บข้อมูลที่ทนทานและเร็ว จึงเลือกสถาปัตยกรรมแบบ AP อย่าง Cassandra เพื่อให้เขียนล็อกได้ไม่มีสะดุด แม้เน็ตเวิร์กสะดุดบางโหนดก็ยังเปิดรับเขียนได้ จากนั้นจึงพึ่งพากลไก Eventual Consistency ซิงก์ข้อมูลปลายทางให้ครบถ้วนทีหลัง

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): ความเข้าใจผิดที่คิดว่าระบบ AP จะให้ข้อมูลตรงกันเสมอตลอดเวลา อาจทำให้ยอดสรุปเงินในบัญชีเกิดข้อผิดพลาด แก้ไขโดยการแยกหมวดหมู่บริการ: สำหรับงานทำรายงานการเงินต้องเลือกใช้ระบบ CP (เช่น PostgreSQL with replication หรือ Google Spanner) และใช้งานระบบ AP เฉพาะสำหรับล็อกและตัวแปรสถิติที่ไม่ซีเรียสเรื่องลำดับ

2. สัญญากระจายศูนย์ (Distributed Consensus): เจาะลึกโปรโตคอล Paxos และ Raft

ทฤษฎีและกลไกการทำงาน (How it works): สัญญากระจายศูนย์ (Consensus Protocol) ช่วยให้โหนดคอมพิวเตอร์ในคลัสเตอร์เห็นพ้องต้องกันในรายการบันทึกประวัติ (Replicated State Machine) โดยไม่มีเครื่องใดเครื่องหนึ่งผูกขาด (Avoiding Single Point of Failure): - **Paxos**: โปรโตคอลดั้งเดิม ทำงานผ่านขั้นตอนเสนอมติแบบ 2 เฟสหลัก ได้แก่ Prepare-Promise (ทาบทามและให้สัญญาว่าจะยอมรับแฮชนี้) และ Propose-Accept (เสนอมติและยืนยันข้อตกลง) ออกแบบมาให้มีความสมมาตรยืดหยุ่นสูงแต่ยุ่งยากในการพัฒนาต่อยอดจริง - **Raft**: โปรโตคอลยุคใหม่ที่ออกแบบมาให้เข้าใจง่ายขึ้น โดยจะเลือกเครื่องนำเดี่ยว (Leader Election) เป็นผู้ประมวลผลการทำงานหลัก จากนั้น Leader จะทำหน้าที่ส่งต่อล็อกข้อมูลไปยังโหนดอื่น (Log Replication) และกดยืนยันมติเมื่อได้รับเสียงตอบรับกลับเกินครึ่งหนึ่ง (Quorum Commitment)

# Textual comparison of state transition behaviors
Raft State Machine:
[Follower] --(times out, starts election)--> [Candidate]
[Candidate] --(wins election majority)------> [Leader]
[Leader] --(detects new candidate term)------> [Follower]

Paxos State Machine (Basic Phase 1 & 2):
Proposer      Acceptors (Nodes)
Prepare(n)   --------->
             <--------- Promise(n, max_accepted_val)
Propose(n,v) --------->
             <--------- Accept(n,v)
                    

Use Case ในชีวิตจริง (Real-world Scenario): ระบบจัดเก็บ Metadata ของท่อส่งข้อมูลยุคใหม่อย่าง Kafka ในโหมด KRaft นำโปรโตคอล Raft มาใช้งานเพื่อทดแทนระบบประสานงานเดิม (ZooKeeper) ทำให้การจัดการคลัสเตอร์สตรีมมิ่งลื่นไหลและเลือกผู้นำใหม่ได้รวดเร็วขึ้นในกรณีที่เน็ตเวิร์กขาดการติดต่อ

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): อัตรา I/O แฝง (Network Latency) และภาระ CPU ของโปรโตคอล Consensus จะเพิ่มขึ้นตามจำนวนสมาชิกโหนดในคลัสเตอร์ แก้ไขโดยไม่ควรเพิ่มโหนดในระบบโหวตมากเกินไป (ปกติจำกัดไว้ที่ 3 หรือ 5 โหนด) และแยกโหนดที่เหลือให้ทำงานเป็นเพียง Follower / Read-replica แบบไม่มีสิทธิ์ร่วมโหวต

3. การจัดการเน็ตเวิร์กขาดการติดต่อ, อาการ Split-Brain และการคำนวณ Quorum

ทฤษฎีและกลไกการทำงาน (How it works): ปัญหา Split-Brain เกิดขึ้นเมื่อเครือข่ายระหว่างโหนดถูกตัดขาดออกจากกันครึ่งหนึ่ง ส่งผลให้โหนดแยกออกเป็น 2 ฝั่ง และแต่ละฝั่งต่างพยายามเลือกตั้งสถาปนาผู้นำ Leader ของตนเอง ทำให้ประวัติการเขียนเกิดการสับสนและเขียนทับกันเสียหาย เพื่อหลีกเลี่ยงเหตุการณ์นี้ ระบบจะนำกลไกการคำนวณเสียงข้างมากหรือ Quorum เข้ามาควบคุม โดยสูตรคำนวณคือ: $$Q = \lfloor N/2 \rfloor + 1$$ เมื่อมีการเขียนข้อมูลหรือเลือกตั้ง ผู้นำต้องได้รับการลงมติเห็นชอบจากโหนดจำนวนอย่างน้อยเท่ากับค่า Quorum เสมอ ฝั่งที่มีจำนวนโหนดน้อยกว่าครึ่งหนึ่ง (Minority Partition) จึงจะไม่สามารถรับเขียนหรือเลือกผู้นำได้เลย

# Quorum check script template
def calculate_quorum(total_nodes):
    return (total_nodes // 2) + 1

def can_accept_writes(active_nodes, total_nodes):
    required_votes = calculate_quorum(total_nodes)
    if active_nodes >= required_votes:
        return True, f"Quorum satisfied: {active_nodes}/{required_votes} nodes active."
    else:
        return False, f"Write blocked. Active nodes ({active_nodes}) < Quorum ({required_votes})."

# Example: 5-node cluster with a partition splitting it into 2 and 3 nodes
print(can_accept_writes(active_nodes=3, total_nodes=5))
print(can_accept_writes(active_nodes=2, total_nodes=5))
                    

Use Case ในชีวิตจริง (Real-world Scenario): คลัสเตอร์เก็บข้อมูล Elasticsearch ขนาด 5 โหนดโดนเน็ตเวิร์กตัดแยกเป็นฝั่ง 3 เครื่องและฝั่ง 2 เครื่อง ฝั่ง 3 เครื่องมีคะแนนเกิน Quorum ($3 \ge 3$) จึงทำงานได้ปกติ ส่วนฝั่ง 2 เครื่องไม่ถึงเกณฑ์จึงปิดบริการเขียนเพื่อป้องกันไม่ให้ข้อมูลสับสน

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): หากจำนวนโหนดรวมในคลัสเตอร์เป็นเลขคู่ (เช่น 4 โหนด ค่า Quorum คือ 3) โอกาสเกิดการแบ่งแยกแบบกึ่งหนึ่งแล้วไม่มีฝั่งใดสามารถให้บริการได้เลยจะสูงขึ้นมาก แก้ไขโดยออกแบบกำหนดจำนวนโหนดหลักในคลัสเตอร์ประมวลผลให้เป็น เลขคี่เสมอ (เช่น 3, 5, 7) เพื่อให้แยกฝั่งข้างมากได้ง่ายสุด

4. กลไกการจำลองคัดลอกข้อมูล: Leader-Follower vs. Leaderless Replication

ทฤษฎีและกลไกการทำงาน (How it works): การสำเนาและเพิ่มขีดความสามารถการอ่านข้อมูล (Replication) ในระบบฐานข้อมูลแบบกระจายศูนย์แบ่งออกเป็น 2 สถาปัตยกรรมหลัก: - **Leader-Follower (Master-Slave)**: การเขียนข้อมูลจะถูกส่งเข้าหาเครื่อง Leader หลักเพียงเครื่องเดียว จากนั้น Leader จะกระจายสำเนาข้อมูลส่งต่อไปยังโหนด Follower ทั้งหมด เหมาะกับการทำระบบงานประมวลผลที่เน้นการอ่านเป็นหลัก - **Leaderless Replication**: ไม่มีโหนดนำเดี่ยว ลูกค้าสามารถยิงขอเขียนหรืออ่านข้อมูลเข้าหาโหนดใดก็ได้พร้อมกัน โดยจะใช้สูตรการตกลงพิกัดความสอดคล้องตามสมการ Quorum ($W + R > N$) ซึ่ง $W$ คือจำนวนโหนดที่ยืนยันการเขียน และ $R$ คือจำนวนโหนดที่ถูกอ่านข้อมูล

# Calculating overlap logic in Leaderless Replication
# Formula: W (Write nodes) + R (Read nodes) > N (Total Replication Factor)
# If satisfied, at least one of the read nodes has the newest write, ensuring Consistency.

def is_strict_consistency_satisfied(w, r, n):
    if w + r > n:
        return True, "Strict read-after-write consistency guaranteed."
    else:
        return False, "Weak consistency. Read might fetch stale data."

# RF=3, Write Quorum = 2, Read Quorum = 2.
print(is_strict_consistency_satisfied(w=2, r=2, n=3))
                    

Use Case ในชีวิตจริง (Real-world Scenario): ระบบชำระเงินของแอปพลิเคชันคลาวด์เลือกใช้กลไก Leaderless Replication (เช่น DynamoDB) เพื่อให้ลูกค้าเปิดใช้งานสั่งจ่ายตังค์ได้ 100% ตลอดเวลา และตั้งค่าความลึกการตรวจสอบระดับสูงให้คิวรีอ่านเขียนทับกันเพื่อการันตีว่าได้ยอดเงินอัปเดตสุดเสมอ

ข้อควรระวัง and วิธีแก้ (Pitfalls & Mitigations): การเซ็ตค่า Quorum ต่ำลง (เช่น $W=1, R=1$ ในคลัสเตอร์ 3 โหนด) จะทำให้การประมวลผลเร็วแต่มีความเสี่ยงที่จะดึงเจอข้อมูลเก่าที่ค้างสะสม แก้ไขโดยการประยุกต์ใช้ **Read Repair** ตรวจเช็คข้อมูลเก่าระว่างคิวรีและทำการซิงก์อัปเดตอัตโนมัติ หรือใช้โปรโตคอลซ่อมแซมพื้นหลัง (Background Anti-entropy)

5. การควบคุมการประมวลผลร่วมกระจายศูนย์ด้วย ZooKeeper และ Raft Metadata Stores

ทฤษฎีและกลไกการทำงาน (How it works): การประมวลผลบิ๊กดาต้าข้ามคลัสเตอร์ (เช่น Hadoop, Spark, Trino) จำเป็นต้องมีกลไกจัดเก็บพารามิเตอร์แบบกระจายศูนย์ (Distributed Configuration) และระบบเลือกผู้นำโปรเซสหลัก **ZooKeeper** ใช้ระบบจัดเก็บแบบโครงสร้างต้นไม้ (ZNodes Hierarchy) ซึ่งรองรับการสร้าง ZNode ชั่วคราว (Ephemeral Nodes) ที่จะลบทิ้งทันทีหากไคลเอ็นต์เชื่อมต่อขาดหายไป ช่วยให้สามารถตรวจสอบการตายของเซิร์ฟเวอร์ย่อยได้อย่างแม่นยำ

# Conceptual Python code demonstrating active leader registration in Zookeeper
# Using ephemeral node to hold active status locks
import time

class DistributedLeaderElection:
    def __init__(self, client_id):
        self.client_id = client_id
        self.is_leader = False

    def acquire_lock(self):
        # Simulate creating an ephemeral node '/leader' in ZooKeeper
        print(f"[{self.client_id}] Attempting to create ephemeral node /leader...")
        # Under zookeeper, if path exists, it throws NodeExistsException
        self.is_leader = True
        print(f"[{self.client_id}] Success. Active leader status locked.")

    def run(self):
        self.acquire_lock()
        # Keep connection heartbeat active...
        
election = DistributedLeaderElection(client_id="spark_coordinator_01")
election.run()
                    

Use Case ในชีวิตจริง (Real-world Scenario): คลัสเตอร์ Apache Spark ที่รันโหมด High-Availability ใช้ ZooKeeper เพื่อเก็บสถานะชี้เป้าว่าเครื่อง Master ตัวใดทำงานรันระบบอยู่ หาก Master เครื่องหลักล้มเหลว โหนดสำรอง (Standby Master) จะดักจับ ZNode ที่หายไปแล้วขึ้นมาทำงานแทนทันที

ข้อควรระวังและวิธีแก้ (Pitfalls & Mitigations): ปัญหา **ZooKeeper Session Timeout** เกิดจากโปรเซสหลักทำงานหนักเกินไปจนลืมส่งสัญญาณชีพจร (JVM Garbage Collection Pause) ส่งผลให้ ZooKeeper คิดว่าระบบตายแล้วลบ ZNode ทิ้ง และเปลี่ยนผู้นำกลางคัน เกิดพายุ Split-brain เล็กๆ แก้ไขโดยตั้งค่าเวลา Session Timeout ให้กว้างขึ้น และทำความสะอาดคลังหน่วยความจำให้เสถียร

🛠️ Weekend Sandbox Challenge: Build a Simple TCP Socket Listener

โจทย์ปฏิบัติการ: จงเขียนสคริปต์ Python จำลองระบบรับส่งข้อมูลเครือข่ายต่ำโดยบิวด์เซิร์ฟเวอร์แบบ TCP Socket Listener เพื่อคอยจับสัญญาณการทักทายและการส่งแพ็กเก็ตข้อมูลจากผู้ใช้

# local_socket_server.py
import socket

# Initialize a TCP/IP socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 8888))
server_socket.listen(1)

print("TCP Server listening on port 8888...")

try:
    while True:
        connection, client_address = server_socket.accept()
        print(f"Connection established from: {client_address}")
        data = connection.recv(1024)
        if data:
            print(f"Received payload: {data.decode('utf-8')}")
            connection.sendall(b"ACK: Data received securely")
        connection.close()
finally:
    server_socket.close()
                    

💼 Senior Technical Interview Q&A

Q1: เพราะเหตุใดท่อส่งข้อมูลจำพวก ETL จึงต้องการกลไกความปลอดภัย TCP แทนการใช้ UDP ในการเชื่อมต่อระบบฐานข้อมูล?

A1: TCP ค้ำประกันความถูกต้องครบถ้วนของการรับส่งข้อมูล (Data Integrity) ผ่านระบบทำสามสเต็ปจับมือ (3-Way Handshake) การระบุหมายเลขลำดับแพ็กเก็ต (Sequence Numbers) และระบบสู้ใหม่เมื่อข้อมูลหาย (Retransmission) ในขณะที่ UDP ส่งข้อความทิ้งโดยไม่รอการยืนยัน ซึ่งหากมีแพ็กเก็ตหล่นหายจะทำให้ข้อมูลในฐานข้อมูลวิเคราะห์ขาดความสมบูรณ์

Q2: ตามทฤษฎี CAP Theorem ระบบฐานข้อมูลกระจายศูนย์อย่าง Cassandra สามารถปรับพารามิเตอร์เพื่อให้ผลลัพธ์การคิวรีคงระดับคงตัวสูง (High Consistency) ได้อย่างไร?

A2: ปรับตั้งค่าความยินยอมรับข้อมูลผ่านตัวแปรระดับ Consistency Level โดยกำหนดระดับการเขียนและอ่านให้อยู่ในโควต้ามติส่วนใหญ่ (Quorum Configuration เช่น $R + W > N$ โดยที่ R คือโหนดอ่าน W คือโหนดเขียน N คือจำนวนโหนดซ้ำซ้อน) เพื่อการันตีว่าเราจะคิวรี่พบข้อมูลอัปเดตล่าสุดจากโหนดปลายทางอย่างแน่นอน

🌐 Interactive VPC Network Subnet Router

Interactive VPC

เป้าหมาย: กำหนดตารางเส้นทาง (Route Table) และกลุ่มสิทธิ์ความปลอดภัย (Security Group) เพื่อเชื่อมต่อ App Server ไปยังฐานข้อมูลดิบใน Private Subnet อย่างปลอดภัยสูงสุด

Public Subnet (10.0.1.0/24)
App
IP: 10.0.1.5
Private Subnet (10.0.2.0/24)
DB
IP: 10.0.2.15
📍 Route Table Rules (Target destination: 10.0.2.0/24)
Route via:
🔒 DB Subnet Inbound Security Group Rule (Port: 5432)
Source Allow:

ข้อดี / จุดเด่น & ข้อเสีย / ข้อควรระวัง

ข้อดี / จุดเด่น

  • ช่วยให้ออกแบบสถาปัตยกรรมข้อมูลขนาดใหญ่ที่สเกลความเร็วคู่ขนานได้ปลอดภัยสูง
  • ช่วยดีบักปัญหาท่อส่งน้ำล่มได้ฉับไวเมื่อเน็ตเวิร์กขัดข้อง

ข้อเสีย / ข้อควรระวัง

  • มีความซับซ้อนในการตั้งค่าและต้องเข้าใจโปรโตคอลระบบคอมพิวเตอร์เชิงลึก
  • ปัญหาระบบเครือข่ายตกหล่น (Network Jitter) บางประเภทตรวจสอบและหาสาเหตุได้ยาก

ปฏิบัติการจริง (Lab Practice)

Bilingual Guide

แล็บ: วิเคราะห์การเชื่อมต่อเครื่องเซิร์ฟเวอร์วิเคราะห์ข้อมูล

💡 คำแนะนำ & ทริกเด็ด

ใช้คำสั่ง telnet [ip] [port] หรือ nc -zv [ip] [port] เพื่อเช็คว่าพอร์ตฐานข้อมูลปลายทางเปิดให้เชื่อมต่อจริงหรือไม่ก่อนเริ่มเขียนโค้ด ETL เสมอ ป้องกันเสียเวลากับปัญหา Firewall