Database Sharding
แบ่ง data ไปหลาย DB instances (คนละ server) — ระดับถัดไปจาก Database Partitioning ที่แบ่งใน DB เดียว
| Database Partitioning | Sharding | |
|---|---|---|
| ขอบเขต | 1 DB instance | หลาย DB instances |
| เห็นจาก app | 1 ตาราง | หลาย databases — app ต้องรู้ว่า query ไป server ไหน |
Consistent Hashing
ใช้ hash function บน sharding key (เช่น user_id) → ผลลัพธ์ → modulo จำนวน shards → ได้ shard target
shard_id = hash(user_id) % num_shardsPitfall: ใช้
hash % Nตรง ๆ → เพิ่ม shard ใหม่ → N เปลี่ยน → key ส่วนใหญ่ rehash ใหม่หมด!
ทางแก้: Consistent Hashing แบบ ring (Cassandra, DynamoDB ใช้) — เพิ่ม shard rehash แค่ส่วนน้อย
Pros
- Scalability: data + memory + CPU กระจายไปหลาย server
- Security: user ถูกจำกัดให้เห็นแค่ shard ของตัวเอง (multi-tenant)
- Index ขนาดเล็ก: แต่ละ shard มี index ของตัวเอง → fit memory → query เร็ว
Cons (และเป็นเรื่องใหญ่!)
- Complex client — app ต้องรู้ logic ของ sharding
- Cross-shard transactions ยาก — ต้อง 2-phase commit หรือ Saga pattern
- Rollback ข้าม shard — shard 1 commit แต่ shard 2 fail → จัดการยาก
- Schema changes — ต้อง migrate ทุก shard พร้อมกัน
- Joins ข้าม shard — แทบทำไม่ได้ → app ต้อง fetch แล้ว join เอง
- ต้องมี sharding key ใน query — ไม่มี key → scatter-gather ทุก shard
Demo: Sharding ด้วย Postgres 3 instances
docker run -d --name pg1 -e POSTGRES_PASSWORD=pw -p 5432:5432 postgres
docker run -d --name pg2 -e POSTGRES_PASSWORD=pw -p 5433:5432 postgres
docker run -d --name pg3 -e POSTGRES_PASSWORD=pw -p 5434:5432 postgresimport hashlib
def get_shard(key):
h = int(hashlib.md5(key.encode()).hexdigest(), 16)
return h % 3 # 0, 1, 2 → ports 5432, 5433, 5434Modern Alternatives
- Vitess — สำหรับ MySQL, sharding layer ที่ app มอง 1 logical table
- Citus — extension สำหรับ PostgreSQL, distributed sharding
- CockroachDB — distributed SQL ที่จัดการ sharding ให้อัตโนมัติ
Pitfall ใหญ่สุด
Shard ก่อนวัด — ส่วนใหญ่ DB เดียวพอ → sharding เพิ่มความซับซ้อนมหาศาลโดยไม่จำเป็น
Rule of thumb: ถ้ายัง vertical scale ได้ (instance ใหญ่กว่า + read replicas) → ยังไม่ต้อง shard
Key Points
- Sharding = แบ่ง data ไปคนละ server — ต่างจาก partitioning ที่อยู่ DB เดียว
- Consistent Hashing แบบ ring ป้องกันการ rehash ทั้งหมดเมื่อเพิ่ม shard
- Cross-shard transactions/joins ยากมาก — ข้อเสียหลัก
- อย่า shard ก่อนเวลา — vertical scale + replicas ก่อน
- Modern tools (Vitess, Citus, CockroachDB) ช่วยซ่อนความซับซ้อน
Related
- Database Partitioning — ขั้นตอนก่อนหน้า shard
- Database Replication — read replicas เป็นทางเลือกก่อน shard
- CAP Theorem — sharding = distributed → ต้องเจอ CAP trade-offs
- Concurrency Control — cross-shard transactions ต้องใช้ 2-phase commit