Distributed Systems · บทที่ 1 จาก 11

Characterization & System Models

ก่อนออกแบบระบบกระจายใด ๆ ต้องตอบให้ได้ก่อนว่า "กระจาย" หมายถึงอะไร มีอะไรที่ต่างจากโปรแกรมเดี่ยวบ้าง และความต่างเหล่านั้นนำไปสู่ความท้าทายอะไร — บทนี้วางกรอบคิดที่ทุกบทถัดไปอ้างอิงกลับมาตลอดวิชา

📚
อิงเนื้อหาจาก Coulouris, Dollimore, Kindberg & Blair — Distributed Systems: Concepts and Design (Chapter 1–2) พร้อมปรับปรุงตัวอย่างให้ตรงกับระบบที่ใช้งานจริงในปัจจุบัน เช่น cloud, container และ microservices

1ระบบกระจายคืออะไร

นิยาม
ระบบกระจาย (Distributed System) คือระบบที่ประกอบด้วยส่วนประกอบ (component) หลายส่วนอยู่บนคอมพิวเตอร์ที่เชื่อมต่อกันผ่านเครือข่าย โดยส่วนประกอบเหล่านั้นสื่อสารและประสานงานกันด้วยการส่งผ่านข้อความ (message passing) เท่านั้น — ไม่มีหน่วยความจำร่วม (shared memory) และไม่มีนาฬิกากลางที่ทุกเครื่องอ้างอิงตรงกัน

นิยามนี้มีนัยสำคัญกว่าที่ดูตอนแรก: มันหมายความว่าทุกสิ่งที่ process หนึ่งรู้เกี่ยวกับ process อื่นมาจากข้อความที่เคยได้รับเท่านั้น ไม่มีทางรู้ "สถานะปัจจุบัน" ของอีกฝั่งได้โดยตรง — นี่คือรากของปัญหาแทบทุกบทที่เหลือในวิชานี้ ตั้งแต่ transaction ข้าม service (บทที่ 5) ไปจนถึงการเรียงลำดับเหตุการณ์ (บทที่ 7) และการตกลงกัน (บทที่ 10)

ตัวอย่างระบบกระจายที่พบในชีวิตจริง

ระดับโครงสร้างพื้นฐาน
  • อินเทอร์เน็ตและอินทราเน็ต
  • เครือข่ายไร้สาย (wireless/mobile network)
  • DNS — ระบบชื่อแบบกระจาย
  • Cloud datacenter เช่น AWS, Azure, GCP
ระดับแอปพลิเคชัน
  • Client-Server เช่น NFS, เว็บไซต์
  • Peer-to-peer เช่น BitTorrent
  • Microservices บน container orchestration
  • Distributed database เช่น Cassandra, Spanner

2ลักษณะสำคัญที่ทำให้ระบบกระจายต่างจากโปรแกรมเดี่ยว

ลักษณะความหมายและผลกระทบ
ความหลากหลาย (Heterogeneity)ส่วนประกอบต่างกันได้ทั้งสถาปัตยกรรม CPU, OS, ภาษาโปรแกรม, และรูปแบบข้อมูล — ต้องมีมาตรฐานกลาง (บทที่ 2 เรื่อง marshalling)
การเกิดพร้อมกัน (Concurrency)หลาย process เข้าถึงทรัพยากรร่วมพร้อมกันได้ ต้องมีกลไกควบคุมไม่ให้แย่งหรือแทรกแซงกัน (บทที่ 4)
ความเป็นอิสระของความล้มเหลว (Independent failures)เมื่อส่วนหนึ่งของระบบล้มเหลว ส่วนอื่นอาจยังทำงานต่อได้และอาจไม่รู้ด้วยซ้ำว่าอีกฝั่งล้มเหลว — เรียกว่า partial failure ซึ่งเป็นแนวคิดที่ปรากฏซ้ำตลอดทั้งวิชา
ไม่มีนาฬิกากลาง (No global clock)แต่ละเครื่องมีนาฬิกาของตัวเองที่เดินไม่ตรงกัน (clock drift) การเรียงลำดับเหตุการณ์ข้ามเครื่องจึงทำโดยอาศัยเวลาธรรมดาไม่ได้ (บทที่ 7)
ทรัพยากรในรูปแบบ Serviceทรัพยากรถูกห่อหุ้มไว้หลัง interface ที่ประกาศไว้ชัดเจน ผู้เรียกไม่จำเป็นต้องรู้การ implement ภายใน
ข้อควรจำสำหรับสอบ
Partial failure และ no global clock คือสองลักษณะที่ทำให้ปัญหาในวิชานี้ "ยาก" กว่าโปรแกรมเดี่ยวโดยธรรมชาติ ไม่ใช่แค่ "ยากเพราะมีหลายเครื่อง" — โจทย์ข้อสอบส่วนใหญ่ในบทถัดไปคือการหาวิธีรับมือกับสองข้อนี้ในบริบทต่าง ๆ

3ความท้าทาย 7 ข้อในการสร้างระบบกระจาย

Coulouris จัดกลุ่มปัญหาการออกแบบระบบกระจายไว้ 7 หัวข้อ แต่ละข้อมีแนวทางแก้ที่ปรากฏซ้ำในบทถัดไปของวิชา

ความท้าทายปัญหาแนวทางแก้ที่พบในวิชานี้
Heterogeneityเครือข่าย, OS, ฮาร์ดแวร์, ภาษาโปรแกรมต่างกันมาตรฐานกลาง (protocol), Middleware, external data representation (บทที่ 2)
Opennessต้องขยาย/เพิ่ม service ใหม่ได้โดยไม่กระทบของเดิมเปิดเผย interface ตามมาตรฐาน (IDL), API contract
SecurityConfidentiality, Integrity, Availability; DoS attackAuthentication, encryption (นอกเหนือขอบเขตหลักของวิชานี้ แต่เชื่อมโยงกับทุกบท)
Scalabilityรองรับผู้ใช้/ทรัพยากรที่เพิ่มขึ้นโดยไม่เสียประสิทธิภาพReplication (บทที่ 9), partition/sharding, caching, DHT (บทที่ 11)
Failure handlingความขัดข้องเกิดแบบ partial — บางส่วนพังโดยส่วนอื่นไม่รู้Detection, recovery, redundancy — ทุกบทตั้งแต่ 5 เป็นต้นไป
Concurrencyเข้าถึงทรัพยากรพร้อมกันโดยไม่แทรกแซงกันLocking, optimistic concurrency control, timestamp ordering (บทที่ 4)
Transparencyซ่อนความซับซ้อนของการกระจายจากผู้ใช้ดูรายละเอียด 8 ประเภทด้านล่าง

Transparency — 8 รูปแบบของการปกปิดความซับซ้อน

แนวคิดหลัก
Transparency คือการทำให้ผู้ใช้มองเห็นระบบกระจายเป็น "ระบบเดียว" แทนที่จะเห็นส่วนย่อยอิสระที่ประกอบกันขึ้น — เป็นเป้าหมายเชิงออกแบบ ไม่ใช่คุณสมบัติที่มีหรือไม่มีแบบขาว-ดำ ระบบจริงมักทำ transparency ได้บางประเภทเท่านั้น
ประเภทความหมาย
Access transparencyเข้าถึงทรัพยากรท้องถิ่นและระยะไกลด้วยวิธีการเดียวกัน
Location transparencyเข้าถึงทรัพยากรได้โดยไม่ต้องรู้ตำแหน่งทางกายภาพ
Concurrency transparencyหลาย process ใช้ทรัพยากรร่วมกันได้โดยไม่รู้ตัวว่ามีคนอื่นใช้อยู่
Replication transparencyผู้ใช้ไม่รู้ว่าทรัพยากรมีสำเนาซ้ำอยู่หลายชุด
Failure transparencyซ่อนความขัดข้องและการกู้คืนจากผู้ใช้
Mobility transparencyทรัพยากร/บริการย้ายตำแหน่งได้โดยไม่กระทบผู้ใช้หรือโปรแกรมอื่น
Performance transparencyปรับโครงสร้างระบบใหม่เพื่อเพิ่มประสิทธิภาพได้โดยผู้ใช้ไม่รู้ตัว
Scaling transparencyขยายระบบได้ (ทั้งขนาดข้อมูลและจำนวนผู้ใช้) โดยไม่ต้องเปลี่ยนโครงสร้างหรือแอปพลิเคชัน

4รูปแบบสถาปัตยกรรมระบบ (Architectural Styles)

Client-Server
Client ร้องขอบริการจาก Server ตัวเดียว หรือ service เดียวกันให้บริการโดย server หลายเครื่อง (เพื่อ load balancing/availability) — รูปแบบพื้นฐานที่สุด
Proxy Server & Cache
Proxy คั่นระหว่าง client กับ server จริง ทำหน้าที่ cache ผลลัพธ์เพื่อลด traffic ไปยัง server ต้นทาง — บรรพบุรุษของ CDN และ API Gateway สมัยใหม่
Peer-to-Peer (P2P)
ทุก process มีบทบาทเท่ากัน ทั้งเป็นผู้ให้และผู้รับบริการ ไม่มี server กลาง — ขยายรายละเอียดในบทที่ 11
Mobile Code / Web Applets
โค้ดถูกดาวน์โหลดจาก server มารันที่ client — บรรพบุรุษของแนวคิด "ส่ง logic ไปหาข้อมูล" ที่ยังพบใน serverless edge functions ปัจจุบัน
Thin Client & Compute Server
Client บางเบาทำหน้าที่แค่แสดงผล ส่งงานประมวลผลหนักไปที่ compute server ผ่านเครือข่าย — แนวคิดเดียวกับ cloud gaming และ remote desktop สมัยใหม่
Two-tier และ Three-tier Architecture
Two-tier: client คุยตรงกับ database — ผูก business logic ไว้ที่ client หรือ database มากเกินไป Three-tier: แยกชั้น presentation, application logic (business layer), และ data ออกจากกันชัดเจน ทำให้ scale และดูแลรักษาแต่ละชั้นแยกอิสระได้ — เป็นต้นแบบโดยตรงของสถาปัตยกรรม microservices ที่ขยาย "application logic" ให้กลายเป็น service ย่อยจำนวนมาก

5System Model: มองระบบกระจายผ่าน 3 มุม

Coulouris เสนอว่าการวิเคราะห์ระบบกระจายควรแยกพิจารณา 3 มุมมองที่เป็นอิสระต่อกัน

มุมมองคำถามที่ตอบ
Physical modelฮาร์ดแวร์และซอฟต์แวร์พื้นฐานประกอบด้วยอะไรบ้าง — เครื่อง, เครือข่าย, middleware
Architectural modelความรับผิดชอบถูกกระจายไปยัง component ใดบ้าง และสื่อสารกันอย่างไร (เช่น client-server, P2P, layered)
Fundamental modelคุณสมบัติเชิงนามธรรมที่ใช้วิเคราะห์และพิสูจน์ระบบ — interaction model, failure model, security model

Interaction Model: Synchronous vs Asynchronous Distributed System

ทำไมต้องแยก
การวิเคราะห์ algorithm แบบกระจาย (เช่น consensus ในบทที่ 10) ต้องอาศัยสมมติฐานว่าระบบรับประกันขอบเขตเวลาได้แค่ไหน
แบบจำลองสมมติฐานผล
Synchronous distributed systemมีขอบเขตบนของ (1) เวลาประมวลผลแต่ละ step (2) ความหน่วงของข้อความ (3) อัตรา clock drift — ทั้งหมดรู้ล่วงหน้าวิเคราะห์ได้ง่าย แต่ไม่ตรงกับอินเทอร์เน็ตจริงที่ latency ผันผวน
Asynchronous distributed systemไม่มีขอบเขตเวลาใด ๆ ที่รับประกันได้ — process อาจช้าแค่ไหนก็ได้ ข้อความอาจหน่วงแค่ไหนก็ได้ตรงกับความเป็นจริงของอินเทอร์เน็ตและ cloud มากกว่า แต่พิสูจน์ทฤษฎีบางอย่างไม่ได้เลย (ดู FLP impossibility ในบทที่ 10)
เชื่อมโยงกับภาคปฏิบัติ
Timeout ที่ต้องเดา (ไม่ใช่รู้แน่ชัด) ว่า request "ช้า" หรือ "ตาย" กันแน่ — ที่พบตอนเขียนโปรแกรม network จริง — คือผลโดยตรงของการอยู่ใน asynchronous distributed system ไม่มีทางออกแบบระบบให้เป็น synchronous ได้จริงบนอินเทอร์เน็ตสาธารณะ

Failure Model: ความล้มเหลวเกิดขึ้นได้กี่แบบ

ประเภทลักษณะ
Omission failureProcess หรือ channel ไม่ทำงานตามที่ควร เช่น crash failure (process หยุดทำงานและไม่กลับมาอีก) หรือ send/receive omission (ข้อความหายระหว่างทาง)
Timing failureเกิดเฉพาะใน synchronous system — คำตอบมาช้าเกินขอบเขตเวลาที่รับประกันไว้
Arbitrary (Byzantine) failureProcess ทำงาน "ผิดปกติ" โดยพลการ อาจตอบค่าผิด ตอบค่าขัดแย้งกันไปยังผู้รับต่างคน หรือถูกโจมตี — รับมือยากที่สุด รายละเอียดในบทที่ 10

Failure model ที่ระบบสมมติไว้ ส่งผลต่อทุก algorithm ที่ออกแบบขึ้นบนระบบนั้นโดยตรง — algorithm ที่ถูกต้องภายใต้สมมติฐาน "crash-only failure" อาจใช้ไม่ได้เลยถ้าระบบมี Byzantine failure จริง (เช่น node ถูกแฮ็กแล้วส่งข้อมูลเท็จ)

6ทันสมัย: จาก Mainframe สู่ Cloud-Native

แนวคิดพื้นฐานข้างต้นถูกเสนอในยุคที่ระบบกระจายยังหมายถึง client-server และ LAN เป็นหลัก — แต่หลักการเดิมทั้งหมดยังคงอยู่ใต้ระบบยุคปัจจุบัน เพียงเปลี่ยนรูปลักษณ์

ยุคลักษณะ
Client-Server แบบดั้งเดิมServer จำนวนจำกัด ติดตั้งแบบ manual แต่ละเครื่องมีบทบาทตายตัว
Cloud Computing (IaaS/PaaS/SaaS)ทรัพยากรเช่าใช้ตามต้องการ (on-demand) IaaS ให้ควบคุมระดับเครื่องเสมือน, PaaS ให้ platform รันโค้ดโดยไม่ต้องดูแล OS, SaaS ให้ใช้ซอฟต์แวร์สำเร็จรูปผ่านเครือข่าย
Container & Orchestrationแต่ละ service รันใน container แยกกัน (Docker) จัดการวงจรชีวิตด้วย orchestrator (Kubernetes) — ตรงกับแนวคิด Service Instance per Container ที่กล่าวถึงในวิชา Network Computing
Microservicesขยายแนวคิด three-tier ให้ "application logic layer" กลายเป็น service เล็กจำนวนมาก แต่ละตัวมีวงจรชีวิตอิสระ — ปัญหาพื้นฐานเดิม (heterogeneity, partial failure, concurrency, no global clock) ยังอยู่ครบ เพียงเกิดถี่ขึ้นเพราะจำนวน service ที่มากขึ้น
ข้อสังเกตสำคัญ
Cloud และ microservices ไม่ได้ทำให้ปัญหาพื้นฐานของระบบกระจายหายไป — มันแค่เปลี่ยนสเกล (จำนวน node ที่มากขึ้น) และเปลี่ยนเครื่องมือ (middleware ใหม่, orchestration ใหม่) ทฤษฎีในบทที่เหลือของวิชานี้ (transaction, replication, consensus) คือรากฐานที่ระบบยุค cloud-native ยังต้องพึ่งพาอยู่ เพียงมี implementation ใหม่ เช่น Raft แทน classical Paxos, gRPC แทน CORBA
คำถามซ้อมสอบ
  1. อธิบายว่าทำไม "no global clock" และ "partial failure" จึงเป็นสองลักษณะที่ทำให้ระบบกระจายวิเคราะห์ยากกว่าโปรแกรมเดี่ยวโดยธรรมชาติ ไม่ใช่แค่ "มีหลายเครื่อง"
  2. ยกตัวอย่าง transparency 3 ประเภท พร้อมอธิบายว่าถ้าระบบไม่มี transparency ประเภทนั้น ผู้ใช้จะเจอปัญหาอะไร
  3. เปรียบเทียบ synchronous กับ asynchronous distributed system และอธิบายว่าทำไมอินเทอร์เน็ตสาธารณะจึงถูกจัดเป็นแบบ asynchronous
  4. อธิบายความแตกต่างระหว่าง omission failure กับ Byzantine failure พร้อมยกตัวอย่างสถานการณ์ที่แต่ละแบบเกิดขึ้นจริง
  5. อธิบายว่าสถาปัตยกรรม three-tier เป็นต้นแบบของ microservices อย่างไร และปัญหาพื้นฐานของระบบกระจายที่ Coulouris ระบุไว้ยังปรากฏใน microservices หรือไม่ อย่างไร

7เริ่มวิเคราะห์จาก “สิ่งที่แต่ละฝ่ายมองเห็น”

เวลาเห็นแผนภาพระบบ นักศึกษามักเริ่มจากนับว่ามีกี่เครื่อง กี่ service และต่อกันด้วยลูกศรกี่เส้น วิธีนี้ช่วยอธิบายโครงสร้าง แต่ยังไม่พอสำหรับระบบกระจาย เพราะความยากไม่ได้อยู่ที่จำนวนกล่องเพียงอย่างเดียว แต่อยู่ที่ว่าแต่ละกล่องรู้ความจริงได้ไม่เท่ากัน และรู้ไม่พร้อมกันด้วย

สมมุติ Service A ส่งคำสั่งสร้างรายการไปยัง Service B แล้วรอเกิน timeout จากมุมของ A เหตุการณ์ที่ยืนยันได้มีเพียง “ยังไม่ได้รับคำตอบภายในเวลาที่กำหนด” แต่โลกจริงอาจเกิดได้หลายแบบ: request ไม่เคยถึง B, request ถึงและ B กำลังทำงาน, B ทำสำเร็จแล้วแต่ response หาย, B crash หลังเขียนข้อมูล หรือ B ตอบกลับมาแล้วแต่ A เลิกรอไปก่อน ทุกโลกให้ observation ฝั่ง A เหมือนกัน

Metaphor: โทรศัพท์สายหลุด
เราสั่งอาหารเสร็จแล้วสายหลุดก่อนร้านพูดว่า “รับรายการแล้ว” การไม่ได้ยินคำยืนยันไม่ได้พิสูจน์ว่าร้านไม่ได้จด ถ้าโทรสั่งใหม่อาจได้อาหารสองชุด แต่ถ้าไม่ทำอะไรอาจไม่ได้อาหารเลย Distributed Systems เริ่มยากตรงที่ระบบต้องตัดสินใจจากหลักฐานไม่ครบ ไม่ได้ยากเพียงเพราะมีเครื่องหลายเครื่อง
สิ่งที่สังเกตได้สิ่งที่สรุปได้สิ่งที่ยังสรุปไม่ได้
ต่อ TCP ถูกปฏิเสธทันทีมีคำตอบระดับ transport ว่า endpoint นี้ไม่รับ connection ในขณะนั้นservice ตั้งใจปิด กำลัง restart ใช้ port ผิด หรือ firewall บางชนิดเป็นต้นเหตุ
request หมดเวลาdeadline ฝั่งผู้เรียกหมดก่อนเห็นผลผู้รับไม่ทำงานหรือไม่ เพราะงานอาจสำเร็จแล้ว
ได้รับ HTTP 500สื่อสารถึง application และ application รายงาน failureข้อมูลถูกเปลี่ยนไปบางส่วนหรือ rollback ครบแล้ว
health check ตอบ 200เส้นทางของ health endpoint ใช้งานได้ทุก dependency และทุก business operation พร้อมใช้งาน

นิสัยสำคัญของการวิเคราะห์ระบบกระจายจึงเป็นการเขียนสองคอลัมน์เสมอ: สิ่งที่รู้จาก observation กับ สิ่งที่อนุมานเพิ่ม ระบบจำนวนมากพังซ้ำเพราะนำสองคอลัมน์นี้มารวมกัน เช่นตีความ timeout ว่า transaction ล้มเหลว แล้ว retry operation ที่ไม่ idempotent ทันที

Local knowledge และความจริงระดับระบบ

แต่ละ process มี local state, ข้อความที่เคยส่ง และข้อความที่เคยรับ แต่มันไม่มีหน้าต่างวิเศษสำหรับดู global state ณ ขณะเดียวกัน ต่อให้ dashboard รวมข้อมูลจากทุกเครื่อง ข้อมูลบน dashboard ก็เดินทางผ่านเครือข่ายและมาถึงคนละเวลา สิ่งที่เรียกว่า “ภาพรวมของระบบ” จึงเป็นภาพที่ประกอบขึ้นจากข้อมูลหลายเวลา ไม่ใช่ภาพถ่ายที่หยุดจักรวาลได้จริง

แนวคิดนี้จะกลับมาในบท Time & Global States ซึ่งใช้ causal ordering และ distributed snapshot ช่วยสร้าง global state ที่มีความหมาย จุดสำคัญคือเราไม่ได้ทำให้นาฬิกาทุกเรือนตรงกันจนสมบูรณ์ แต่กำหนดเงื่อนไขว่าชุดเหตุการณ์แบบใดถือว่าเป็นภาพของระบบที่สอดคล้องกันได้

8System Model ไม่ใช่แผนภาพระบบ

คำว่า model มักถูกใช้หลวมจนหมายถึงรูปอะไรก็ได้ที่มีกล่องและลูกศร แต่ในบทนี้ model มีหน้าที่กำหนดขอบเขตของสิ่งที่เราจะวิเคราะห์ ถ้าไม่บอกสมมติฐานเรื่องเวลา การส่งข้อความ และ failure เราจะไม่รู้ว่า algorithm ที่เสนอนั้นแก้โจทย์อะไร หรือรับประกันได้ภายใต้โลกแบบใด

Physical model ถามว่า “ของอยู่ที่ไหน”

มีเครื่องกี่ชนิด อยู่ region/zone ใด เชื่อมผ่าน LAN, WAN หรือ mobile network ข้อมูลอยู่ใน disk, memory หรือ object storage และจุดใดมี shared fate เช่นเครื่องหลายตัวอยู่ rack เดียวกัน

Architectural model ถามว่า “แบ่งหน้าที่อย่างไร”

ใครเรียกใคร ใครเก็บ state ใครเป็นเจ้าของข้อมูล การสื่อสารเป็น synchronous หรือ asynchronous และมีศูนย์กลาง, hierarchy หรือ peer-to-peer

Interaction model ถามว่า “เวลาเชื่อถือได้แค่ไหน”

มีขอบเขต processing/communication delay หรือไม่ ใช้ timeout เป็นข้อสันนิษฐานหรือเป็น guarantee และ message อาจหาย ซ้ำ หรือสลับลำดับได้หรือไม่

Failure model ถามว่า “ผิดได้แค่ไหน”

process หยุดเงียบ, restart แล้วลืม state, channel ทำข้อความหาย หรือสมาชิกอาจตอบข้อมูลขัดแย้งโดยพลการ ถ้า model ไม่รวม failure แบบหนึ่ง algorithm ก็ไม่จำเป็นต้องรับมือแบบนั้น

กรณีศึกษา: ระบบชำระเงินสาม Service

สมมุติระบบมี Order, Payment และ Inventory อยู่คนละ container บน cluster เดียวกัน ถ้าวาดเพียงสามกล่องต่อกัน เรารู้แค่ว่าใครเรียกใคร แต่ยังตอบคำถามต่อไปนี้ไม่ได้:

  1. Payment กับ Inventory อยู่ zone เดียวกันหรือไม่ ถ้าไฟดับจะหายพร้อมกันหรือเปล่า
  2. Order รอผลทั้งสอง service แบบ synchronous หรือบันทึก event แล้วตอบรับก่อน
  3. แต่ละ service เก็บฐานข้อมูลของตนเองหรือเขียนฐานข้อมูลเดียวกัน
  4. ถ้า Payment ตอบช้า Order จะ retry กี่ครั้ง ใช้ request ID เดิมหรือสร้างใหม่
  5. process crash แล้วกลับมาพร้อม disk เดิม หรือกลับมาเป็น instance ใหม่ที่ไม่มี memory เดิม
  6. เราสมมุติเพียง crash failure หรือรวมกรณีที่ service คืนค่าผิดด้วย

คำตอบเหล่านี้เปลี่ยนวิธีออกแบบทั้งหมด เช่นถ้า process restart แล้ว memory หาย การจำ request ID ไว้ใน memory ไม่พอสำหรับ at-most-once behavior ถ้าฐานข้อมูลทั้งสามอยู่บน storage ชุดเดียว การแยก service ไม่ได้ให้ failure independence อย่างที่รูปชวนให้เชื่อ และถ้า workflow asynchronous คำว่า “order สำเร็จ” ต้องนิยามใหม่ว่าแปลว่ายอมรับคำขอแล้วหรือทุกขั้นเสร็จแล้ว

Model ที่ดีต้องเล็กพอให้คิด แต่ไม่เล็กจนซ่อนปัญหา

เราไม่มีทางใส่รายละเอียดโลกจริงทุกอย่างลง model ได้ เพราะ model ที่ละเอียดเท่าโลกจริงก็ช่วยลดภาระการคิดไม่ได้ แต่การตัดรายละเอียดต้องสัมพันธ์กับคำถาม ถ้าวิเคราะห์ consensus อาจไม่สนใจชนิด CPU แต่สนใจ message delay และ crash ถ้าวิเคราะห์ throughput อาจสนใจจำนวน core, queue และ network bandwidth ถ้าวิเคราะห์ภัยคุกคามต้องเพิ่มผู้โจมตีและ trust boundary เข้ามา

คำถามระหว่างอ่าน
ก่อนใช้ผลจาก algorithm หรือ paper ให้ถามว่า “ผลนี้จริงภายใต้ model แบบใด” ถ้า paper สมมุติ reliable FIFO channel แต่ระบบจริงใช้ queue ที่ส่งซ้ำได้ การย้าย algorithm มาใช้ตรง ๆ ไม่ใช่ implementation detail เล็ก ๆ แต่เป็นการเปลี่ยนโจทย์

9Synchronous, Asynchronous และโลกกึ่งกลางที่ใช้จริง

Synchronous system ในทางทฤษฎีไม่ได้หมายถึงการเขียนโค้ดแบบ blocking แต่หมายถึงระบบมีขอบเขตบนที่รู้ล่วงหน้าสำหรับเวลาประมวลผล ความหน่วงของข้อความ และ clock drift ส่วน asynchronous system ไม่รับประกันขอบเขตเหล่านี้ ต่อให้ข้อความส่วนใหญ่มาถึงใน 20 ms ก็ยังเป็น asynchronous ถ้าไม่มีค่าที่รับประกันว่า “ช้าที่สุดไม่เกินเท่าใด”

ความสับสนนี้ทำให้คนเห็น latency เฉลี่ยต่ำแล้วคิดว่าระบบมีเวลาแน่นอน แต่ algorithm ไม่ได้อยู่ด้วยค่าเฉลี่ย มันต้องรับมือ tail, pause, overload, packet loss, route change และ process ที่ถูก scheduler หยุดชั่วคราว ข้อความที่ช้ามากกับ process ที่ตายให้ observation แก่ผู้รอเหมือนกันคือยังไม่มีคำตอบ

โลกที่สมมุติสิ่งที่ทำได้สิ่งที่ต้องระวัง
Synchronousใช้ deadline ที่รับประกันแยก process ช้าเกินขอบเขตออกจาก process ปกติได้เหมาะกับระบบควบคุมบางชนิด แต่สมมุติฐานอาจแพงและแคบ
Asynchronousmodel ปลอดภัยต่อความล่าช้าที่ไม่มีเพดานแยก crashed process จาก very slow process ไม่ได้จากการรอเพียงอย่างเดียว
Partially synchronousยอมรับว่าช่วงหนึ่งไม่รู้ขอบเขต แต่หลังระบบนิ่งจะมีขอบเขตบางค่าใช้ใน consensus ปฏิบัติจำนวนมากเพื่อให้ safety อยู่เสมอและ progress หลัง network ดีขึ้น

ระบบจริงจำนวนมากจึงแยก safety ออกจาก liveness Safety บอกว่าสิ่งเลวร้าย เช่น leader สองคน commit log ขัดแย้งกัน ต้องไม่เกิด แม้เครือข่ายแย่ ส่วน liveness บอกว่าระบบควรเดินหน้าต่อเมื่อสภาพแวดล้อมกลับมาดีพอ ช่วง network partition ระบบอาจหยุดรับบางงานเพื่อรักษา safety ไม่ใช่เพราะ algorithm ล้มเหลว แต่เพราะไม่มีข้อมูลพอให้เดินหน้าทั้งเร็วและถูกพร้อมกัน

Timeout คือเครื่องมือด้านนโยบาย ไม่ใช่เครื่องตรวจความตาย

Timeout ตอบว่า “เรายอมรอนานเพียงใด” ไม่ได้ตอบว่า “อีกฝ่ายตายหรือยัง” ค่าที่สั้นลดเวลารอแต่เพิ่ม false suspicion ค่าที่ยาวลดการตัดสินผิดแต่ทำให้ failure ใช้เวลานานกว่าจะปรากฏ การตั้ง timeout จึงผูกกับ user expectation, latency distribution, retry budget และต้นทุนของงาน ไม่ควรเลือกเลขกลมเพราะดูจำง่าย

ตัวอย่าง
หน้า checkout อาจมีเวลาให้ทั้ง workflow 3 วินาที ถ้า gateway รอ Payment เต็ม 3 วินาที จะไม่เหลือเวลาส่ง error หรือ fallback กลับผู้ใช้ ระบบจึงต้องแบ่ง deadline budget ให้ DNS/connect/TLS, service call, database และการตอบกลับ รวมถึงส่ง deadline ต่อไปยัง downstream เพื่อไม่ให้คนข้างในทำงานต่อหลังผู้ใช้เลิกรอแล้ว

10Failure Model: จาก “ล่ม” คำเดียวไปสู่พฤติกรรมที่ออกแบบรับมือได้

คำว่า server ล่มกว้างเกินไปสำหรับการออกแบบ ระบบต้องรู้ว่ากำลังรับมือ failure class ใด เพราะต้นทุนต่างกันมาก การรับมือ crash-stop ใช้ redundancy และ leader election ได้ แต่ถ้า process อาจส่งค่าขัดแย้งให้สมาชิกคนละคน เราเข้าสู่ Byzantine failure ซึ่งต้องใช้จำนวน replica, quorum และการตรวจสอบที่เข้มกว่ามาก

ชนิดสถานการณ์แนวทางรับมือข้อจำกัด
Crash-stopprocess หยุดและไม่กลับมาreplica, failure detector, failoverdetector อาจสงสัยผิดใน asynchronous network
Crash-recoveryหยุดแล้วกลับมา โดย stable storage บางส่วนยังอยู่log, checkpoint, replay, epochต้องแยก instance เก่ากับใหม่และป้องกัน stale message
Omissionส่งหรือรับข้อความบางฉบับหายacknowledgment, retry, duplicate detectionretry เปลี่ยน loss เป็น duplicate ได้
Timingทำงานช้ากว่าขอบเขตที่กำหนดdeadline, admission control, isolationมีความหมายเป็น failure เมื่อ model มี bound เท่านั้น
Arbitrary/Byzantineตอบผิดหรือขัดแย้งจาก bug/attackBFT protocol, signature, diverse checksแพงและไม่ได้แก้ช่องโหว่ทุกชนิดโดยอัตโนมัติ

Failure detector มีความไม่แน่นอนอยู่ในตัว

Heartbeat ทำงานคล้ายเพื่อนส่งข้อความว่า “ยังอยู่นะ” ทุกช่วงเวลา ถ้าไม่เห็น heartbeat เราเริ่มสงสัย แต่สาเหตุอาจเป็น process ตาย, network ขาด, queue แน่น, GC pause หรือเครื่องตรวจเองช้า Failure detector จึงมักให้ suspicion ไม่ใช่คำพิพากษาจากธรรมชาติ

แนวคิด completeness ถามว่า process ที่ตายจะถูกสงสัยในที่สุดหรือไม่ ส่วน accuracy ถามว่า process ที่ยังดีจะถูกสงสัยผิดหรือไม่ ในอินเทอร์เน็ตที่ไม่มี bound เราไม่สามารถได้ detector ที่รู้ถูกทันทีทุกครั้ง จึงต้องออกแบบผลจากการสงสัยผิดให้จำกัด เช่นใช้ lease/epoch ป้องกัน leader เก่ากลับมาเขียนข้อมูล แม้สมาชิกบางส่วนคิดว่ามันหมดสถานะผู้นำแล้ว

Shared fate: แยกหลายกล่องแต่พังพร้อมกัน

Replication ให้ประโยชน์ต่อเมื่อสำเนาไม่แชร์ failure domain มากเกินไป การรัน replica สาม container บน physical host เดียวช่วย process failure แต่ไม่ช่วย host failure การวางสามเครื่องใน rack เดียวไม่ช่วยไฟ rack ดับ และการวางหลาย region แต่ใช้ identity provider หรือ control plane เดียวอาจยังมีจุดร่วมที่ล้มทั้งหมดได้

ดังนั้นคำถามไม่ใช่ “มี replica กี่ตัว” แต่คือ “replica เหล่านี้เป็นอิสระจาก failure ใดบ้าง” การเพิ่ม independence มีต้นทุนด้าน latency, bandwidth, consistency และการปฏิบัติการ ไม่มีคำตอบว่ากระจายไกลที่สุดดีที่สุดเสมอ ระบบซื้อ fault tolerance ด้วยต้นทุนชนิดอื่น

11Transparency: ซ่อนเท่าที่ช่วย ไม่ใช่ซ่อนจนตัดสินใจไม่ได้

Transparency ทำให้ระบบใช้ง่ายขึ้น เช่นผู้ใช้เปิดไฟล์ด้วยชื่อเดิมแม้ไฟล์ย้าย server หรือเรียก service ผ่านชื่อโดยไม่รู้ instance จริง แต่ transparency มีขอบเขต ยิ่งซ่อน distribution มาก นักพัฒนายิ่งเสี่ยงคิดว่า remote operation มีต้นทุนและ failure เหมือน local operation

Metaphor: กระจกใส
กระจกที่ใสช่วยให้มองผ่านได้โดยไม่สนใจตัวกระจก แต่ถ้ากระจกทำให้ระยะทางดูใกล้กว่าจริง เราอาจเดินชนมัน Abstraction ที่ดีซ่อนรายละเอียดซ้ำซ้อน แต่ไม่ควรซ่อนความต่างที่มีผลต่อ correctness เช่น remote call ช้า ล้มกลางทาง และอาจประมวลผลซ้ำได้
Transparencyประโยชน์สิ่งที่ไม่ควรซ่อนทั้งหมด
Accessใช้ interface เดียวกันกับทรัพยากรหลายชนิดremote latency, permission และ partial failure
Locationย้าย service/replica ได้โดย client ไม่ผูก IPdata residency และ geographic latency
Replicationอ่านชื่อเดียวโดยระบบเลือกสำเนาstaleness และ consistency level ที่งานต้องรู้
Failureretry/failover ความผิดพลาดชั่วคราวให้เองoperation ที่อาจเกิดซ้ำและ degraded state
Scalingเพิ่ม capacity โดยไม่แก้ client ทุกตัวquota, backpressure และ limit ที่เปลี่ยนพฤติกรรม

หลักคิดที่ใช้ได้คือซ่อน mechanism แต่เปิดเผย semantics ผู้ใช้ไม่จำเป็นต้องรู้ว่า request ไป replica ตัวใด แต่ควรรู้ว่า read อาจเก่าได้หรือไม่ ไม่จำเป็นต้องจัดการ reconnect ทุกขั้นเอง แต่ควรรู้ว่า library retry operation ใดและรับประกันอะไร

12สถาปัตยกรรมไม่ได้บอกคุณภาพโดยลำพัง

Client-server, three-tier, microservices, P2P และ event-driven architecture เป็นรูปแบบการแบ่งความรับผิดชอบ ไม่ใช่อันดับวิวัฒนาการที่ของใหม่ดีกว่าของเก่าเสมอ ระบบ modular monolith ที่มีขอบเขตชัดอาจแก้ง่ายและเชื่อถือได้กว่าระบบ microservices ที่ทุก service ต้อง deploy พร้อมกัน

รูปแบบจุดแข็งแรงกดดันที่ตามมา
Client–Serverownership และ control ชัดserver เป็นคอขวดหรือจุดล้มเหลวถ้าไม่ทำ redundancy
Three-tierแยก presentation, logic, dataapplication tier อาจโตเป็นก้อนใหญ่และ database เป็นศูนย์กลาง
Microservicesdeploy/scale ตาม business capabilitynetwork, consistency, observability และ operations ซับซ้อนขึ้น
Event-drivenลด temporal coupling ผู้ส่ง/รับไม่ต้องพร้อมกันduplicate, ordering, schema evolution และ debugging
P2Pกระจายทรัพยากรและลดศูนย์กลางchurn, trust, discovery และ uneven capacity

การเลือก architecture จึงเริ่มจาก workload, ownership, failure domain, consistency และทีมที่ดูแล ไม่ใช่เริ่มจากวาดกล่องจำนวนมาก รูปที่ดู distributed อาจยังมี shared database หรือ deployment pipeline เดียวจนล้มพร้อมกัน ขณะที่ระบบ process เดียวอาจจัดโมดูลดีพอและเป็นคำตอบที่เหมาะกับขนาดงาน

13Workshop: เขียน System Model ของระบบหนึ่งหน้า

เลือกหนึ่งระบบ เช่นระบบลงทะเบียนเรียน ระบบสั่งอาหาร ระบบ IoT หรือระบบวิเคราะห์ข้อมูล ห้ามเริ่มจากเทคโนโลยี ให้เริ่มจากสิ่งที่ระบบต้องรักษาและสิ่งที่ผู้ใช้สังเกตได้ แล้วจัดทำเอกสารหนึ่งหน้าโดยมีหัวข้อต่อไปนี้

  1. Components และ ownership: ใครรับผิดชอบข้อมูลและ decision ใด
  2. Communication: synchronous/asynchronous, protocol, message semantics และ deadline
  3. State: อยู่ที่ไหน มี replica/cache หรือไม่ และสถานะใดสูญหายเมื่อ restart
  4. Time assumption: ใช้ physical clock ตรงไหน ต้องการ causal/total order หรือไม่
  5. Failure model: crash-stop, recovery, omission, partition หรือ Byzantine แบบใดอยู่ในขอบเขต
  6. Safety: สิ่งใดห้ามเกิด เช่นหักเงินซ้ำหรือออกเลขที่ซ้ำ
  7. Liveness: สิ่งใดต้องเกิดในที่สุดเมื่อระบบกลับมาปกติ
  8. Observability: log, metric, trace หรือ audit ใดพิสูจน์เหตุการณ์ได้
เกณฑ์ตรวจ
แบบจำลองที่ดีไม่จำเป็นต้องมีลูกศรมาก แต่ต้องทำให้ผู้อ่านตอบได้ว่าเมื่อ message หนึ่งหาย ระบบรู้หรือไม่ จะทำอะไรต่อ และการตัดสินใจนั้นเสี่ยงละเมิด safety อย่างไร ถ้าเอกสารตอบเพียงว่าใช้ Kubernetes, Kafka และ database ชื่อดัง แสดงว่ายังบอกเครื่องมือมากกว่าบอก model

14สรุปและขั้นตอนถัดไป

ระบบกระจายไม่ได้เริ่มจากการมีหลายเครื่อง แต่เริ่มจากการที่แต่ละส่วนมองเห็นความจริงไม่พร้อมกัน สื่อสารผ่านข้อความ และล้มเหลวแยกจากกันได้ System model ทำให้เราระบุชัดว่าโลกที่กำลังวิเคราะห์มีเวลา channel และ failure แบบใด ขณะที่ architecture บอกว่าเราแบ่งความรับผิดชอบและ state อย่างไร

บทเรียนสำคัญที่สุดอาจฟังดูย้อนแย้ง: abstraction ที่ดีทำให้ระบบใช้ง่าย แต่การซ่อน distribution มากเกินไปกลับทำให้ระบบอันตราย เราจึงควรซ่อนกลไกที่ไม่จำเป็นต่อผู้ใช้ แต่เปิดเผย semantics ที่มีผลต่อความถูกต้อง เช่น deadline, duplicate, consistency และ failure

ขั้นตอนถัดไปคือ Interprocess Communication เราจะลงจาก model มาดู message จริงว่า process สองฝั่งสร้าง request–reply อย่างไร ข้อมูลต่างภาษาแปลงเป็นรูปแบบกลางอย่างไร และเหตุใดการส่งข้อความที่ดูเหมือนงานพื้นฐานจึงเป็นจุดเริ่มของ duplicate, ordering และ group communication ทั้งหมด