12 เม.ย. 2568·อ่าน 2 นาที

Blue-green เทียบกับ Canary: ปรับใช้การเปลี่ยนแปลง API และฐานข้อมูลอย่างปลอดภัย

อธิบายการปรับใช้แบบ Blue-green กับ Canary สำหรับการเปลี่ยน API และฐานข้อมูล พร้อมขั้นตอนปฏิบัติที่ลดความเสี่ยง downtime ระหว่างมิเกรชันและเมื่อไคลเอนต์มือถืออัปเดตช้า

Blue-green เทียบกับ Canary: ปรับใช้การเปลี่ยนแปลง API และฐานข้อมูลอย่างปลอดภัย

ทำไมการปรับใช้ถึงมีความเสี่ยงเมื่อมีการเปลี่ยนสคีมาและการอัปเดตมือถือช้า

การปล่อยใช้อาจดูเรียบร้อยในการทดสอบ แต่ล้มเหลวทันทีเมื่อเจอทราฟฟิคจริง สาเหตุทั่วไปคือโค้ดของคุณไม่ใช่อย่างเดียวที่เปลี่ยนไป สัญญาของ API และสคีมาฐานข้อมูลก็เปลี่ยนด้วย และมักจะไม่เปลี่ยนในจังหวะเดียวกัน

ระบบพังเมื่อส่วนต่าง ๆ ไม่เห็นด้วยเกี่ยวกับความหมายของสิ่งที่ "ถูกต้อง" แบ็กเอนด์เวอร์ชันใหม่อาจคาดหวังคอลัมน์ที่ยังไม่มี โค้ดเก่าเขียนข้อมูลในรูปแบบที่โค้ดใหม่อ่านไม่ออก แม้แต่การเปลี่ยนเล็ก ๆ เช่น เปลี่ยนชื่อฟิลด์ เข้มงวดการตรวจสอบค่า หรือตั้งค่า enum ใหม่ ก็สามารถทำให้เกิดข้อผิดพลาดใน production ได้

แอปมือถือยิ่งเพิ่มความเสี่ยงเพราะเวอร์ชันเก่ายังคงใช้งานอยู่ บางคนอัปเดตในไม่กี่นาที บางคนเป็นสัปดาห์ นั่นหมายความว่า backend ต้องให้บริการไคลเอนต์หลายรุ่นพร้อมกัน หากคุณปล่อยการเปลี่ยน API ที่ทำงานได้กับแอปใหม่เท่านั้น คุณอาจทำให้การชำระเงิน การลงทะเบียน หรือการซิงค์แบ็กกราวด์ของผู้ใช้บางกลุ่มพังโดยไม่รู้ตัวทันที

"ความเสี่ยงของ downtime" ไม่ได้หมายถึงเว็บล่มอย่างเดียว ในระบบจริง มักแสดงออกมาเป็นความล้มเหลวบางส่วน เช่น:

  • เกิด spike ของข้อผิดพลาด 4xx/5xx บน endpoint เฉพาะ ขณะที่ส่วนอื่นปกติ
  • เข้าสู่ระบบล้มเหลวเพราะ token, role หรือเรคคอร์ดผู้ใช้ไม่ตรงกับความคาดหวัง
  • ปัญหาข้อมูลเงียบ ๆ (ค่าเริ่มต้นผิด ข้อความถูกตัด ความสัมพันธ์หายไป) ที่โผล่มาหลายวันหลัง
  • งานแบ็กกราวด์ติดค้างและสร้างคิวที่ต้องใช้เวลาหลายชั่วโมงในการระบาย

นี่คือเหตุผลที่ทีมงานเปรียบเทียบ blue-green กับ canary: คุณพยายามลด blast radius เมื่อการเปลี่ยนไม่เข้ากันอย่างสมบูรณ์

Blue-green และ canary อธิบายแบบเข้าใจง่าย

เมื่อคนพูดถึงการเทียบ blue-green กับ canary พวกเขามักตอบคำถามเดียวกัน: คุณอยากสลับแบบครั้งเดียวใหญ่ ๆ ที่ควบคุมได้หรืออยากทดสอบแบบเล็ก ๆ ระมัดระวัง

Blue-green: สองเวอร์ชันเต็มและการสลับทราฟฟิค

Blue-green หมายความว่าคุณรันสองสภาพแวดล้อมเต็มรูปแบบพร้อมกัน "Blue" คือเวอร์ชันปัจจุบันที่ให้บริการผู้ใช้ ส่วน "Green" คือเวอร์ชันใหม่ที่ deploy และทดสอบคู่ขนาน เมื่อพร้อม คุณสลับทราฟฟิคจาก blue ไป green

วิธีนี้ดีเรื่องความคาดการณ์ได้ คุณสามารถยืนยันเวอร์ชันใหม่ด้วยการตั้งค่าคล้าย production ก่อนให้บริการผู้ใช้จริง แล้วทำการตัดต่อครั้งเดียวให้เรียบร้อย

การย้อนกลับก็ตรงไปตรงมา: หากมีปัญหาหลังสลับ ให้ชี้ทราฟฟิคกลับไปที่ blue มันใกล้เคียงกับการสลับกลับทันที แต่ cache งานแบ็กกราวด์ และการเปลี่ยนข้อมูลยังสามารถทำให้การกู้คืนซับซ้อนได้

Canary: ส่งทราฟฟิคส่วนน้อยก่อน

Canary หมายความว่าเวอร์ชันใหม่เปิดให้ใช้งานกับกลุ่มผู้ใช้หรือคำขอส่วนน้อยก่อน หากดูสุขภาพดี คุณเพิ่มเปอร์เซ็นต์ทีละน้อยจนกระทั่งให้บริการทุกคน

Canary เหมาะเมื่อคุณกังวลพฤติกรรมที่ไม่คาดคิดภายใต้ทราฟฟิคจริง คุณจะจับข้อผิดพลาดได้เร็ว ก่อนที่ผู้ใช้ส่วนใหญ่จะได้รับผลกระทบ

การย้อนกลับทำได้โดยลดเปอร์เซ็นต์ของ canary กลับเป็นศูนย์หรือหยุดการส่งทราฟฟิคไปยังเวอร์ชันใหม่ มักจะทำได้เร็ว แต่ไม่เสมอไปว่าจะสะอาด เพราะผู้ใช้บางส่วนอาจสร้างข้อมูลหรือ state ที่ทั้งสองเวอร์ชันต้องรองรับแล้ว

สรุปเทรดออฟง่าย ๆ:

  • Blue-green เน้นการสลับที่สะอาดและการสลับกลับที่รวดเร็ว
  • Canary เน้นการเรียนรู้จากทราฟฟิคจริงด้วย blast radius ที่จำกัด
  • ไม่มีวิธีใดรับประกันความเสี่ยงของฐานข้อมูล หากการเปลี่ยนสคีมาไม่เข้ากัน ทั้งสองก็ล้มเหลวได้
  • Canary ขึ้นกับการมอนิเตอร์เพราะตัดสินจากสัญญาณสด
  • Blue-green มักต้องมีทรัพยากรเพิ่มเพราะรันสองสแตกเต็มรูปแบบ

ตัวอย่าง: หากคุณปล่อย API ที่บางครั้งส่งฟิลด์ใหม่ การใช้ canary จะช่วยให้คุณเห็นว่าไคลเอนต์เก่าจะพังกับข้อมูลที่ไม่คาดคิดหรือไม่ แต่ถ้าการเปลี่ยนต้องเปลี่ยนชื่อคอลัมน์ที่โค้ดเก่าอ่านไม่ได้ Blue-green จะช่วยไม่ได้เว้นแต่ว่าสคีมาถูกออกแบบให้รองรับทั้งสองเวอร์ชัน

ทำไมการย้ายสคีมาถึงต่างจากการ deploy โค้ด

การ deploy โค้ดมักจะ rollback ง่าย ถ้าเวอร์ชันใหม่ทำงานผิด ให้ redeploy build เก่าแล้วโดยรวมกลับมาที่เดิมได้

การเปลี่ยนฐานข้อมูลต่างออกไปเพราะมันเปลี่ยนรูปทรงของข้อมูล เมื่อแถวถูกเขียนใหม่ คอลัมน์ถูกลบ หรือข้อจำกัดเข้มงวดขึ้น การย้อนกลับหายาก แม้คุณจะย้อนโค้ดกลับไป มันอาจอ่านสคีมาใหม่ไม่ออก

นี่คือเหตุผลที่ความเสี่ยงของ downtime ในการย้ายสคีมามักเกี่ยวกับการออกแบบมิเกรชันมากกว่าวิธี deploy

พื้นฐานมิเกรชันแบบออนไลน์

มิเกรชันที่ปลอดภัยที่สุดถูกสร้างให้ทำงานได้ในขณะที่เวอร์ชันเก่าและใหม่รันพร้อมกัน รูปแบบง่าย ๆ คือ: ทำการเปลี่ยนที่ปลอดภัยให้ข้ามได้ อัปเดตโค้ดให้ใช้มัน แล้วล้างข้อมูลทีหลัง

ลำดับ expand-then-contract ทั่วไปคือ:

  • เปลี่ยนแบบเพิ่มก่อน: เพิ่มคอลัมน์ nullable เพิ่มตารางใหม่ เพิ่มดัชนีโดยไม่ล็อกการเขียน
  • พฤติกรรมคู่ขนาน: เขียนทั้งที่เก่าและที่ใหม่ หรืออ่านจากที่ใหม่แล้ว fallback ไปเก่า
  • ทำ backfill แยกเป็นชุดเล็ก ๆ
  • สลับพฤติกรรม: ย้ายทราฟฟิคไปยังพฤติกรรมใหม่ส่วนใหญ่
  • การเปลี่ยนทำลายล้างสุดท้าย: ลบคอลัมน์เก่า เอาทางเลือกโค้ดเก่าออก เข้มงวดข้อจำกัดทีหลัง

มิเกรชันแบบ "big bang" รวมขั้นตอนเสี่ยงทั้งหมดใน release เดียว: การล็อกนาน การ backfill หนัก และโค้ดที่สมมติว่าสคีมาใหม่มีอยู่ทุกที่

ทำไมการอัปเดตมือถือช้าจึงเพิ่มเกณฑ์

ไคลเอนต์มือถืออาจคงอยู่บนเวอร์ชันเก่านานเป็นสัปดาห์ backend ต้องรับคำขอเก่าและส่งคำตอบแบบเก่าในขณะที่ฐานข้อมูลพัฒนา

ถ้าแอปเก่าไม่ส่งฟิลด์ใหม่ เซิร์ฟเวอร์ของคุณไม่สามารถทำให้ฟิลด์นั้นเป็น required ในฐานข้อมูลทันที คุณต้องมีช่วงเวลาที่ทั้งสองพฤติกรรมทำงานได้

ยุทธศาสตร์ไหนลดความเสี่ยง downtime สำหรับมิเกรชัน

ตัวเลือกที่ปลอดภัยขึ้นอยู่กับคำถามหลัก: เวอร์ชันเก่าและใหม่สามารถรันถูกต้องบนสคีมาฐานข้อมูลเดียวกันไปสักระยะไหม

ถ้าคำตอบคือใช่ Blue-green มักเป็นตัวเลือกที่ downtime ต่ำสุด คุณสามารถเตรียมการเปลี่ยนฐานข้อมูลก่อน เก็บทราฟฟิคไว้บนสแตกเก่า แล้วสลับทราฟฟิคไปสแตกใหม่ทีเดียว หากมีปัญหาสลับกลับได้เร็ว

Blue-green ยังล้มเหลวเมื่อแอปใหม่ต้องการสคีมาใหม่ทันที ตัวอย่างทั่วไป เช่น การลบหรือเปลี่ยนชื่อคอลัมน์ที่เวอร์ชันเก่ายังอ่าน หรือการเพิ่มข้อจำกัด NOT NULL ก่อนที่แอปจะเขียนค่า ในกรณีเหล่านี้ การย้อนกลับอาจไม่ปลอดภัยเพราะฐานข้อมูลไม่เข้ากันแล้ว

Canary เหมาะเมื่อคุณต้องเรียนรู้แบบควบคุม กลุ่มเล็กของทราฟฟิคจริงจะเข้าถึงเวอร์ชันใหม่ก่อน ช่วยให้จับกรณีขอบเช่น ดัชนีหาย รูปแบบคิวรีไม่คาดคิด หรือ background jobs ทำงานต่างในโหลด production เทรดออฟคือคุณต้องให้ทั้งสองเวอร์ชันทำงานได้พร้อมกัน ซึ่งมักหมายถึงการเปลี่ยนฐานข้อมูลที่ย้อนกลับเข้ากันได้

กฎตัดสินใจเชิงปฏิบัติ

เมื่อพิจารณา blue-green กับ canary สำหรับความเสี่ยง downtime ของมิเกรชัน:

  • เลือก blue-green เมื่อการเปลี่ยนสคีมาสามารถทำแบบเพิ่มได้และเข้ากันได้ และคุณต้องการสลับที่สะอาดและเร็ว
  • เลือก canary เมื่อไม่แน่ใจว่าการเปลี่ยนจะทำงานอย่างไรใน production หรือคาดว่ารูปแบบข้อมูลหายากจะสำคัญ
  • หากมิเกรชันบังคับให้เกิดการเปลี่ยนที่ทำให้ระบบเสียหายทันที อย่าเลือกระหว่าง blue-green และ canary ให้เปลี่ยนแผนเป็น expand-then-contract

"เข้ากันได้" ในชีวิตจริงเป็นอย่างไร

สมมติคุณเพิ่มฟิลด์ใหม่ในตาราง orders เส้นทางปลอดภัยคือ: เพิ่มคอลัมน์เป็น nullable, deploy โค้ดที่เขียนค่า, backfill แถวเก่า แล้วค่อยบังคับข้อจำกัด ต่อด้วยการลบฟิลด์เก่า ในการตั้งค่านี้ Blue-green ให้การสลับที่สะอาดได้ ส่วน canary ให้สัญญาณเตือนล่วงหน้าว่ายังมีโค้ดเส้นทางใดสมมติรูปแบบเก่าอยู่หรือไม่

การอัปเดตมือถือช้าส่งผลต่อการเลือกวิธีปรับใช้อย่างไร

เป็นเจ้าของซอร์สโค้ด
สร้างโค้ด Go, Vue3 และ Kotlin หรือ SwiftUI พร้อมใช้งานสำหรับ production ที่คุณสามารถปรับใช้เองได้ทุกที่
สร้างโค้ด

ผู้ใช้เว็บรีเฟรชได้ ผู้ใช้มือถือไม่ทำอย่างนั้น

บน iOS และ Android คนอยู่บนเวอร์ชันเก่าหลายสัปดาห์หรือหลายเดือน บางคนไม่อัปเดตเลยจนแอปบังคับ นั่นหมายความว่าไคลเอนต์ "เก่า" ยังคงเรียก API ของคุณนานหลังจากที่คุณปล่อย backend ใหม่แล้ว ไคลเอนต์มือถือเก่าๆ กลายเป็นการทดสอบความเข้ากันได้ย้อนหลังอย่างถาวร

จุดมุ่งหมายจึงเปลี่ยนจาก "deploy โดยไม่มี downtime" เป็น "ทำให้หลายรุ่นไคลเอนต์ทำงานได้พร้อมกัน" ในทางปฏิบัติ มือถือมักผลักให้คุณคิดแบบ canary สำหรับ API ถึงแม้ว่าคุณจะใช้ blue-green สำหรับโครงสร้างพื้นฐาน

การเปลี่ยนที่เข้ากันได้ย้อนหลังกับการเวอร์ชัน API

ส่วนใหญ่คุณต้องการการเปลี่ยนที่เข้ากันได้ย้อนหลัง เพราะจะให้ไคลเอนต์เก่าและใหม่แชร์ endpoint เดียวกัน

ตัวอย่างที่เข้ากันได้ย้อนหลังได้แก่ การเพิ่มฟิลด์ใหม่ การรับทั้งรูปแบบ payload เก่าและใหม่ การเก็บฟิลด์ตอบกลับเดิม และหลีกเลี่ยงการเปลี่ยนความหมาย

การเวอร์ชัน API สำหรับแอปมือถือจะมีประโยชน์เมื่อพฤติกรรมต้องเปลี่ยนจริง ๆ (ไม่ใช่แค่เพิ่มข้อมูล) หรือเมื่อคุณต้องลบหรือเปลี่ยนชื่อฟิลด์

ตัวอย่าง: การเพิ่มฟิลด์ optional เช่น marketing_opt_in มักปลอดภัย แต่การเปลี่ยนวิธีการคำนวณ price มักไม่ปลอดภัย

วางแผนหน้าต่างการเลิกสนับสนุน

ถ้าคุณต้องการการเปลี่ยนที่ทำให้ระบบเสียหาย ให้ถือการสิ้นสุดการสนับสนุนเป็นการตัดสินใจเชิงผลิตภัณฑ์ หน้าต่างการเลิกสนับสนุนที่มีประโยชน์วัดโดย "ผู้ใช้ที่ยังใช้งานบนเวอร์ชันเก่า" ไม่ใช่แค่วันเวลา

ลำดับที่ใช้งานได้จริง:

  • ปล่อย backend ที่รองรับทั้งไคลเอนต์เก่าและใหม่
  • ปล่อยแอปมือถือเวอร์ชันใหม่และติดตามการนำไปใช้ตามเวอร์ชัน
  • เตือนหรือจำกัดเฉพาะเมื่อเปอร์เซ็นต์ผู้ใช้เก่าลดลงต่ำกว่าค่าปลอดภัย
  • ลบพฤติกรรมเก่าทีหลังพร้อมแผนย้อนกลับ

ขั้นตอนทีละขั้น: รูปแบบการเปิดตัวที่ปลอดภัยสำหรับ API + ฐานข้อมูล

จัดการการอัปเดตมือถือที่ช้า
สร้างแอปมือถือที่ยังคงเข้ากันได้ในขณะที่ผู้ใช้ค่อย ๆ อัปเดตในหลายวันหรือหลายสัปดาห์
สร้างแอป

เมื่อคุณเปลี่ยน API และฐานข้อมูลพร้อมกัน แผนที่ปลอดภัยมักเป็นการเปิดตัว 2 หรือ 3 ขั้นตอน แต่ละขั้นควรปลอดภัยเมื่อติดตั้งแยกกัน แม้ผู้ใช้จะคงแอปมือถือเก่าไว้นาน

รูปแบบการเปิดตัวที่หลีกเลี่ยงการทำให้ไคลเอนต์เก่าพัง

เริ่มจากการเปลี่ยนฐานข้อมูลแบบเพิ่มก่อน เพิ่มคอลัมน์หรือตารางใหม่ หลีกเลี่ยงการเปลี่ยนชื่อหรือการลบ ให้คอลัมน์เป็น nullable ใช้ค่า default เพื่อที่โค้ดเก่าจะไม่โดนบังคับ

จากนั้นส่งโค้ดที่ทนต่อทั้งสองรูปแบบ การอ่านควรรองรับกรณีที่ "ฟิลด์เก่าหายไป" และ "ฟิลด์ใหม่มีอยู่" การเขียนควรยังคงเขียนฟิลด์เก่าไว้ก่อน และสามารถเขียนฟิลด์ใหม่ด้วยได้ถ้าต้องการ

ลำดับทั่วไป:

  • เพิ่มชิ้นส่วนสคีมาใหม่ (คอลัมน์ ตาราง ดัชนี) โดยไม่เอาของเก่าออก
  • Deploy โค้ดที่อ่านได้ทั้งเก่าและใหม่และไม่ล้มเมื่อเจอ null
  • Backfill แถวเก่าเป็นชุดเล็ก ๆ แล้วยืนยันจำนวน อัตรา null และประสิทธิภาพคิวรี
  • สลับเส้นทางการเขียนไปยังฟิลด์ใหม่ โดยเก็บ fallback อ่าน
  • หลังจากไคลเอนต์มือถือเก่าหายไปแล้ว ให้ลบฟิลด์เก่าและล้างโค้ด

Backfill และการตรวจสอบ: ที่ซ่อนของการล่ม

การ backfill มักล้มเพราะมองเป็นสคริปต์สั้น ๆ ให้รันเป็นชุด ๆ ดูโหลด และตรวจสอบผล หากพฤติกรรมใหม่ต้องการดัชนี ให้เพิ่มดัชนีก่อนสลับการอ่านหรือเขียน ไม่ใช่หลัง

ตัวอย่าง: คุณเพิ่ม phone_country_code เพื่อปรับปรุงฟอร์แมต เริ่มจากเพิ่มคอลัมน์ (nullable), อัปเดต API ให้รับแต่ยังทำงานถ้าไม่มีค่า, backfill จากหมายเลขเดิม, แล้วเริ่มเขียนสำหรับการลงทะเบียนใหม่ สัปดาห์ต่อมาเมื่อเวอร์ชันเก่าหลุดไปแล้วค่อยลบเส้นทางการแยกวิเคราะห์เก่า

เครื่องมือที่ทำให้ทั้งสองกลยุทธ์ปลอดภัยยิ่งขึ้น (โดยไม่ต้องซับซ้อน)

คุณไม่จำเป็นต้องตั้งค่าซับซ้อนเพื่อทำให้ blue-green หรือ canary ปลอดภัยขึ้น นิสัยบางอย่างช่วยลดความประหลาดใจเมื่v API และสคีมาก้าวไม่พร้อมกัน

Dual-read และ dual-write (เก็บไว้ชั่วคราว)

Dual-write คือแอปเขียนข้อมูลทั้งที่เก่าและที่ใหม่ในช่วงเปลี่ยน เช่น ทั้ง users.full_name และ users.display_name ส่วน dual-read คืออ่านจากที่ใหม่แล้ว fallback ไปที่เก่า

สิ่งนี้ช่วยให้มีเวลาสำหรับการอัปเดตลูกค้าที่ช้า แต่ควรเป็นสะพานชั่วคราว กำหนดว่าจะลบอย่างไร ติดตามเส้นทางที่ถูกใช้ (ใหม่กับ fallback) และเพิ่มการตรวจสอบพื้นฐานให้การเขียนทั้งสองทางสอดคล้องกัน

Feature flags สำหรับการเปลี่ยนพฤติกรรม

Feature flags ช่วยให้ deploy โค้ดโดยไม่เปิดพฤติกรรมเสี่ยงทันที ช่วยทั้ง blue-green และ canary เพราะคุณแยกการ "deploy" ออกจากการ "เปิดใช้งาน"

ตัวอย่าง: deploy การรองรับฟิลด์ตอบกลับใหม่ แต่ให้เซิร์ฟเวอร์ยังคงส่งรูปแบบเดิมจนกว่าจะพร้อม จากนั้นเปิดพฤติกรรมใหม่ให้กลุ่มเล็ก ๆ ดูข้อผิดพลาด แล้วขยาย หากผิดพลาดก็ปิด flag โดยไม่ต้อง redeploy

มุมมองการทดสอบสัญญา (API คือสัญญา)

หลายเหตุการณ์มิเกรชันไม่ใช่ "ปัญหาฐานข้อมูล" จริง ๆ แต่เป็นปัญหาความคาดหวังของไคลเอนต์

ถือ API เป็นสัญญา หลีกเลี่ยงการเอาฟิลด์ออกหรือเปลี่ยนความหมาย ทำให้ฟิลด์ที่ไม่รู้จักเป็น optional การเปลี่ยนแบบเพิ่มมักปลอดภัย การเปลี่ยนที่ทำให้ระบบเสียหายควรรอเวอร์ชัน API ใหม่

งานย้ายข้อมูลที่เชื่อถือได้

การมิเกรชันมักต้องมีงาน backfill เพื่อคัดลอกข้อมูล คำนวณค่า หรือล้างข้อมูล งานเหล่านี้ควรน่าเบื่อและทำซ้ำได้: รันสองครั้งได้ ปรับ retry ได้ ติดตามได้ และ throttle เพื่อไม่ให้โหลดพุ่ง

ข้อผิดพลาดทั่วไปที่ทำให้เกิดการล่มระหว่างมิเกรชัน

โฮสต์เองเมื่อจำเป็น
ส่งออกซอร์สโค้ดที่สร้างขึ้นเพื่อโฮสต์เองเมื่อคุณต้องการการควบคุมการปรับใช้เต็มที่
ส่งออกโค้ด

เหตุการณ์ล่มส่วนใหญ่เกิดเพราะ release สมมติว่าทุกอย่างเปลี่ยนพร้อมกัน: บริการทุกตัว deploy พร้อมกัน ข้อมูลสะอาด และไคลเอนต์อัปเดตทันที ระบบจริงไม่เป็นแบบนั้น โดยเฉพาะกับมือถือ

รูปแบบล้มเหลวบ่อย ๆ:

  • ลบหรือเปลี่ยนชื่อคอลัมน์เร็วเกินไป ไฟล์งานแบ็กกราวด์หรือไคลเอนต์มือถือเก่าอาจยังเรียกใช้อยู่
  • สมมติว่าไคลเอนต์อัปเดตเร็ว มือถือใช้เวลานาน
  • รันมิเกรชันที่ล็อกตารางใหญ่ในช่วงชั่วโมงเร่งด่วน ดัชนีหรือการเปลี่ยนอาจบล็อกการเขียน
  • ทดสอบเฉพาะข้อมูลตัวอย่างที่สะอาด ข้อมูลจริงมี null รูปแบบแปลก ตัวซ้ำ และค่าที่ย้อนอดีต
  • ไม่มีแผนย้อนกลับจริงสำหรับโค้ดและข้อมูล แค่บอกว่า "เราจะ redeploy เวอร์ชันก่อนหน้า" ไม่พอถ้าสคีมาถูกเปลี่ยน

ตัวอย่าง: คุณเปลี่ยนชื่อ status เป็น order_status และ deploy API ใหม่ เว็บแอปอาจทำงาน แต่ไคลเอนต์มือถือเก่าส่ง status แล้ว API ปฏิเสธคำขอ ทำให้การชำระเงินล้มเหลว หากคุณลบคอลัมน์ การกู้คืนพฤติกรรมไม่ใช่การสลับกลับอย่างรวดเร็ว

ดีฟอลต์ที่ดีกว่าคือ: ทำการเปลี่ยนทีละน้อย กลับได้ง่าย ให้เส้นทางเก่าและใหม่ทำงานร่วมกัน และเขียนลงว่าเมื่อเมตริกพุ่งขึ้นจะทำอะไร (จะชี้ทราฟฟิคกลับอย่างไร ฟีเจอร์แฟล็กใดปิดพฤติกรรมใหม่ และจะตรวจสอบ/ซ่อมข้อมูลอย่างไรถ้า backfill ผิดพลาด)

เช็คลิสต์ด่วนก่อน deploy

สร้างเครื่องมือภายในได้เร็วขึ้น
สร้างแผงผู้ดูแลหรือพอร์ทัลงานภายในอย่างรวดเร็ว แล้วทบทวนอย่างปลอดภัยเมื่อข้อมูลเปลี่ยน
ลองตอนนี้

ก่อนปล่อย มีเช็คลิสต์สั้น ๆ ที่จับปัญหาที่ทำให้ต้องย้อนคืนกลางดึก เรื่องนี้สำคัญสุดเมื่อคุณเปลี่ยน API และฐานข้อมูลพร้อมกัน โดยเฉพาะเมื่อการอัปเดตมือถือช้า

ห้าข้อที่ป้องกันการล่มส่วนใหญ่

  • Compatibility: ยืนยันว่าเวอร์ชันเก่าและใหม่ทำงานกับสคีมาฐานข้อมูลเดียวกัน การทดสอบที่เป็นประโยชน์คือ รัน build ปัจจุบันบน staging DB ที่มีมิเกรชันใหม่
  • Migration order: ให้มิเกรชันแรกเป็นแบบเพิ่ม และกำหนดการเปลี่ยนทำลายล้าง (ลบคอลัมน์ เข้มงวดข้อจำกัด) ไว้ทีหลัง
  • Rollback: นิยามการย้อนกลับที่เร็วที่สุด สำหรับ blue-green คือสลับทราฟฟิคกลับ สำหรับ canary คือส่งทราฟฟิค 100% ไปเวอร์ชันเสถียร หากการย้อนกลับต้องใช้มิเกรชันอีกครั้ง แปลว่าไม่ง่าย
  • Performance: วัด latency ของคิวรีหลังการเปลี่ยนสคีมา ไม่ใช่แค่ความถูกต้อง ดัชนีหายอาจทำให้ endpoint รู้สึกเหมือนล่ม
  • Client reality: ระบุเวอร์ชันมือถือที่เก่าและยัง active อยู่ ถ้าสัดส่วนที่สำคัญยังอยู่บนเวอร์ชันนั้น ให้วางแผนหน้าต่างความเข้ากันได้นานขึ้น

สถานการณ์สมเหตุสมผลสั้น ๆ

ถ้าคุณเพิ่มฟิลด์ใหม่อย่าง preferred_language ให้ deploy การเปลี่ยนฐานข้อมูลเป็น nullable ก่อน แล้วส่งโค้ดเซิร์ฟเวอร์ที่อ่านได้เมื่อมีค่าแต่ไม่จำเป็น จนกว่าทราฟฟิคส่วนใหญ่จะมาจากแอปที่อัปเดตแล้วค่อยบังคับหรือเอาพฤติกรรมเก่าออก

ตัวอย่าง: เพิ่มฟิลด์ใหม่โดยไม่ทำให้แอปมือถือเก่าพัง

สมมติคุณเพิ่มฟิลด์โปรไฟล์ country และธุรกิจอยากให้เป็น required นั่นอาจพังสองที่: ไคลเอนต์เก่าอาจไม่ส่งฟิลด์ และฐานข้อมูลอาจปฏิเสธการเขียนถ้าคุณบังคับ NOT NULL เร็วเกินไป

แนวทางปลอดภัยคือสองการเปลี่ยนแยกกัน: เพิ่มฟิลด์แบบเข้ากันได้ก่อน แล้วบังคับ "required" ทีหลังหลังจากไคลเอนต์อัปเดต

หน้าตาเมื่อใช้ blue-green

ด้วย blue-green คุณ deploy เวอร์ชันใหม่ข้าง ๆ เวอร์ชันเก่า แต่สคีมาควรเข้ากันได้กับทั้งสองเวอร์ชัน

ลำดับปลอดภัยคือ:

  • deploy มิเกรชัน (เพิ่ม country เป็น nullable)
  • deploy เวอร์ชัน green ที่รับ missing country และใช้ fallback
  • ทดสอบฟลูว์สำคัญกับ green (signup, edit profile, checkout)
  • สลับทราฟฟิค

ถ้าผิดพลาด ให้สลับกลับ กุญแจคือการสลับกลับได้ก็ต่อเมื่อสคีมายังรองรับเวอร์ชันเก่า

หน้าตาเมื่อใช้ canary

ด้วย canary คุณเปิดพฤติกรรม API ใหม่ให้กลุ่มเล็ก (โดยทั่วไป 1%–5%) แล้วสังเกตข้อผิดพลาดการตรวจสอบฟิลด์ที่หายไป latency และความล้มเหลวของฐานข้อมูล

ความประหลาดใจทั่วไปคือไคลเอนต์มือถือเก่าส่งอัปเดตโปรไฟล์โดยไม่ส่ง country หาก API ถือว่าจำเป็นทันที คุณจะเห็นข้อผิดพลาด 400 ถ้าฐานข้อมูลบังคับ NOT NULL อาจเห็น 500

ลำดับปลอดภัยคือ:

  • เพิ่ม country เป็น nullable (หรือใส่ default ปลอดภัยเช่น "unknown")
  • ยอมรับการขาด country จากไคลเอนต์เก่า
  • backfill country สำหรับผู้ใช้เดิมในงานแบ็กกราวด์
  • บังคับ "required" ทีหลัง (ก่อนใน API แล้วตามด้วยฐานข้อมูล)

หลังการปล่อย ให้เอกสารระบุว่าไคลเอนต์เก่าส่งอะไรได้บ้างและเซิร์ฟเวอร์รับประกันอะไร สัญญาเป็นลายลักษณ์อักษรนี้ช่วยป้องกันการแตกในการมิเกรชันถัดไป

หากคุณสร้างด้วย AppMaster (appmaster.io) วินัยการเปิดตัวแบบเดียวกันใช้ได้ แม้ว่าคุณจะสร้าง backend, เว็บ และแอปมือถือเนทีฟจากโมเดลเดียว ใช้แพลตฟอร์มในการส่งการเปลี่ยนสคีมาแบบเพิ่มได้และโลจิก API ที่ทนทานก่อน แล้วค่อยเข้มงวดเมื่อการนำไปใช้สูงขึ้น

คำถามที่พบบ่อย

What’s the simplest difference between blue-green and canary deployments?

Blue-green รันสองสภาพแวดล้อมเต็มรูปแบบพร้อมกันแล้วสลับทราฟฟิคทั้งหมดทีเดียว ส่วน Canary ปล่อยเวอร์ชันใหม่ให้กับเปอร์เซ็นต์เล็ก ๆ ก่อนแล้วค่อยเพิ่มขึ้นตามสัญญาณจากทราฟฟิคจริง

When should I choose blue-green for an API + database change?

ใช้ blue-green เมื่อคุณต้องการการสลับที่สะอาดและรวดเร็ว และมั่นใจว่าเวอร์ชันใหม่เข้ากันได้กับสคีมาฐานข้อมูลปัจจุบัน เหมาะเมื่อความเสี่ยงหลักมาจากโค้ดแอปพลิเคชัน ไม่ใช่พฤติกรรมที่ไม่รู้จักใน production

When is canary the safer option?

ใช้ canary เมื่อคุณต้องการเรียนรู้จากทราฟฟิคจริงก่อนจะปล่อยให้ทุกคนใช้งาน เช่น กรณีรูปแบบการคิวรี ข้อมูลขอบเขต หรือ background jobs อาจทำงานแตกต่างใน production มันช่วยลด blast radius แต่ต้องติดตามตัวชี้วัดอย่างใกล้ชิดและพร้อมหยุดการเปิดตัว

Do blue-green or canary automatically make database migrations safe?

ไม่ใช่ ทั้ง blue-green และ canary ไม่ได้ทำให้การย้ายสคีมาโดยอัตโนมัติปลอดภัย หากการเปลี่ยนแปลงสคีมาทำให้เข้ากันไม่ได้ (เช่น ลบหรือเปลี่ยนชื่อคอลัมน์ที่โค้ดเก่ายังใช้) ทั้งสองวิธีสามารถล้มเหลว วิธีที่ปลอดภัยกว่าคือออกแบบการย้ายข้อมูลออนไลน์ที่รองรับทั้งเวอร์ชันเก่าและใหม่พร้อมกัน

Why do slow mobile app updates make deployments riskier?

ผู้ใช้มือถือสามารถคงอยู่บนเวอร์ชันเก่าเป็นสัปดาห์หรือหลายสัปดาห์ ดังนั้น backend ต้องรองรับหลายรุ่นของไคลเอนต์พร้อมกัน ซึ่งมักหมายถึงต้องรักษา backward compatibility ของ API ให้ยาวขึ้นและหลีกเลี่ยงการเปลี่ยนที่ต้องให้ไคลเอนต์ทั้งหมดอัปเดตทันที

What’s the safest way to roll out a schema change without downtime?

เริ่มจากการเปลี่ยนเชิงเพิ่ม เช่น เพิ่มคอลัมน์ที่เป็น nullable หรือตารางใหม่ จากนั้น deploy โค้ดที่รองรับทั้งรูปแบบเก่าและใหม่ ทำ backfill เป็นชุดเล็ก ๆ สลับพฤติกรรมการเขียน แล้วค่อยลบฟิลด์เก่าหรือเข้มงวดข้อจำกัดทีหลัง

How do I keep my API backward compatible during a migration?

จดรายการสิ่งที่ไคลเอนต์เก่าส่งและคาดหวัง แล้วหลีกเลี่ยงการเอาฟิลด์ออกหรือเปลี่ยนความหมาย เพิ่มฟิลด์ใหม่แบบ optional ยอมรับทั้งรูปแบบคำขอเก่าและใหม่ และเลื่อนการตรวจสอบ “required” จนกว่าอัตราการอัปเดตจะสูงพอ

What are dual-read and dual-write, and when should I use them?

Dual-write คือการเขียนข้อมูลทั้งที่ที่เก่าและที่ใหม่ในช่วงเปลี่ยนผ่าน ส่วน dual-read คืออ่านฟิลด์ใหม่แล้ว fallback ไปหาอันเก่า เก็บไว้นานพอให้ลูกค้าอัปเดต แต่ต้องเป็นสะพานชั่วคราว ติดตามเส้นทางที่ถูกใช้และวางแผนการล้างข้อมูลเมื่อพร้อม

How do feature flags reduce risk during API or DB changes?

Feature flags ช่วยให้คุณ deploy โค้ดโดยไม่เปิดใช้งานพฤติกรรมเสี่ยงทันที คุณจึงแยกการ “deploy” ออกจากการ “เปิดใช้” ได้ ช่วยทั้ง blue-green และ canary เพราะถ้าพบข้อผิดพลาดก็ปิดฟีเจอร์ได้โดยไม่ต้อง redeploy

What are the most common migration mistakes that cause outages?

การลบหรือเปลี่ยนชื่อคอลัมน์เร็วเกินไป การบังคับ NOT NULL ก่อนที่ไคลเอนต์จะส่งค่า และการรันมิเกรชันที่ล็อกตารางใหญ่เวลาท้ายชั่วโมงเป็นสาเหตุทั่วไป อีกปัญหาคือสมมติว่าข้อมูลทดสอบสะอาดเหมือน production ทำให้ backfill ล้มเหลวกับค่าว่างหรือรูปแบบแปลก ๆ

ง่ายต่อการเริ่มต้น
สร้างบางสิ่งที่ น่าทึ่ง

ทดลองกับ AppMaster ด้วยแผนฟรี
เมื่อคุณพร้อม คุณสามารถเลือกการสมัครที่เหมาะสมได้

เริ่ม