Database
น้องๆ เคยเจอไหม? อัพเดทระบบทีไร เว็บล่ม ร้านเน็ตเจ๊ง ลูกค้าหายหมด! นั่นแหละคือฝันร้ายของคนทำ IT สมัยผมทำร้านเน็ต SiamCafe.net นี่กลัวสุดๆ เพราะทุกนาทีที่ร้านปิดคือเงินที่หายไปเป็นกระบุง
Database Migration Zero Downtime คือการย้ายฐานข้อมูลโดยที่ระบบยังทำงานได้ตามปกติ ไม่มีช่วงเวลาที่ระบบหยุดทำงานเลยสักนิดเดียว คิดภาพตามนะ สมัยก่อนเราต้องปิดร้าน เปลี่ยนเฟอร์นิเจอร์ใหม่ แล้วค่อยเปิดร้านใหม่ แต่ Zero Downtime คือเปลี่ยนเฟอร์นิเจอร์ไป ลูกค้าก็ยังนั่งเล่นเกมส์กินน้ำได้ตามสบาย เจ๋งไหมล่ะ?
ทำไมมันถึงสำคัญ? ก็เพราะว่าในโลกยุคนี้ ลูกค้าเค้าไม่รอใครแล้วไง! ถ้าเว็บเราล่ม เค้าก็ไปใช้ของคนอื่น จบ! แถมยังเสียความน่าเชื่อถืออีกต่างหาก Zero Downtime เลยเป็นเหมือนยันต์กันผี ที่ช่วยให้เราอัพเดทระบบได้แบบไม่ต้องกลัวลูกค้าหนี SiamCafe Blog มีบทความดีๆ อีกเยอะ ลองเข้าไปอ่านดูนะ
Replication คือการก็อปปี้ข้อมูลจากฐานข้อมูลหนึ่ง (Master) ไปยังอีกฐานข้อมูลหนึ่ง (Slave) แบบ Real-time สมัยผมทำร้านเน็ต ผมใช้ Replication เพื่อสำรองข้อมูล ถ้าเครื่องหลักมีปัญหา ก็สลับไปใช้เครื่องสำรองได้ทันที คิดซะว่า Master คือต้นฉบับ Slave คือสำเนา เราแก้ไขต้นฉบับ สำเนาก็จะถูกแก้ไขตาม
-- ตัวอย่างการตั้งค่า Replication ใน MySQL
CHANGE MASTER TO
MASTER_HOST='master_ip_address',
MASTER_USER='replication_user',
MASTER_PASSWORD='replication_password',
MASTER_LOG_FILE='recorded_log_file_name',
MASTER_LOG_POS=4;
START SLAVE;
Load Balancer คือตัวจัดการจราจร ที่คอยกระจาย Traffic ไปยัง Server หลายๆ ตัว เพื่อไม่ให้ Server ตัวใดตัวหนึ่งทำงานหนักเกินไป สมัยผมใช้ Load Balancer ในร้านเน็ต คือให้มันกระจายคนเล่นเกมส์ Counter-Strike ไปตามเครื่องต่างๆ ไม่ให้เครื่องไหนค้าง เพราะคนเยอะเกินไป
Load Balancer จะช่วยให้เราสามารถสลับไปใช้ฐานข้อมูลตัวใหม่ได้ โดยที่ผู้ใช้งานไม่รู้สึกถึงการเปลี่ยนแปลง เพราะ Load Balancer จะคอย Redirect Traffic ไปยังฐานข้อมูลตัวใหม่ให้อัตโนมัติ
Schema คือโครงสร้างของฐานข้อมูล เช่น ตาราง คอลัมน์ Index ต่างๆ ก่อนที่จะทำการ Migration เราต้องตรวจสอบให้แน่ใจว่า Schema ของฐานข้อมูลเก่าและฐานข้อมูลใหม่นั้นเข้ากันได้ ถ้าไม่เข้ากัน ระบบพังแน่นอน!
เคยเจอเคส Schema ไม่ตรงกันไหม? สมัยก่อนผมเคยพลาดตอนอัพเดทระบบ Forum ปรากฏว่า Schema ใหม่ ไม่รองรับข้อมูลเก่า ทำให้ข้อมูลบางส่วนหายไปเลย เข็ดจนตาย!
เอาล่ะ มาถึงขั้นตอนสำคัญแล้ว Zero Downtime Migration ไม่ยากอย่างที่คิด แต่ต้องวางแผนให้ดีนะ ไม่งั้น "งานเข้า" แน่นอน
เริ่มจากตั้งค่า Replication ให้ฐานข้อมูลใหม่ (New DB) ทำงานเป็น Slave ของฐานข้อมูลเก่า (Old DB) เพื่อให้ข้อมูลจาก Old DB ถูกก็อปปี้ไปยัง New DB แบบ Real-time
-- บน New DB
CHANGE MASTER TO
MASTER_HOST='old_db_ip_address',
MASTER_USER='replication_user',
MASTER_PASSWORD='replication_password',
MASTER_LOG_FILE='recorded_log_file_name',
MASTER_LOG_POS=4;
START SLAVE;
หลังจากที่ Replication ทำงานได้แล้ว เราจะเริ่มใช้เทคนิคที่เรียกว่า "Double Write" คือให้ Application ของเราเขียนข้อมูลไปยังทั้ง Old DB และ New DB พร้อมๆ กัน
// Code ตัวอย่าง (Pseudo-code)
function saveData(data) {
writeToOldDB(data);
writeToNewDB(data);
}
ทำไมต้อง Double Write? ก็เพื่อให้ New DB มีข้อมูลที่ "สดใหม่" อยู่เสมอไงล่ะ! แถมยังเป็นการทดสอบระบบไปในตัวด้วย ถ้า Double Write มีปัญหา เราจะได้รู้ตัวก่อนที่จะสลับไปใช้ New DB จริงๆ
เมื่อ New DB มีข้อมูลที่ "สดใหม่" และระบบ Double Write ทำงานได้อย่างราบรื่นแล้ว ก็ถึงเวลา Switch Traffic! เราจะใช้ Load Balancer เพื่อเปลี่ยนเส้นทาง Traffic จาก Old DB ไปยัง New DB
ก่อนที่จะ Switch Traffic จริงๆ ควรทำการทดสอบก่อนเสมอ! ลอง Redirect Traffic ไปยัง New DB สัก 10% แล้วค่อยๆ เพิ่มปริมาณขึ้นเรื่อยๆ ถ้าไม่มีปัญหาอะไร ก็ Switch Traffic ทั้งหมดได้เลย
สมัยผมทำร้านเน็ต ผมเคยใช้เทคนิคนี้ตอนย้าย Database ของระบบสมาชิก ผลลัพธ์คือลูกค้าไม่รู้สึกถึงการเปลี่ยนแปลงเลยสักนิดเดียว! SiamCafe Blog มี Tips & Tricks เกี่ยวกับ IT อีกเยอะนะ
หลังจาก Switch Traffic ไปยัง New DB เรียบร้อยแล้ว เราก็สามารถหยุด Replication และ Double Write ได้เลย
อย่าลืม Monitor ระบบอย่างใกล้ชิดหลังจากการ Migration นะ! คอยดู Log File และ Performance ของ New DB อย่างสม่ำเสมอ เพื่อให้แน่ใจว่าทุกอย่างทำงานได้ตามปกติ
Zero Downtime Migration ไม่ใช่ทางเลือกเดียวในการย้ายฐานข้อมูล ยังมีวิธีอื่นๆ อีกมากมาย แต่ละวิธีก็มีข้อดีข้อเสียแตกต่างกันไป ลองมาดูกัน
| วิธี | ข้อดี | ข้อเสีย |
|---|---|---|
| Dump & Restore | ง่ายที่สุด | ใช้เวลานาน ระบบต้องหยุดทำงาน |
| In-Place Upgrade | ไม่ต้องใช้ Hardware เพิ่ม | เสี่ยงที่จะเกิดปัญหา Database Corruption |
| Zero Downtime Migration | ระบบทำงานได้ตลอดเวลา | ซับซ้อนกว่าวิธีอื่น ต้องใช้ทรัพยากรเพิ่ม |
เลือกวิธีไหนดี? ก็ขึ้นอยู่กับความต้องการและความพร้อมของแต่ละคน ถ้า Database ไม่ใหญ่มาก และยอมให้ระบบหยุดทำงานได้ Dump & Restore ก็เป็นทางเลือกที่ง่ายที่สุด แต่ถ้าต้องการ Zero Downtime จริงๆ ก็ต้องลงทุนลงแรงกับ Zero Downtime Migration
สมัยผมทำร้านเน็ต SiamCafe เนี่ย เรื่อง Database นี่สำคัญสุดๆ เพราะลูกค้าเยอะ ฐานข้อมูลเกมส์ ข้อมูลสมาชิก มันต้องเป๊ะ ถ้าเกิด Downtime นี่โดนด่าเละ! เลยต้องหาทางทำให้มันอัพเดทได้โดยที่ไม่ต้องปิดร้าน หรือให้มันกระทบกับลูกค้าน้อยที่สุด
Zero Downtime Migration เลยเป็นอะไรที่ต้องศึกษาอย่างจริงจัง ผมลองผิดลองถูกมาเยอะ เลยอยากจะแชร์เทคนิคที่ใช้ได้จริงให้ฟังกัน
อันนี้เบสิคเลย คือเราจะมี Database 2 ชุด ชุดนึงคือ "Blue" ที่ใช้งานจริง อีกชุดคือ "Green" ที่เราจะเอาไว้ทดสอบและอัพเดท
พอเราอัพเดท "Green" เสร็จแล้ว เราก็แค่สลับให้ "Green" กลายเป็น Database หลักแทน "Blue" ง่ายๆ แค่นี้เอง
# สมมติว่าเราใช้ Nginx เป็น Load Balancer
# แก้ config ให้ชี้ไปที่ Green Database แทน
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://green_database;
}
}
ถ้า Blue/Green มันดูใหญ่ไป ลอง Rolling Updates ดู คือค่อยๆ อัพเดท Database ทีละ Node
เช่น มี Database 3 ตัว ก็อัพเดทตัวแรกก่อน พอตัวแรกเสร็จก็ค่อยอัพเดทตัวที่สอง ทำไปเรื่อยๆ จนครบ
ข้อดีคือ Downtime มันน้อยมาก เพราะมันไม่ได้ดับทั้งหมดทีเดียว แต่ข้อเสียคือ มันต้องออกแบบ App ให้รองรับ Database ที่มี Schema หลาย version ได้
เรื่อง Schema นี่ตัวดีเลย ถ้าเปลี่ยน Schema แบบไม่คิดหน้าคิดหลังนี่พังแน่ๆ สมัยผมเคยเจอเคสที่ developer เปลี่ยน type ของ column ใน Database แล้ว App เก่ามันอ่านไม่ได้ ผลคือลูกค้าเข้าร้านมาเล่นเกมส์ไม่ได้เลย ต้องรีบ Rollback แทบไม่ทัน
ดังนั้น เวลาจะเปลี่ยน Schema ต้องคิดถึง Backward Compatibility เสมอ เช่น ถ้าจะเปลี่ยน Column name ก็ให้เพิ่ม Column ใหม่ แล้วค่อยๆ migrate ข้อมูลจาก Column เก่าไป Column ใหม่ แล้วค่อยลบ Column เก่าทิ้ง
-- เพิ่ม column ใหม่
ALTER TABLE users ADD COLUMN new_email VARCHAR(255);
-- migrate ข้อมูล
UPDATE users SET new_email = email;
-- เปลี่ยน app ให้ใช้ column ใหม่
-- (ใน app code)
-- ลบ column เก่า
ALTER TABLE users DROP COLUMN email;
อันนี้ advance หน่อย คือเราจะ copy traffic จาก Database หลัก ไปยัง Database ที่เรากำลังจะอัพเดท เพื่อทดสอบว่า Database ใหม่มันทำงานได้ถูกต้อง
ข้อดีคือเราสามารถทดสอบ Performance และ Stability ของ Database ใหม่ได้ โดยที่ไม่กระทบกับ User จริง แต่ข้อเสียคือ มันต้องใช้ Resource เยอะ และต้องมี Infrastructure ที่ซับซ้อน
อย่าลืม Backup ข้อมูลก่อนทำอะไรเสมอ!
ถ้า Database ใหญ่มากๆ Migration นานแน่นอน ลองใช้เทคนิค Sharding หรือ Partitioning ดู จะช่วยแบ่ง Database ออกเป็นส่วนๆ ทำให้ Migration เร็วขึ้น
เรื่องข้อมูลหายเป็นอะไรที่น่ากลัวที่สุด ต้องมี Backup เสมอ และควรมีกระบวนการ Verification หลัง Migration เพื่อตรวจสอบว่าข้อมูลถูกต้องครบถ้วน
เตรียม Rollback Plan ไว้เสมอ ถ้า Migration แล้ว App พัง ให้รีบ Rollback กลับไปใช้ Database เดิมทันที แล้วค่อยมาวิเคราะห์หาสาเหตุ
มี Tool เยอะแยะเลยที่ช่วยเรื่อง Database Migration ลองศึกษาดูว่า Tool ไหนเหมาะกับ Database และ Infrastructure ของคุณ
Database คนละ Version กัน Migration ได้ แต่ต้องระวังเรื่อง Compatibility อาจจะต้องใช้ Tool ช่วย หรือเขียน Script เอง
Zero Downtime Database Migration ไม่ใช่เรื่องง่าย ต้องใช้ความรู้ ความเข้าใจ และประสบการณ์ แต่ถ้าทำได้ มันจะช่วยลดผลกระทบต่อ User และทำให้เราสามารถอัพเดท Database ได้อย่างมั่นใจ
หวังว่าเทคนิคที่ผมแชร์ไปจะเป็นประโยชน์กับทุกคนนะครับ ลองเอาไปปรับใช้กันดู SiamCafe Blog ยังมีบทความดีๆ อีกเยอะ ลองเข้าไปอ่านกันได้เลย
อย่าลืมว่าไม่มีสูตรสำเร็จตายตัว ทุกอย่างต้องปรับตามสถานการณ์จริง iCafeForex ก็เหมือนกัน ต้องปรับกลยุทธ์ตามตลาดตลอดเวลา