Scaling & Reliability — ขยายระบบและกำจัดจุดตาย
Vertical/Horizontal Scaling · Load Balancing · SPOF · Replication · ▶ ในคลิป 0:12:40 – 0:29:50
เมื่อทราฟฟิกโตจนเครื่องเดียวรับไม่ไหว มีทางเลือกสองทาง: ทำให้เครื่อง ใหญ่ขึ้น หรือทำให้เครื่อง เยอะขึ้น บทนี้ว่าด้วยการเลือกทาง, เครื่องมือที่ทำให้ "เยอะขึ้น" เป็นจริงได้ (load balancer) และหลักคิดที่สำคัญกว่าความเร็ว — ระบบต้องไม่ตายเพราะชิ้นส่วนเดียวพัง
3.1 Vertical vs Horizontal Scaling
| มิติ | Vertical (Scale Up) | Horizontal (Scale Out) |
|---|---|---|
| วิธี | เพิ่ม CPU/RAM เครื่องเดิม | เพิ่มจำนวนเครื่อง |
| แก้โค้ด | แทบไม่ต้อง | ต้องทำแอปให้ stateless |
| เพดาน | มี — ฮาร์ดแวร์ใหญ่สุดในตลาด | แทบไม่มี |
| ความทนทาน | ยังเป็น SPOF | เครื่องหนึ่งตาย ที่เหลือรับแทน |
| ราคา | แพงขึ้นแบบ exponential | เพิ่มแบบ linear ตามจำนวนเครื่อง |
3.2 Load Balancer — จราจรกลางของระบบ
Load balancer (LB) คือด่านหน้าที่รับทุก request แล้วกระจายไปยังเซิร์ฟเวอร์ที่ "ยังแข็งแรง" เบื้องหลัง ทำสองหน้าที่พร้อมกัน: กระจายโหลด ให้ไม่มีเครื่องไหนล้น และ ตรวจสุขภาพ (health check) เพื่อหยุดส่งงานให้เครื่องที่ตาย
อัลกอริทึมกระจายโหลดที่ต้องรู้
| อัลกอริทึม | วิธีทำงาน | เหมาะกับ |
|---|---|---|
| Round Robin | วนส่งทีละเครื่องตามคิว 1→2→3→1... | เซิร์ฟเวอร์สเปกเท่ากัน งานแต่ละชิ้นหนักพอ ๆ กัน |
| Weighted Round Robin | วนตามคิวแต่เครื่องแรงรับสัดส่วนมากกว่า | เครื่องสเปกไม่เท่ากัน (ช่วงเปลี่ยนผ่านฮาร์ดแวร์) |
| Least Connections | ส่งให้เครื่องที่มีงานค้างน้อยที่สุด | งานแต่ละชิ้นใช้เวลาไม่เท่ากัน (เช่นมี request ช้า ๆ ปน) |
| IP Hash | hash IP ผู้ใช้ → ผู้ใช้เดิมไปเครื่องเดิมเสมอ | ต้องการ session affinity โดยไม่มี shared store |
LB ยังแบ่งตามชั้นที่ทำงาน: L4 (Transport) ดูแค่ IP/port — เร็วมาก ส่วน L7 (Application) อ่าน HTTP ได้ จึง route ตาม path ได้ (เช่น /api/video ไปเครื่องกลุ่มหนึ่ง /api/chat ไปอีกกลุ่ม) แลกกับ overhead ที่สูงกว่า
3.3 Single Point of Failure — ศัตรูหมายเลขหนึ่ง
SPOF คือชิ้นส่วนใดก็ตามที่ถ้าพังแล้วทั้งระบบหยุด วิธีไล่หามันคือชี้ไปที่ทุกกล่องในไดอะแกรมแล้วถามว่า "ถ้ากล่องนี้หายไปตอนนี้ ระบบยังเดินไหม" — คำตอบ "ไม่" ทุกจุดคือการบ้าน และยาแก้มีตัวเดียวคือ redundancy (มีสำรอง):
- Web/App tier — มีหลายเครื่องหลัง LB อยู่แล้วจากการ scale out
- Load balancer เองก็เป็น SPOF! — แก้ด้วย LB คู่ (active-passive) + failover อัตโนมัติ หรือใช้ DNS กระจายไปหลาย LB
- Database — ตัวที่มักถูกลืม แก้ด้วย replication (ถัดไป)
- ทั้ง Data Center — ระดับสูงสุด: กระจายหลาย Availability Zone / หลาย region
คำถามที่ตามมาจากการไล่ SPOF เสมอคือ "กำจัดจนระบบทนแค่ไหนถึงจะพอ" — วงการวัดค่านี้ด้วย "จำนวนเก้า" (nines) ของ availability:
| Availability | เรียกว่า | ดาวน์ได้สูงสุด/ปี |
|---|---|---|
| 99% | two nines | ~3.65 วัน |
| 99.9% | three nines | ~8.8 ชั่วโมง |
| 99.99% | four nines | ~52 นาที |
| 99.999% | five nines | ~5.3 นาที |
ทุก "เก้า" ที่เพิ่ม = ต้นทุนและ redundancy ที่ต้องเพิ่มเป็นเท่าตัว — กำหนดเป้าตามความสำคัญของระบบก่อนเสมอ (payment gateway ไล่ 99.99%+ ขณะที่ระบบภายในอาจพอใจ 99.9%) แล้วออกแบบ redundancy ให้พอดีเป้า ไม่ใช่มากที่สุดเท่าที่ทำได้
3.4 Database Replication — ฐานข้อมูลก็ต้องมีตัวสำรอง
โครงสร้างมาตรฐานคือ Primary–Replica (หรือ leader–follower): เขียนที่ primary ตัวเดียว แล้วข้อมูลถูกส่งต่อ (replicate) ไปยัง replica หลายตัวซึ่งรับหน้าที่ อ่าน — ได้ประโยชน์สองต่อ: กระจายโหลดอ่าน (ระบบส่วนใหญ่อ่านมากกว่าเขียนหลายเท่า) และเป็นตัวสำรองเมื่อ primary ตาย
3.5 Database Sharding — เมื่อ Replication ไม่พอ
Replication ที่เล่าไปแก้ปัญหาการ อ่าน ได้ดี แต่ไม่ช่วยเรื่อง เขียน หรือ พื้นที่เก็บข้อมูล เลย — เพราะเขียนได้ที่ primary ตัวเดียวเสมอ และทุก replica ต้องเก็บสำเนาข้อมูล "ทั้งหมด" เท่ากับ primary เมื่อข้อมูลใหญ่เกินดิสก์เครื่องเดียว หรือเขียนถี่เกินที่ primary ตัวเดียวรับไหว ทางออกคือ Sharding (horizontal partitioning): ตัดแถวของตารางเดียวกันออกเป็นส่วน ๆ กระจายไปอยู่คนละเครื่อง (shard) ที่แต่ละตัวรับทั้งอ่านและเขียนของส่วนตัวเองอย่างอิสระ
| กลยุทธ์ | วิธีแบ่ง | ข้อแลก |
|---|---|---|
| Range-based | แบ่งตามช่วงของ shard key เช่น user_id 1–1M → shard 1 | Query แบบช่วงทำง่าย แต่เสี่ยง "shard ร้อน" ถ้าข้อมูลใหม่กระจุกที่ shard ล่าสุด |
| Hash-based | hash(shard key) กระจายแถวให้เกลี่ยเท่า ๆ กันทุก shard | กระจายสม่ำเสมอ แต่ query แบบช่วงทำไม่ได้ และเพิ่ม/ลด shard ต้อง reshuffle ข้อมูลจำนวนมาก (บรรเทาได้ด้วย consistent hashing) |
| Directory-based | มี lookup table กลางคอยจำว่า key ไหนอยู่ shard ไหน | ยืดหยุ่นที่สุด ย้ายข้อมูลทีละส่วนได้ แต่ lookup service เองต้องดูแลเรื่อง availability เพิ่มอีกชั้น |
✅ สรุปบทที่ 3 — Scale up ง่ายแต่มีเพดาน → scale out คือทางหลักของระบบใหญ่ โดยมีเงื่อนไขว่าแอปต้อง stateless · LB กระจายงาน + health check ตัดเครื่องตาย (Round Robin / Least Connections / IP Hash) · ไล่ฆ่า SPOF ทุกชั้น — อย่าลืมว่า LB และ DB ก็ตายได้ · DB ใช้ primary–replica เพื่อกระจายโหลดอ่านและรองรับ failover · เขียน/พื้นที่เก็บไม่พอค่อย sharding — แลกมาด้วย JOIN ข้าม shard ที่ยากขึ้นและ reshard ที่แพง