Scalable Data Services
บทปิดท้าย — ทุกเทคนิคก่อนหน้านี้ (ขนานในซีพียู, MPI/CUDA, สถาปัตยกรรมระบบใหญ่, cloud) สุดท้ายต้องมาบรรจบที่คำถามเดียวกัน: ข้อมูลอยู่ที่ไหน และทำอย่างไรให้เข้าถึงได้เร็วพอเมื่อผู้ใช้มีหลักล้านคน บทนี้ดูสามเทคนิคคลาสสิกที่ตอบคำถามนั้นจากคนละมุม
1ปัญหาตั้งต้น: ทำไม Data Service ถึงเป็นคอขวด
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
มักเป็น MySQL server (
mysqld) ที่แอปพลิเคชันเชื่อมต่อผ่าน SQL ตามปกติ — แต่ละ SQL node เชื่อมต่อไปยังทุก Data nodeData 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) |
3Distributed File System: กรณีศึกษา GlusterFS
เก็บข้อมูลเป็นไฟล์/โฟลเดอร์ปกติ ใช้ token (extended attribute ของไฟล์) ระบุตำแหน่งไฟล์แบบกระจาย — Gluster แปลงชื่อไฟล์ที่ร้องขอเป็น token แล้วเข้าถึงไฟล์โดยตรง ไม่ต้องมี metadata server กลาง (ต่างจากระบบไฟล์แบบ centralized-metadata อย่าง GFS/HDFS ยุคแรก)
ทำสำเนาข้อมูลอัตโนมัติข้ามหลาย storage ให้ high availability (auto fail-over) และ auto self-healing (ซ่อมแซมสำเนาที่เสียหายอัตโนมัติ) ใช้ load balancing ช่วยกระจายการเข้าถึงสำเนาที่ replicate ไว้
4In-Memory Caching: กรณีศึกษา Memcached
// ตัวอย่างจากเอกสารต้นฉบับ — 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
SELECT * FROM users WHERE userid = ? — ครั้งแรก query ไปที่ฐานข้อมูลแล้วเก็บผลลง Memcached ครั้งต่อไปอ่านจาก cache โดยตรง (เร็วกว่าอ่านดิสก์ของฐานข้อมูลมาก) ลดภาระที่ตกไปยังฐานข้อมูลจริงลงอย่างมาก5ประกอบร่างทั้งหมด: สถาปัตยกรรมแบบ Facebook (ตามที่เอกสารต้นฉบับอ้างถึง)
6จาก NDB, GlusterFS และ Memcached ไปสู่ระบบปัจจุบัน
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 ข้าม nodes | Availability หาก shard มีสำเนาเดียว |
9Sharding และการเลือก Partition Key
Hash partition กระจาย key ได้สม่ำเสมอแต่ range scan ข้าม shards Range partition เหมาะกับช่วงแต่เสี่ยง hotspot ที่ปลายใหม่ Directory-based mapping ยืดหยุ่นแต่ metadata service กลายเป็น dependency สำคัญ
- Key ต้องมี cardinality และกระจาย traffic
- Query สำคัญควรแตะ shards ให้น้อย
- หลีกเลี่ยง timestamp ตรง ๆ หาก writes ทั้งหมดลงปลายเดียว
- คิดถึง tenant ใหญ่ที่หนักกว่าค่าเฉลี่ย
- วางแผน resharding ก่อน shard เต็ม
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 |
| Leaderless | Availability สูงและไม่มี leader ถาวร | Quorum, version conflict, read repair และ anti-entropy |
รูปแบบที่เหมาะขึ้นกับ write pattern และ invariant ข้อมูล profile อาจใช้ single writer ต่อผู้ใช้ ขณะที่ shopping cart อาจยอม merge ส่วน inventory ก่อน checkout ต้องเข้มกว่า
12Quorum และความหมายของ R, W, N
W + W > N
ในโลกจริง sloppy quorum อาจฝากข้อมูลบน node อื่นชั่วคราว เซต R และ W จึงไม่ใช่ owners ชุดเดียวเสมอ การตั้ง QUORUM ไม่ได้รับประกัน linearizability โดยอัตโนมัติ ต้องดู versioning, concurrent writes และ read path
13Consistency Model จากมุมผู้ใช้
- Linearizability — operation ดูเหมือนเกิดทันทีและเคารพลำดับเวลาจริง
- Sequential consistency — ทุกคนเห็นลำดับเดียวกัน แต่ไม่จำเป็นต้องตรงเวลาจริง
- Causal consistency — เหตุและผลรักษาลำดับ ส่วนเหตุการณ์อิสระต่างลำดับได้
- Eventual consistency — เมื่อหยุดเขียน สำเนาจะลู่เข้าหาค่าเดียวกันในที่สุด
- Session guarantees — read-your-writes และ monotonic reads ลดความงงของผู้ใช้
14CAP และ PACELC แบบไม่ใช้เป็นป้ายสินค้า
เมื่อ network partition ทำให้ replica สองฝั่งสื่อสารไม่ได้ ระบบเลือกได้ว่าจะปฏิเสธบาง operation เพื่อรักษา consistency หรือให้ทั้งสองฝั่งตอบต่อและยอมเห็นต่างชั่วคราว Partition tolerance เป็นสภาพที่ต้องรับมือ ไม่ใช่ feature ที่ติ๊กทิ้งได้ในเครือข่ายจริง
PACELC เติมว่าแม้ไม่มี partition ระบบยังเลือกระหว่าง latency กับ consistency เพราะการรอ replica ไกลยืนยันย่อมช้ากว่าตอบจากสำเนาใกล้ ระบบเดียวกันอาจเลือกต่างกันต่อ operation จึงไม่ควรติดป้ายฐานข้อมูลทั้งก้อนว่า CP/AP โดยไม่บอก configuration
15Write Path: คำว่า “สำเร็จ” ต้องมีความหมาย
- รับ request และตรวจ idempotency key
- เขียน write-ahead log
- อัปเดต memory structure หรือ page
- Replicate ไป replicas ตาม policy
- ตอบ client เมื่อถึง durability/consistency level
- 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 family | LSM-Tree family |
|---|---|---|
| Write | อัปเดต pages แบบ random | Append log/memtable แล้ว flush sequential |
| Read | ค้นผ่าน tree ไป page ที่เกี่ยวข้อง | อาจตรวจหลาย levels/files ใช้ index/Bloom ช่วย |
| Background | Page split/merge | Compaction และ 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 ได้ต่างกัน
| มิติ | File | Object |
|---|---|---|
| ชื่อ | Directory/path | Bucket/key |
| แก้ข้อมูล | Random read/write ตาม semantics | มักเขียน object ใหม่หรือ multipart |
| เหมาะกับ | Shared files และ legacy/POSIX-like apps | Data lake, media, backup, artifacts |
| ปัญหา | Metadata และ locking | Small 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-aside | App อ่าน cache; miss จึงอ่าน DB แล้วเติม | Race, stale และ stampede |
| Read-through | Cache layer โหลดต้นทางให้ | ผูกกับ loader semantics |
| Write-through | เขียน cache และ backing store ก่อนตอบ | Write latency สูงขึ้น |
| Write-back | ตอบหลัง cache แล้ว flush ภายหลัง | Durability และ ordering ซับซ้อน |
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
- Stampede — key ร้อนหมดอายุแล้วหลาย request rebuild พร้อมกัน
- Penetration — ขอ key ที่ไม่มีซ้ำ ๆ จนทะลุ cache ไป DB ใช้ negative cache/Bloom filter
- Avalanche — keys จำนวนมากหมดหรือ cache nodes ล่มพร้อมกัน ทำ origin รับโหลดมหาศาล
ใช้ 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
- Ordering มักรับประกันภายใน partition ไม่ใช่ทั้งระบบ
- Consumer group แบ่ง partitions ให้ consumers
- Lag บอกว่าผู้บริโภคตามหลังเท่าใด
- Retention ทำให้ replay ได้ภายในช่วง
- Exactly-once ต้องนิยามขอบเขตระหว่าง log, state และ sink
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
- เพิ่ม field แบบ optional ก่อนให้ผู้ใช้ field deploy ครบ
- อย่าเปลี่ยนความหมาย field เดิมเงียบ ๆ
- เก็บ version และ registry สำหรับ event contracts
- ใช้ expand-and-contract เมื่อเปลี่ยน database schema
- ทดสอบ replay event เก่ากับ code ใหม่
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 ย่อยแล้วรวมภายหลัง
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
- Read/write latency แยก percentile, operation และ shard
- Queue, connection pool และ saturation
- Replication lag, quorum failures และ replica health
- Cache hit/miss, eviction, hot keys และ stampede
- Disk space, IOPS, compaction backlog และ write amplification
- Slow query, scanned rows/bytes และ index usage
- Backup age, restore test และ data-integrity errors
Cluster average ซ่อน shard ร้อน ควรดู distribution ต่อ partition/tenant แต่ระวัง label cardinality จน monitoring system กลายเป็น data service ที่ scale ไม่ไหวเสียเอง
34Capacity Planning
- ประมาณ data growth, retention และ replication/encoding overhead
- แยก read/write QPS และ request size
- วัด working set ที่ต้องอยู่ memory/cache
- เผื่อ compaction, repair, backup และ rebalance traffic
- กำหนด headroom สำหรับ failure หนึ่ง node/zone
- ทดลอง load จริงและ skew ไม่ใช้ค่าเฉลี่ย uniform อย่างเดียว
35กรณีศึกษา: ระบบขายบัตรที่มี Traffic พุ่ง
- CDN/cache ข้อมูลกิจกรรมที่อ่านบ่อย
- Admission queue จำกัดผู้เข้าสู่ purchase flow
- Inventory ใช้ strong coordination ต่อ seat/section ป้องกันขายซ้ำ
- Reservation มี lease/expiry และ idempotency key
- Payment ผ่าน saga/compensation ไม่ถือ distributed lock ระหว่าง network call ยาว
- Event log ส่ง notification/analytics นอก critical path
ไม่ควรใช้ consistency level เดียวทั้งระบบ หน้า event ยอม stale ได้ แต่สิทธิ์ซื้อที่นั่งเดียวกันต้องเข้ม การแบ่งตาม invariant ช่วยรักษาความถูกต้องโดยไม่บังคับทุก request จ่ายต้นทุนสูงสุด
36แล็บและแบบฝึกที่แนะนำ
37Transactions และขอบเขต Atomicity
Transaction ภายใน database เดียวให้ atomicity ตามระดับที่เลือก แต่เมื่อ operation ครอบคลุมหลาย shards, cache, queue และ payment gateway ขอบเขตเดิมไม่ครอบคลุมทั้งหมด
| แนวทาง | เหมาะเมื่อ | ต้นทุน |
|---|---|---|
| Local transaction | Invariant อยู่ฐาน/shard เดียว | ง่ายและเร็ว จึงควรออกแบบ boundary ให้ใช้ได้ |
| 2PC | ต้อง atomic ข้าม participants ที่รองรับ | Coordination, blocking และ availability |
| Saga | Workflow ยาวและยอม intermediate state | Compensation, idempotency และ anomaly |
| Outbox/CDC | ส่ง event สอดคล้อง DB commit | Duplicate และ 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
- ตรวจ completeness, validity, uniqueness และ freshness
- เก็บ lineage ว่ามาจาก job/version ใด
- ทำ invariant checks หลัง migration/backfill
- Quarantine record ผิดแทนทิ้งเงียบ
- กำหนด owner และ incident path ของ dataset
40Online Migration และ Backfill
- เพิ่ม schema ใหม่แบบ compatible
- Deploy writers ที่รองรับรูปเก่าและใหม่
- Backfill แบบ rate-limited ไม่แย่ง foreground
- ตรวจ counts, checksum และ invariants
- ย้าย readers แบบ canary
- เก็บกวาดหลัง 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
- Source of truth และ derived views อยู่ที่ใด
- Shard key กระจาย bytes และ traffic หรือไม่
- Write acknowledgement ทน failure ระดับใด
- Read consistency ของแต่ละ use case คืออะไร
- Cache miss/stampede แล้ว source รับไหวหรือไม่
- Replication lag, repair และ reshard มี runbook หรือยัง
- Backup กู้ได้จริงใน RTO/RPO หรือไม่
- Schema/event evolution รองรับ deploy ไม่พร้อมกันหรือไม่
- Hot tenant/key ถูกจำกัดผลอย่างไร
- การลบครอบคลุมสำเนาทุกชั้นหรือไม่
คำถามสุดท้ายก่อนเลือกฐานข้อมูล
อย่าเริ่มจากตารางเปรียบเทียบชื่อผลิตภัณฑ์ ให้เริ่มจาก 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 ก่อนเลือกเทคโนโลยี เป้าหมายไม่ใช่ใช้เครื่องมือให้ครบ แต่คืออธิบายได้ว่าทุกชิ้นแก้คอขวดใด และสร้างต้นทุนใหม่ตรงไหนครับ
- อธิบายโครงสร้างสอง tier ของ MySQL NDB Cluster (SQL layer และ Storage layer) และบทบาทของแต่ละประเภท node
- เมื่อ Data Node หนึ่งใน NDB Cluster ล้มเหลว ระบบตอบสนองอย่างไร และทำไมจึงต้องมี node เหลืออย่างน้อย 1 ตัวต่อ node group เสมอ
- อธิบายว่า GlusterFS หาตำแหน่งไฟล์ได้อย่างไรโดยไม่ต้องมี metadata server กลาง และข้อดี/ข้อเสียของแนวทางนี้คืออะไร
- ยกตัวอย่างการใช้งาน Memcached ร่วมกับ MySQL เพื่อลดภาระของฐานข้อมูล พร้อมอธิบายว่าทำไมวิธีนี้จึงช่วยได้
- เปรียบเทียบว่าสถาปัตยกรรมแบบ Facebook ที่เอกสารต้นฉบับยกมา ใช้เทคนิคจากบทที่ 7, 8 และ 9 ร่วมกันอย่างไร และหากออกแบบระบบเดียวกันนี้ในปี 2026 จะเลือกใช้เทคโนโลยีอะไรแทนแต่ละชั้นบ้าง