- เมื่อต้นปีนี้ Notion ล่มเป็นเวลา 5 นาที และได้ทำ PostgreSQL sharding ที่ดำเนินการมาเป็นเวลาหลายเดือน
→ เริ่มมีเสียงตอบรับทันทีว่าระบบเร็วขึ้นมาก
- ตัดสินใจทำ sharding ตั้งแต่เมื่อไร
→ หลังจากเติบโตขึ้นหลายหมื่นเท่าในช่วง 5 ปีที่ผ่านมา Postgres monolith ที่ใช้งานได้ดีมาตลอดก็เริ่มเกินขีดความสามารถด้านปริมาณข้อมูล
→ VACUUM เริ่มถูกขัดจังหวะอย่างต่อเนื่อง และคาดว่าจะเกิด TXID wraparound ในไม่ช้า จึงเริ่มงาน sharding
- ออกแบบ sharding scheme
→ sharding ระดับแอปพลิเคชัน
⇨ จะ shard ข้อมูลอะไรบ้าง
⇨ จะแบ่งข้อมูลโดย partition ด้วยคีย์ใด
⇨ จะสร้าง shard กี่ตัว และควรจัดโครงสร้างอย่างไร
→ การตัดสินใจ #1
⇨ Notion มี data model ที่ประกอบขึ้นในระดับ block
⇨ ตัดสินใจ shard ทุกตารางที่เชื่อมกับตาราง block (เช่น Space, Discussion, Comment เป็นต้น)
→ การตัดสินใจ #2
⇨ block ถูก partition ตาม workspace ID
⇨ แต่ละ workspace มี UUID กำกับอยู่แล้ว จึงนำมาใช้
→ การตัดสินใจ #3
⇨ จัดโครงสร้างด้วย 480 logical shards และ 32 physical DB
เหตุผลที่เลือก 480 แทน 512 ซึ่งเป็นเลขยกกำลังของ 2 คือเป็นตัวเลขที่แบ่งย่อยได้ยืดหยุ่นกว่า
- ย้ายไปยัง shard
→ 1. เขียนข้อมูลซ้ำไปยัง Old & New DB ทั้งคู่ (พร้อม Audit Log)
→ 2. หลังเริ่ม dual-write แล้ว จึงเริ่ม backfill ข้อมูลจาก Old DB ไปยัง New DB
→ 3. ตรวจสอบความถูกต้องของข้อมูลใน New DB
→ 4. สลับไปใช้ New DB (ทำแบบ incremental)
- บทเรียนที่ได้มาอย่างยากลำบาก
→ ทำ sharding ให้เร็วกว่านี้: เพราะรอจนภาระของ DB เดิมสูงมาก การ migration เองก็กลายเป็นภาระเพิ่ม จึงทำได้อย่างช้าๆ เท่านั้น
→ ตั้งเป้า migration แบบ zero downtime: throughput ของการทำ dual-write เป็นคอขวดสำคัญในช่วงสลับระบบสุดท้าย
→ ใช้ composite PK แทน partition key แยกต่างหาก: หากนำ id ซึ่งเป็น PK ของ DB เดิมมารวมกับ space_id ซึ่งเป็น partition key ก็อาจไม่จำเป็นต้องส่ง space_id ไปมาภายในแอป
1 ความคิดเห็น
เรื่องของ TXID ใน Postgres เป็นหัวข้อที่ถูกพูดถึงอยู่เสมอ
ข้อบกพร่องของ PostgreSQL https://th.news.hada.io/topic?id=1829
สิ่งที่ได้เรียนรู้จากการสเกล PostgreSQL ตลอด 5 ปี https://th.news.hada.io/topic?id=4101