☕ 5-Min Tech Story #55

Twitter Snowflake: ทำไมระบบสเกลโลกถึงเลิกใช้ Auto Increment และเกลียด UUID เข้าไส้?

⏱️ ใช้เวลาอ่านประมาณ: 4 นาที 20 วินาที

เมื่อระบบของคุณเติบโตจาก Database ก้อนเดียว กลายเป็น Microservices 20 ตัวที่พยายามสร้าง "ใบสั่งซื้อ" หรือ "โพสต์ใหม่" พร้อมกันหลักหมื่นรายการต่อวินาที...

คำถามแรกที่คุณจะเจอคือ: "เราจะสร้าง Primary Key (ID) ให้ข้อมูลเหล่านี้ยังไง ไม่ให้เลขชนกัน?"

🛑 ทางตันของเทคโนโลยีโบราณ

1. ใช้ Auto Increment (1, 2, 3...) ใน Database:

ถ้าให้ Database เป็นคนนับเลข ID = ID + 1 Database จะกลายเป็น คอขวด (Single Point of Failure) ทันที ทุก Microservice ต้องวิ่งมาต่อคิวรอ Database เครื่องเดียวเพื่อขอเลข ID ทำให้ระบบสเกลไม่ได้

2. เปลี่ยนไปใช้ UUID (สุ่มตัวอักษร 36 ตัว):

f47ac10b-58cc-4372-a567-0e02b2c3d479

การสุ่ม UUID สร้างเองที่ฝั่งแอปพลิเคชันได้เลย ไม่ต้องง้อ Database! แต่หายนะจะมาเยือนตอนที่คุณเอา UUID ไปทำ Primary Key / B-Tree Index

❄️ เกล็ดหิมะแห่ง Twitter (Snowflake ID)

วิศวกรของ Twitter (X) ได้คิดค้นโครงสร้าง ID ขึ้นมาใหม่ที่ตอบโจทย์ทั้งความเร็ว ขนาด และการจัดเรียง เรียกว่า Snowflake

หลักการคือ: แทนที่จะสุ่มมั่วๆ หรือให้ Database นับเลข... เราจะเอา "เวลา" "รหัสเครื่อง" และ "ตัวนับ" มาแพ็กอัดรวมกันในตัวเลข 64 บิต (BigInt) ก้อนเดียว!

โครงสร้าง 64 Bits ของ Snowflake

  • [1 Bit] Sign: เป็น 0 เสมอ (เพื่อให้ค่าเป็นบวก)
  • [41 Bits] Timestamp: เก็บเวลาหน่วยมิลลิวินาที (รองรับการใช้งานได้นานถึง 69 ปี!)
  • [10 Bits] Machine ID: รหัสประจำเครื่องเซิร์ฟเวอร์ (รองรับได้ 1,024 เครื่อง)
  • [12 Bits] Sequence Number: ลำดับที่วิ่งตั้งแต่ 0 - 4095

⚙️ มันทำงานอย่างไรในเสี้ยววินาที?

สมมติมี Microservice เครื่องที่ 42 กำลังสร้าง ID... โค้ดจะดึงเวลาปัจจุบันมา (สมมติว่าเป็นมิลลิวินาทีที่ 1,600,000,000) แล้วเติมรหัสเครื่อง 42 ลงไป

และถ้าใน 1 มิลลิวินาทีนั้น มีคำขอเข้ามา 5 รายการ ตัว Sequence จะนับ 0, 1, 2, 3, 4 แปะท้ายลงไป... แต่พอเข็มนาฬิกาขยับไปมิลลิวินาทีถัดไป Sequence จะถูกรีเซ็ตกลับเป็น 0 ใหม่ทันที!

"ด้วยบิต 12 ตัวสุดท้ายนี้... เซิร์ฟเวอร์ 1 เครื่อง สามารถสร้าง ID ที่ไม่ซ้ำกันได้ถึง 4,096 รายการ ภายใน 1 มิลลิวินาที (หรือ 4 ล้าน ID ต่อวินาที!) โดยไม่ต้องคุยกับใครเลย!"

🛡️ พลังที่โลก Distributed โหยหา

ผลลัพธ์ที่ได้จากการอัดข้อมูลลง 64-bit BigInt คือเวทมนตร์ 3 ประการ:

  1. Time-sortable (เรียงตามเวลาได้): เพราะ 41 บิตแรกคือเวลา! ID ที่สร้างทีหลังจะมีค่าตัวเลขสูงกว่าเสมอ ฐานข้อมูล B-Tree จึงบันทึกข้อมูลต่อท้าย (Append-only) ได้อย่างสวยงาม ไม่เกิด Page Split ทราฟฟิกพุ่งฉิว
  2. High Availability: ระบบไม่ต้องพึ่งพา Database ในการออกเลข Microservice ทุกเครื่องสามารถสร้าง ID ของตัวเองได้แบบ Local (Decentralized) 100%
  3. Compact (เล็กกะทัดรัด): ตัวเลข 64-bit ใช้พื้นที่แค่ 8 Bytes (เทียบกับ UUID ที่กิน 16 Bytes และเป็น String) ช่วยประหยัด RAM สำหรับ Index ไปได้เกินครึ่ง!

💡 5-Min Takeaway

"ปัญหาเรื่องคอขวด บางครั้งก็แก้ได้ด้วยการจัดระเบียบตรรกะระดับบิต" เมื่อระบบเข้าสู่โลกของ Microservices การผูกมัดตัวเองกับ Auto Increment ของฐานข้อมูลคือหายนะ จงหลีกเลี่ยง UUID ในฐานะ Primary Key หลัก และพิจารณาใช้สถาปัตยกรรมอย่าง Snowflake ID หรือ ULID ที่ผสานข้อดีของการสร้างแบบกระจายศูนย์ เข้ากับความสามารถในการจัดเรียงตามเวลา เพื่อปกป้องประสิทธิภาพของ Database ไว้ให้ทำงานได้สมบูรณ์ที่สุด