Parallel Systems · บทที่ 9 จาก 9 (บทสุดท้าย)

Scalable Data Services

บทปิดท้าย — ทุกเทคนิคก่อนหน้านี้ (ขนานในซีพียู, MPI/CUDA, สถาปัตยกรรมระบบใหญ่, cloud) สุดท้ายต้องมาบรรจบที่คำถามเดียวกัน: ข้อมูลอยู่ที่ไหน และทำอย่างไรให้เข้าถึงได้เร็วพอเมื่อผู้ใช้มีหลักล้านคน บทนี้ดูสามเทคนิคคลาสสิกที่ตอบคำถามนั้นจากคนละมุม

📚
สังเคราะห์จากเอกสาร "Scalable Data Services" (2110414, Natawut Nupairoj) — เนื้อหาต้นฉบับอ้างอิง MySQL Cluster (2006), GlusterFS (2010), และ Memcached เป็นกรณีศึกษา ซึ่งยังคงเป็นตัวแทนของแนวคิดหลัก 3 แบบที่ระบบยุคปัจจุบันยังใช้อยู่: database clustering, distributed file system, และ in-memory caching

1ปัญหาตั้งต้น: ทำไม Data Service ถึงเป็นคอขวด

จากเอกสารต้นฉบับ
Data retrieval มักเป็นคอขวดของระบบขนาดใหญ่เสมอ ด้วยเหตุผลสองข้อ: Searching (หาข้อมูลที่ต้องการท่ามกลางข้อมูลปริมาณมาก) และ Transferring (ย้ายข้อมูลจาก storage มาถึงผู้ใช้) — เทคนิคพื้นฐานสองแบบที่แก้ปัญหานี้คือ Data Partitioning (แบ่งข้อมูลกระจายไปหลายเครื่อง) และ Data Replication (ทำสำเนาข้อมูลซ้ำ แลกกับภาระเรื่อง consistency) ส่วนเทคนิคระดับสูงกว่านั้นคือหัวข้อของบทนี้ทั้งสามแบบ: Database Clustering, Distributed/High-Performance File Systems, และ In-Memory Caching

2Database Clustering: กรณีศึกษา MySQL Cluster (NDB)

MySQL รองรับหลาย storage engine (MyISAM, InnoDB, Memory, Federated) — NDB (Network DataBase) คือ engine ที่ออกแบบมาเฉพาะสำหรับทำ clustering โดยเฉพาะ

คุณสมบัติ NDB Clusterรายละเอียด
In-memory storageเก็บข้อมูลและ index ไว้ใน memory เป็นหลัก (checkpoint ลงดิสก์เป็นระยะ) ทำให้เร็วกว่าดิสก์มาก
Shared-Nothing Architectureแต่ละ node ไม่แชร์ดิสก์/memory กัน — ไม่มี single point of failure ในระดับฮาร์ดแวร์
Synchronous Replicationข้อมูลถูก replicate ระหว่าง node แบบ synchronous — เมื่อ node หนึ่งพัง อีก node หนึ่งมีข้อมูลล่าสุดครบถ้วนพร้อมทำงานต่อทันที (fail-over)
Row-level Lockingล็อกเฉพาะแถวที่กำลังแก้ไข ไม่ใช่ทั้งตาราง — รองรับ concurrent transaction ได้มากขึ้น

โครงสร้างสอง Tier ของ Cluster

SQL Layer (SQL Nodes / API Nodes)
มักเป็น MySQL server (mysqld) ที่แอปพลิเคชันเชื่อมต่อผ่าน SQL ตามปกติ — แต่ละ SQL node เชื่อมต่อไปยังทุก Data node
Storage Layer (Data Nodes + Management Nodes)
Data node (ndbd) เก็บข้อมูลและ index จริง รับผิดชอบ transaction coordination รองรับได้สูงสุด 48 data node ต่อ cluster · Management node (ndb_mgmd) ควบคุมการตั้งค่าและทำหน้าที่ arbitrator เวลาเกิด network partition

พฤติกรรมเมื่อเกิดความล้มเหลว (Failure Scenarios)

เมื่อ node ใดพังระบบตอบสนองอย่างไร
MySQL Server (SQL node) พังแอปพลิเคชันย้ายไปใช้ SQL node อื่นแทน; mysqld พยายาม reconnect อัตโนมัติ
Data Node พังData node อื่นใน group รับรู้และ transaction ที่ค้างอยู่จะถูก abort — ระบบต้องมี node เหลืออย่างน้อย 1 ตัวต่อ node group เสมอ (ถ้าทั้ง group เหลือ 0 node ระบบต้อง shutdown)
ตัวอย่างจากเอกสารต้นฉบับ: Web Session Storage
ระบบ web ทั่วไปที่ไม่มี cluster: หลาย Apache/PHP server (อยู่หลัง load balancer) เชื่อมต่อ MySQL serverตัวเดียว — ตัวนั้นคือ single point of failure ทั้งระบบ · เมื่อเปลี่ยนมาใช้ NDB Cluster: MySQL ถูกกระจายเป็นหลาย node ที่มีข้อมูล replicate ร่วมกัน (shared storage แบบ redundant) ไม่มี single point of failure อีกต่อไป แม้ data node หนึ่งพังระบบยังให้บริการต่อได้

3Distributed File System: กรณีศึกษา GlusterFS

คืออะไร
Clustered file system แบบ open-source ที่รวมพื้นที่ดิสก์และ memory จากหลายเครื่องเข้าเป็น global namespace เดียวผ่านเครือข่าย — ขยายได้ถึงระดับ petabyte รองรับ client หลักพัน ใช้ฮาร์ดแวร์ทั่วไป (commodity hardware) เป็นการทำ storage virtualization รูปแบบหนึ่ง
Load Balancing Mode
เก็บข้อมูลเป็นไฟล์/โฟลเดอร์ปกติ ใช้ token (extended attribute ของไฟล์) ระบุตำแหน่งไฟล์แบบกระจาย — Gluster แปลงชื่อไฟล์ที่ร้องขอเป็น token แล้วเข้าถึงไฟล์โดยตรง ไม่ต้องมี metadata server กลาง (ต่างจากระบบไฟล์แบบ centralized-metadata อย่าง GFS/HDFS ยุคแรก)
Replication Mode
ทำสำเนาข้อมูลอัตโนมัติข้ามหลาย storage ให้ high availability (auto fail-over) และ auto self-healing (ซ่อมแซมสำเนาที่เสียหายอัตโนมัติ) ใช้ load balancing ช่วยกระจายการเข้าถึงสำเนาที่ replicate ไว้
จุดสังเกตเชิงสถาปัตยกรรม
การไม่มี metadata server กลางคือจุดขายหลักของ GlusterFS เทียบกับดีไซน์อื่น — ไม่มี single point of failure/bottleneck ที่ metadata server แต่ก็แลกมาด้วยความซับซ้อนของ token-based lookup

4In-Memory Caching: กรณีศึกษา Memcached

คืออะไร
General-purpose distributed memory caching system แบบ open source — เปรียบเหมือน hash table ขนาดยักษ์ที่กระจายอยู่บนหลายเครื่อง ใช้ RAM เก็บ cache ของข้อมูล/object เพื่อเร่งความเร็วเว็บไซต์ที่ขับเคลื่อนด้วยฐานข้อมูล เอกสารต้นฉบับระบุผู้ใช้งานจริงยุคนั้น ได้แก่ LiveJournal, Wikipedia, Facebook, Flickr, Twitter, YouTube
// ตัวอย่างจากเอกสารต้นฉบับ — Memcached ผ่าน Java API
MemcachedClient c = new MemcachedClient(
    new InetSocketAddress("127.0.0.1", 11211));

c.set("someKey", 3600, someObject);        // เก็บ object, หมดอายุใน 3600 วิ
Object myObject = c.get("someKey");         // ดึงค่ากลับ
c.delete("someKey");                        // ลบออกจาก cache
Memcached + MySQL: รูปแบบการใช้งานทั่วไป
Cache ผลลัพธ์ของ query ที่ถูกเรียกซ้ำบ่อย เช่น SELECT * FROM users WHERE userid = ? — ครั้งแรก query ไปที่ฐานข้อมูลแล้วเก็บผลลง Memcached ครั้งต่อไปอ่านจาก cache โดยตรง (เร็วกว่าอ่านดิสก์ของฐานข้อมูลมาก) ลดภาระที่ตกไปยังฐานข้อมูลจริงลงอย่างมาก

5ประกอบร่างทั้งหมด: สถาปัตยกรรมแบบ Facebook (ตามที่เอกสารต้นฉบับอ้างถึง)

ทำไมต้องพูดถึง Facebook
เอกสารต้นฉบับปิดท้ายด้วยการยกสถาปัตยกรรมของ Facebook (ยุคก่อนปี 2010) เป็นตัวอย่างที่ประกอบทุกเทคนิคในวิชานี้เข้าด้วยกัน — เป็นกรณีตัวอย่างที่ดีเพราะแสดงให้เห็นว่าระบบขนาดใหญ่จริงไม่ได้ใช้เทคนิคเดียว แต่ผสมทุกชั้น: load balancer กระจาย request (บทที่ 7) → web server tier แบบ stateless (บทที่ 7) → Memcached เป็น cache ชั้นกลาง (หัวข้อนี้) → MySQL ที่ทำ clustering/replication ชั้นล่างสุด (หัวข้อนี้) — ระบบขนาดใหญ่ทุกระบบคือการประกอบเทคนิคพื้นฐานเหล่านี้เข้าด้วยกันเป็นชั้น ๆ ไม่มีเทคนิคเดียวที่ตอบโจทย์ทุกอย่าง

6จาก NDB, GlusterFS และ Memcached ไปสู่ระบบปัจจุบัน

แล้ว · ~2010–2013
ตอนนี้ · 2026
MySQL Cluster (NDB) คือทางเลือกหลักสำหรับ relational database ที่ต้อง scale-out แบบ shared-nothing — ตั้งค่าซับซ้อน ต้องดูแล node group เอง
แนวคิด shared-nothing + synchronous replication ยังอยู่ แต่ถูกทำให้ใช้ง่ายขึ้นมากในรูปของ NewSQL (CockroachDB, TiDB, Google Spanner) ซึ่งเพิ่ม distributed transaction ข้าม region ได้ด้วย หรือ managed service อย่าง Amazon Aurora / Vitess (ผู้ให้บริการดูแล replication/fail-over ให้อัตโนมัติ ผู้ใช้ไม่ต้องตั้งค่า node เอง)
GlusterFS คือหนึ่งในตัวเลือกหลักของ scale-out distributed file system บน commodity hardware ใช้ token-based lookup แทน metadata server กลาง
งานเก็บข้อมูลขนาดใหญ่จำนวนมากย้ายไปใช้ Object Storage (Amazon S3, MinIO, Ceph) ที่ทิ้งแนวคิด "ไฟล์/โฟลเดอร์" ไปเลย ใช้ flat key-value namespace แทน — scale ได้ง่ายกว่าระบบไฟล์แบบเดิมมาก โดยเฉพาะกับ workload แบบ cloud-native และ data lake
Memcached คือมาตรฐานของ in-memory caching — เก็บได้แค่ key-value แบบง่าย (string/object เดี่ยว) ไม่มี persistence และไม่มี built-in replication
Redis แซงหน้าขึ้นมาเป็นตัวเลือกยอดนิยมกว่าในหลายกรณี เพราะรองรับโครงสร้างข้อมูลซับซ้อนกว่า (list, set, sorted set, hash), มี persistence (RDB/AOF snapshot), และมี built-in replication/cluster mode ในตัว — แต่ Memcached เองก็ยังไม่ตาย ยังถูกใช้ในกรณีที่ต้องการความง่ายและ multi-threaded performance ล้วน ๆ โดยไม่ต้องการฟีเจอร์เสริม
สิ่งที่เอกสารต้นฉบับไม่ได้พูดถึงเลย เพราะยังไม่มีในเวลานั้น
NoSQL แบบ document/wide-column (MongoDB, Cassandra, DynamoDB) ซึ่งเลือกสละ strong consistency บางส่วนแลกกับ availability/partition-tolerance ตาม CAP theorem (เชื่อมโยงกับเนื้อหา replication ในวิชา Distributed Systems) และ data streaming platform (Kafka, Pulsar) ที่เปลี่ยนกรอบคิดจาก "query ฐานข้อมูล" เป็น "subscribe ต่อ stream ของ event" — ทั้งสองแนวคิดกลายเป็นเสาหลักของสถาปัตยกรรมข้อมูลขนาดใหญ่ยุคปัจจุบัน ควบคู่ไปกับเทคนิคคลาสสิกในบทนี้ ไม่ใช่มาแทนที่

7บริการข้อมูลต้องรักษาอะไรบ้าง

บริการคำนวณที่ไม่มี state สามารถสร้าง instance ใหม่แล้วรับงานต่อได้ แต่บริการข้อมูลต้องตอบว่าข้อมูลอยู่ที่ใด รุ่นใดถูกต้อง และจะกู้กลับอย่างไรเมื่อเครื่องหาย การ scale จึงไม่ใช่เพียงเพิ่ม replicas เพราะสำเนาหลายชุดสร้างปัญหาความสอดคล้องตามมา

เป้าหมายคำถามตัวชี้วัด
Capacityเก็บข้อมูลและดัชนีได้มากเท่าใดTB/node, compression, metadata overhead
Throughputอ่านเขียนต่อวินาทีได้เท่าใดOps/s, MB/s
Latencyคำขอหนึ่งเสร็จเร็วเพียงใดp50/p95/p99 แยก read/write
Durabilityตอบสำเร็จแล้วทน failure ระดับใดReplica/zone, fsync, loss probability
Consistencyผู้อ่านสังเกตลำดับอะไรได้Linearizable, causal, eventual, staleness
Availabilityเมื่อบางส่วนล่มยังรับ operation ใดได้Error rate, quorum availability, recovery time

8Replication, Backup และ Sharding แก้คนละปัญหา

แนวคิดเป้าหมายสิ่งที่ไม่รับประกัน
Replicationมีสำเนาเพื่อ availability, read scale และ localityย้อนข้อมูลที่ลบผิด หากการลบถูก replicate แล้ว
Backupเก็บประวัติสำหรับ recoveryรับ traffic ต่อทันทีเมื่อ primary ล่ม
Shardingแบ่งข้อมูลและ load ข้าม nodesAvailability หาก shard มีสำเนาเดียว
เอกสารหลายสาขา
Replication คือถ่ายเอกสารฉบับล่าสุดไว้หลายสาขา Backup คือเก็บฉบับเดือนก่อนในห้องนิรภัย ส่วน sharding คือแบ่งแฟ้มตามจังหวัดให้แต่ละสาขาดูแล หากพนักงานลบเอกสารแล้วส่งคำสั่งลบทุกสาขา สำเนาหลายชุดก็หายพร้อมกัน จึงยังต้องมี backup

9Sharding และการเลือก Partition Key

Hash partition กระจาย key ได้สม่ำเสมอแต่ range scan ข้าม shards Range partition เหมาะกับช่วงแต่เสี่ยง hotspot ที่ปลายใหม่ Directory-based mapping ยืดหยุ่นแต่ metadata service กลายเป็น dependency สำคัญ

จำนวนข้อมูลสมดุลไม่เท่ากับโหลดสมดุล
Shard แต่ละตัวอาจมี 1 TB เท่ากัน แต่ shard ที่ถือผู้ใช้ดังรับคำขอสิบเท่า ต้องวัด bytes, QPS, CPU และ working-set heat พร้อมกัน

10Consistent Hashing และการย้ายข้อมูลเมื่อสมาชิกเปลี่ยน

Hash แบบ modulo N ทำให้ key ส่วนใหญ่ remap เมื่อ N เปลี่ยน Consistent hashing วาง node และ key บนวงแหวน เมื่อเพิ่ม node จะย้ายเพียงช่วงใกล้เคียง Virtual nodes ช่วยกระจายช่วงและรองรับเครื่อง capacity ต่างกัน

Consistent hashing ลดการย้ายแต่ไม่ได้แก้ hot key, replication หรือ consistency และคำว่า consistent ในชื่อนี้หมายถึง mapping เปลี่ยนน้อย ไม่ใช่ strong consistency ของข้อมูล

11Single-Leader, Multi-Leader และ Leaderless

รูปแบบข้อดีต้นทุน
Single leaderลำดับ write ชัดและ conflict น้อยFailover, leader bottleneck และ latency ข้าม region
Multi-leaderเขียนใกล้ผู้ใช้และทน partition ระหว่างพื้นที่Concurrent conflict และ merge
LeaderlessAvailability สูงและไม่มี leader ถาวรQuorum, version conflict, read repair และ anti-entropy

รูปแบบที่เหมาะขึ้นกับ write pattern และ invariant ข้อมูล profile อาจใช้ single writer ต่อผู้ใช้ ขณะที่ shopping cart อาจยอม merge ส่วน inventory ก่อน checkout ต้องเข้มกว่า

12Quorum และความหมายของ R, W, N

เงื่อนไขคลาสสิก
R + W > N
W + W > N
R คือจำนวน replica ที่อ่าน W คือจำนวนที่ยืนยัน write และ N คือ replication factor การทับกันช่วยให้ read พบสำเนาจาก write ล่าสุดภายใต้สมมติฐานที่กำหนด

ในโลกจริง sloppy quorum อาจฝากข้อมูลบน node อื่นชั่วคราว เซต R และ W จึงไม่ใช่ owners ชุดเดียวเสมอ การตั้ง QUORUM ไม่ได้รับประกัน linearizability โดยอัตโนมัติ ต้องดู versioning, concurrent writes และ read path

13Consistency Model จากมุมผู้ใช้

หน้า Profile
ผู้ใช้อาจยอมให้เพื่อนต่างภูมิภาคเห็นรูปใหม่ช้าหนึ่งวินาที แต่เจ้าของที่เพิ่งเปลี่ยนรูปไม่ควร refresh แล้วกลับไปเห็นรูปเก่า Session guarantee จึงสร้างประสบการณ์ที่สมเหตุสมผลโดยไม่ต้องบังคับทุก replica ให้ตรงกันทันที

14CAP และ PACELC แบบไม่ใช้เป็นป้ายสินค้า

เมื่อ network partition ทำให้ replica สองฝั่งสื่อสารไม่ได้ ระบบเลือกได้ว่าจะปฏิเสธบาง operation เพื่อรักษา consistency หรือให้ทั้งสองฝั่งตอบต่อและยอมเห็นต่างชั่วคราว Partition tolerance เป็นสภาพที่ต้องรับมือ ไม่ใช่ feature ที่ติ๊กทิ้งได้ในเครือข่ายจริง

PACELC เติมว่าแม้ไม่มี partition ระบบยังเลือกระหว่าง latency กับ consistency เพราะการรอ replica ไกลยืนยันย่อมช้ากว่าตอบจากสำเนาใกล้ ระบบเดียวกันอาจเลือกต่างกันต่อ operation จึงไม่ควรติดป้ายฐานข้อมูลทั้งก้อนว่า CP/AP โดยไม่บอก configuration

15Write Path: คำว่า “สำเร็จ” ต้องมีความหมาย

  1. รับ request และตรวจ idempotency key
  2. เขียน write-ahead log
  3. อัปเดต memory structure หรือ page
  4. Replicate ไป replicas ตาม policy
  5. ตอบ client เมื่อถึง durability/consistency level
  6. Flush/compact/merge ภายหลังตาม storage engine

ถ้าตอบหลังอยู่ใน memory เพียงตัวเดียว latency ต่ำแต่ process crash อาจทำข้อมูลหาย ถ้ารอ fsync และ quorum durability สูงขึ้นแต่ช้า API documentation ต้องบอกว่าคำว่า acknowledged ทน failure ระดับใด

16Read Path และ Read Amplification

การอ่านอาจตรวจ cache, memory table, index, SSTables หลายไฟล์ และ replicas หลายตัว Bloom filter ช่วยบอกไฟล์ที่ไม่น่ามี key ลด I/O แต่ false positive ยังเกิดได้ Compaction รวมไฟล์และลบ version เก่า แต่ใช้ I/O เบื้องหลัง

ระบบ write-optimized อาจเขียนเร็วโดยเลื่อนงานไปตอนอ่าน/compaction Trade-off จึงไม่หาย เพียงย้ายเวลาและ resource ไปส่วนอื่น ต้องวัด foreground latency พร้อม background backlog

17B-Tree กับ LSM-Tree

มิติB-Tree familyLSM-Tree family
Writeอัปเดต pages แบบ randomAppend log/memtable แล้ว flush sequential
Readค้นผ่าน tree ไป page ที่เกี่ยวข้องอาจตรวจหลาย levels/files ใช้ index/Bloom ช่วย
BackgroundPage split/mergeCompaction และ write amplification
เหมาะกับRead-heavy และ transactional access หลายแบบWrite-heavy, log/time-series และ distributed stores หลายชนิด

การเลือก storage engine ต้องดู read/write ratio, key distribution, range scan, durability และ SSD behavior ไม่ใช่ชื่อฐานข้อมูลอย่างเดียว

18Distributed File System กับ Object Storage

Distributed file system ให้ hierarchical namespace และ file semantics ส่วน object storage ใช้ key/object API และออกแบบให้ object เป็นก้อนใหญ่ค่อนข้าง immutable แยก metadata กับ data และ scale namespace ได้ต่างกัน

มิติFileObject
ชื่อDirectory/pathBucket/key
แก้ข้อมูลRandom read/write ตาม semanticsมักเขียน object ใหม่หรือ multipart
เหมาะกับShared files และ legacy/POSIX-like appsData lake, media, backup, artifacts
ปัญหาMetadata และ lockingSmall objects, listing และ request cost

19Erasure Coding กับ Replication

Replication สามชุดอ่านและซ่อมง่ายแต่ใช้พื้นที่ 3 เท่า Erasure coding แบ่งข้อมูลเป็น k fragments และ parity m fragments ทนการหายบางส่วนด้วย overhead ต่ำกว่า แต่ encode/decode และ repair ซับซ้อนกว่า

ข้อมูลร้อนอาจ replicate เพื่อ latency และ repair เร็ว ส่วนข้อมูลเย็นใช้ erasure coding ประหยัดพื้นที่ การเลือกต้องดู failure domain, bandwidth repair และเวลาที่ระบบอยู่ใน degraded state

20Cache-Aside, Read-Through และ Write Policies

Patternลำดับข้อควรระวัง
Cache-asideApp อ่าน cache; miss จึงอ่าน DB แล้วเติมRace, stale และ stampede
Read-throughCache layer โหลดต้นทางให้ผูกกับ loader semantics
Write-throughเขียน cache และ backing store ก่อนตอบWrite latency สูงขึ้น
Write-backตอบหลัง cache แล้ว flush ภายหลังDurability และ ordering ซับซ้อน
Database กับ Cache เปลี่ยนพร้อมกันไม่ได้จริง
ถ้าเขียน DB สำเร็จแต่ลบ cache ล้ม ผู้ใช้เห็นค่าเก่า หากลบ cache ก่อนแต่ transaction abort ก็สร้าง miss โดยไม่จำเป็น ต้องเลือก failure behavior, retry และ TTL ให้ชัด ไม่หวัง atomicity ข้ามสองระบบโดยไม่มี protocol

21Memcached กับ Redis: อย่าเลือกจากคำว่า In-Memory เหมือนกัน

Memcached เน้น distributed key-value cache ที่เรียบง่าย Client-side hashing กระจาย keys และข้อมูลหายได้ตามธรรมชาติของ cache Redis เพิ่ม data structures, persistence, replication, scripting/transactions และ stream capabilities จึงอาจเป็น cache, coordination primitive หรือ data service

ความสามารถเพิ่มไม่ได้ฟรี การใช้ Redis เป็น source of truth ต้องออกแบบ durability, failover และ memory policy ต่างจากใช้เป็น cache ที่สร้างใหม่ได้ ต้องเรียกบทบาทให้ถูกก่อนเลือก configuration

22Cache Eviction และ Admission

LRU โดยประมาณเก็บของที่เพิ่งใช้ LFU เก็บของใช้บ่อย TTL จำกัดอายุ แต่ cache ขนาดจำกัดอาจถูก scan workload ไล่ของร้อนออก Admission policy ตัดสินก่อนว่าของใหม่ควรเข้าหรือไม่ ไม่ใช่รับทุกอย่างแล้วค่อยไล่

ควรวัด hit ratio แยกตาม traffic/bytes และ miss penalty Cache ที่ hit 99% แต่ 1% miss เป็น query หนักอาจยังสร้างคอขวด ค่าที่ต้อง optimize คือเวลาและโหลดที่ประหยัด ไม่ใช่เปอร์เซ็นต์สวยเพียงตัวเดียว

23Cache Stampede, Penetration และ Avalanche

ใช้ jitter TTL, request coalescing, stale-while-revalidate, rate limit และ warm-up แบบค่อยเป็นค่อยไป Cache เป็นกลไก performance แต่ failure ของมันต้องไม่กลายเป็น traffic amplifier ทำลาย source of truth

24NewSQL และ Distributed SQL

Distributed SQL พยายามรักษา relational model, SQL และ transactions ขณะ scale ข้าม nodes มักแบ่ง key ranges และใช้ consensus ต่อ shard/range พร้อม transaction protocol ข้าม shards

ความสะดวกของ SQL ไม่ลบ physical distribution Cross-shard join/transaction ยังแพงกว่า local operation Schema และ primary key ควรทำให้ transaction สำคัญอยู่ shard เดียวเมื่อเป็นไปได้

25Event Log และ Stream Processing

Append-only log แยก producers กับ consumers เก็บลำดับต่อ partition และ replay ได้ เหมาะกับ event integration, CDC และ stream processing Partition key กำหนดทั้ง ordering และ load balance

26Change Data Capture และ Materialized View

CDC อ่านการเปลี่ยนจาก database log แล้วส่ง event ไป search index, cache หรือ analytics store ช่วยหลีกเลี่ยง dual write จาก application แต่ระบบปลายทางล่าช้าและต้องรับ schema evolution

Materialized view เก็บรูปข้อมูลที่คำนวณไว้สำหรับ query เฉพาะ ลด read latency แลกกับ update pipeline และ eventual consistency ต้องวัด freshness และ rebuild path หาก view เสีย

27Search Index ไม่ใช่ Database สำเนาธรรมดา

Inverted index ทำให้ค้นคำและ ranking เร็ว แต่ update/consistency semantics ต่างจาก transactional database มักใช้ database เป็น source of truth และ index เป็น derived view ผ่าน CDC

หาก index update หาย ต้องมี reconciliation หรือ rebuild ผู้ใช้ควรเห็นสถานะที่เหมาะสม เช่นรายการสร้างแล้วแต่อาจค้นหาได้ช้าครู่หนึ่ง แทนการสมมติ dual write atomic โดยไม่มีหลักประกัน

28Schema Evolution

ระบบหลาย services deploy ไม่พร้อมกัน Producer ใหม่อาจส่ง field เพิ่ม ขณะที่ consumer เก่ายังทำงาน Schema ที่ดีต้อง forward/backward compatible และกำหนด default/optional semantics

29Multi-Tenancy และ Noisy Neighbor

หลาย tenants แชร์ database/cache ลดต้นทุนแต่ tenant ใหญ่แย่ง connection, memory และ IOPS ต้องมี quota, workload isolation และ per-tenant observability

รูปแบบมีตั้งแต่ shared tables, schema ต่อ tenant, database ต่อ tenant ไปจน cluster แยก Isolation สูงขึ้นแต่ operational cost เพิ่ม การเลือกขึ้นกับ compliance, scale distribution และ customization

30Hot Partition และ Mitigation

Key ยอดนิยม, sequential timestamp หรือ tenant ใหญ่ทำ partition ร้อน แนวทางแก้ได้แก่ salting key, split range, adaptive partition, caching และแยก write counter เป็น shards ย่อยแล้วรวมภายหลัง

Salting แลก write balance กับ read complexity
กระจาย user123 เป็น user123#0..#9 ทำให้ writes กระจาย แต่การอ่านรวมต้อง query หลาย keys และ aggregate อย่าแก้ hotspot โดยไม่คำนวณต้นทุน read path ใหม่

31Data Locality และ Compute Pushdown

เมื่อข้อมูลใหญ่ การย้ายข้อมูลไป compute แพงกว่าย้ายคำสั่งไปหา storage ระบบ query จึง push filter, projection และ aggregation ลงใกล้ data ลด bytes ที่ส่งกลับ Columnar format ช่วยอ่านเฉพาะ columns และ compression ลด I/O

หลักนี้สืบต่อจาก cache blocking ใน PS 1–4 ต่างกันเพียงระยะทาง จาก register/cache ไป disk/object store และ network rack แก่นคือใช้ข้อมูลซ้ำใกล้จุดประมวลผลและไม่เคลื่อน bytes ที่ไม่จำเป็น

32Data Tiering

Tierลักษณะตัวอย่างข้อมูล
Hotเข้าถึงบ่อย latency ต่ำ ราคาแพงActive sessions, current inventory
Warmเข้าถึงเป็นครั้งคราวRecent logs และ historical profile
Cold/Archiveเข้าถึงน้อย retrieval ช้า ราคาต่ำCompliance archive และ backup เก่า

Lifecycle policy ย้ายข้อมูลตามอายุหรือการใช้งาน แต่ต้องทดสอบ retrieval เพราะเหตุการณ์ audit อาจต้องข้อมูลเย็นภายใน deadline ที่ชั้น archive ให้ไม่ได้

33Observability ของ Data Service

Cluster average ซ่อน shard ร้อน ควรดู distribution ต่อ partition/tenant แต่ระวัง label cardinality จน monitoring system กลายเป็น data service ที่ scale ไม่ไหวเสียเอง

34Capacity Planning

  1. ประมาณ data growth, retention และ replication/encoding overhead
  2. แยก read/write QPS และ request size
  3. วัด working set ที่ต้องอยู่ memory/cache
  4. เผื่อ compaction, repair, backup และ rebalance traffic
  5. กำหนด headroom สำหรับ failure หนึ่ง node/zone
  6. ทดลอง load จริงและ skew ไม่ใช้ค่าเฉลี่ย uniform อย่างเดียว
N+1 Capacity
ถ้า cluster ทำงานเต็ม 90% ในภาวะปกติ เมื่อ node หนึ่งล่ม งานของมันย้ายไปคนอื่นแล้วทุกตัวอาจอิ่ม Capacity ที่ดูประหยัดจึงไม่มีพื้นที่สำหรับ recovery

35กรณีศึกษา: ระบบขายบัตรที่มี Traffic พุ่ง

  1. CDN/cache ข้อมูลกิจกรรมที่อ่านบ่อย
  2. Admission queue จำกัดผู้เข้าสู่ purchase flow
  3. Inventory ใช้ strong coordination ต่อ seat/section ป้องกันขายซ้ำ
  4. Reservation มี lease/expiry และ idempotency key
  5. Payment ผ่าน saga/compensation ไม่ถือ distributed lock ระหว่าง network call ยาว
  6. Event log ส่ง notification/analytics นอก critical path

ไม่ควรใช้ consistency level เดียวทั้งระบบ หน้า event ยอม stale ได้ แต่สิทธิ์ซื้อที่นั่งเดียวกันต้องเข้ม การแบ่งตาม invariant ช่วยรักษาความถูกต้องโดยไม่บังคับทุก request จ่ายต้นทุนสูงสุด

36แล็บและแบบฝึกที่แนะนำ

แล็บ Sharding
สร้าง key distribution แบบ uniform และ Zipf เปรียบเทียบ modulo, consistent hashing และ range partition วัด balance และจำนวน key ที่ย้ายเมื่อเพิ่ม node
แล็บ Cache
Implement cache-aside พร้อม TTL จากนั้นฉีด hot key และ simultaneous expiry เพิ่ม coalescing/jitter แล้ววัด database QPS กับ tail latency
Data Architecture Review
ให้ระบุ source of truth, derived views, consistency, durability acknowledgement, backup/restore และ reshard path ของระบบหนึ่ง ห้ามใช้คำว่า scalable โดยไม่มีตัวเลข workload

37Transactions และขอบเขต Atomicity

Transaction ภายใน database เดียวให้ atomicity ตามระดับที่เลือก แต่เมื่อ operation ครอบคลุมหลาย shards, cache, queue และ payment gateway ขอบเขตเดิมไม่ครอบคลุมทั้งหมด

แนวทางเหมาะเมื่อต้นทุน
Local transactionInvariant อยู่ฐาน/shard เดียวง่ายและเร็ว จึงควรออกแบบ boundary ให้ใช้ได้
2PCต้อง atomic ข้าม participants ที่รองรับCoordination, blocking และ availability
SagaWorkflow ยาวและยอม intermediate stateCompensation, idempotency และ anomaly
Outbox/CDCส่ง event สอดคล้อง DB commitDuplicate และ propagation lag

38Secondary Index บนข้อมูลที่ถูกแบ่ง

Primary key บอก shard ได้ตรง แต่ query ตาม field อื่นต้องมี secondary index หาก index local ต่อ shard การค้นหาที่ไม่รู้ shard ต้อง scatter ทุก shard หาก global index lookup เร็วแต่ update และ consistency ซับซ้อน

Search index หรือ denormalized lookup table เป็น derived state ต้องมี repair/rebuild และบอก freshness การเพิ่ม query flexibility สร้าง write amplification กับ storage เพิ่มเสมอ

39Data Quality และ Correctness

ระบบ scale ได้แต่ข้อมูลผิดก็เพียงผลิตคำตอบผิดได้เร็วขึ้น ควรกำหนด schema validation, uniqueness, referential expectations และ reconciliation ระหว่าง source กับ derived views

40Online Migration และ Backfill

  1. เพิ่ม schema ใหม่แบบ compatible
  2. Deploy writers ที่รองรับรูปเก่าและใหม่
  3. Backfill แบบ rate-limited ไม่แย่ง foreground
  4. ตรวจ counts, checksum และ invariants
  5. ย้าย readers แบบ canary
  6. เก็บกวาดหลัง rollback window

Backfill เป็น workload จริงที่ทำ cache churn, compaction และ replica lag ต้อง pause/resume, checkpoint และ observability ไม่ใช่ script ครั้งเดียวที่หวังให้จบ

41Privacy, Retention และการลบ

ข้อมูลอาจอยู่ใน primary, replicas, cache, index, log, backup และ analytics การลบจากตารางเดียวไม่ใช่ลบทั้งระบบ ต้องมี inventory, retention และ deletion propagation

Backup immutable อาจไม่ลบ record รายชิ้นทันที จึงต้องกำหนดอายุและควบคุม restore ไม่ให้ข้อมูลที่ต้องลบกลับมาโดยไม่มี re-deletion process

42Checklist สำหรับ Data Architecture

คำถามสุดท้ายก่อนเลือกฐานข้อมูล

อย่าเริ่มจากตารางเปรียบเทียบชื่อผลิตภัณฑ์ ให้เริ่มจาก workload, invariant, query pattern, growth, RTO/RPO และ failure ที่ต้องทน จากนั้นจึงถามว่า service ใดให้ semantics ที่ต้องการด้วยต้นทุนที่ทีมดูแลได้ ฐานข้อมูลที่มี feature มากที่สุดอาจไม่เหมาะ หาก feature สำคัญของระบบคือสิ่งที่ทีมยังไม่เข้าใจเวลามันล้ม

การทำ proof of concept ควรมี skew, node failure, backup restore และ reshard ไม่ใช่ทดสอบ insert/read บนข้อมูล uniform เพียงอย่างเดียว เพราะ data service มักดูดีในวันที่ทุกอย่างปกติ และแสดงสถาปัตยกรรมจริงในวันที่ต้องย้ายหรือกู้ข้อมูลครับ

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

Parallel Systems เริ่มจากการถามว่างานแบ่งตรงไหนได้ จากนั้นพบว่าความเร็วไม่ได้ขึ้นกับจำนวนหน่วยคำนวณอย่างเดียว แต่ขึ้นกับ dependency, locality, granularity, communication และ architecture เมื่อขยายออกเป็นบริการขนาดใหญ่ คำถามเดิมยังอยู่ เพียง data movement ไกลขึ้นและ failure มีหลายระดับขึ้น

บริการข้อมูลทำให้ภาพทั้งวิชามาบรรจบกัน Sharding คือ decomposition Replication คือการใช้ทรัพยากรหลายชุดเพื่อ availability และ read scale Cache คือ locality Queue คือการจัด ordering/backpressure และ benchmark คือหลักฐานว่าการออกแบบคุ้มจริงหรือไม่

ขั้นตอนถัดไปที่เหมาะคือทำ capstone หนึ่งระบบ โดยเริ่มจาก workload และ invariant แล้วออกแบบ compute path, data path, partition, cache, failure recovery และ measurement plan ก่อนเลือกเทคโนโลยี เป้าหมายไม่ใช่ใช้เครื่องมือให้ครบ แต่คืออธิบายได้ว่าทุกชิ้นแก้คอขวดใด และสร้างต้นทุนใหม่ตรงไหนครับ

เส้นทางที่วิชานี้พาเดินผ่านมา
วิชานี้เริ่มจากคำถามเล็กที่สุด — "ทำไมซีพียูตัวเดียวไม่พอ" (บทที่ 1-2) — แล้วขยายออกทีละชั้น: ประเภทของงานขนาน (บทที่ 3), สถาปัตยกรรมฮาร์ดแวร์ที่รองรับ (บทที่ 4), เครื่องมือเขียนโปรแกรมจริง (บทที่ 5), วิธีวัดว่า "ขนานแล้วคุ้มไหม" อย่างเป็นวิทยาศาสตร์ (บทที่ 6) แล้วจึงยกระดับจาก "ขนานในเครื่องเดียว" ไปสู่ "ขนานข้ามเครื่องนับพัน" (บทที่ 7-9) ซึ่งเป็นจุดที่ปัญหาของ Parallel Systems กับปัญหาของ Distributed Systems มาบรรจบกัน — สองวิชานี้จึงไม่ใช่สองเรื่องที่แยกขาดจากกัน แต่เป็นสเกลที่ต่อเนื่องกันของปัญหาเดียวกัน: จะทำให้งานหลายชิ้นทำงานร่วมกันได้อย่างถูกต้องและมีประสิทธิภาพได้อย่างไร
คำถามซ้อมสอบ
  1. อธิบายโครงสร้างสอง tier ของ MySQL NDB Cluster (SQL layer และ Storage layer) และบทบาทของแต่ละประเภท node
  2. เมื่อ Data Node หนึ่งใน NDB Cluster ล้มเหลว ระบบตอบสนองอย่างไร และทำไมจึงต้องมี node เหลืออย่างน้อย 1 ตัวต่อ node group เสมอ
  3. อธิบายว่า GlusterFS หาตำแหน่งไฟล์ได้อย่างไรโดยไม่ต้องมี metadata server กลาง และข้อดี/ข้อเสียของแนวทางนี้คืออะไร
  4. ยกตัวอย่างการใช้งาน Memcached ร่วมกับ MySQL เพื่อลดภาระของฐานข้อมูล พร้อมอธิบายว่าทำไมวิธีนี้จึงช่วยได้
  5. เปรียบเทียบว่าสถาปัตยกรรมแบบ Facebook ที่เอกสารต้นฉบับยกมา ใช้เทคนิคจากบทที่ 7, 8 และ 9 ร่วมกันอย่างไร และหากออกแบบระบบเดียวกันนี้ในปี 2026 จะเลือกใช้เทคโนโลยีอะไรแทนแต่ละชั้นบ้าง