แจ้งเพื่อทราบ: เนื้อหน้าต่อไปนี้ เป็นกรณีศึกษาที่เป็นการคาดเดาเหตุผลที่ทำไมถึงล่ม ซึ่งอยู่บนพื้นฐานข้อมูลจริงบางส่วน นำไปใช้อ้างอิงในเหตุการณ์จริงว่าระบบจะล่มเพราะสิ่งที่คาดการณ์นี้ไม่ได้ แต่เป็นเนื้อหา เพื่อใช้ศึกษาความเป็นไปได้จากประสบการณ์ของผู้เขียนเท่านั้น
จากกรณี เดี่ยว 10 ของโน้ส อุดมหยุดขายบัตรกะทันหันหลังระบบขายบัตรล่ม เลยเอามาตั้งโจทย์เล็กๆ ว่า
“มีร้านเซเว่นอีเลฟเว่นที่มีทั้งหมด 8,500 สาขา มีจุดขายเคาน์เตอร์เซอร์วิสรวม 20,000 จุด มีระบบรองรับธุรกรรมสูงสุดระดับ 1,000,000 รายการภายใน 1 วัน”
พูดง่ายๆ คือ มีระบบที่รองรับได้วินาทีละ 11.57 รายการ ตลอดทั้งวัน
จากข่าวต้นเรื่องและโจทย์ทำให้รู้ว่า มีการทดสอบระบบขายบัตร เดี่ยว 10 พร้อมกัน 600 สาขาก็สามารถรับมือได้ แต่ไม่ได้บอกว่ารองรับได้กี่รายการต่อวินาที แต่ผู้ทดสอบลืมไปหรือเปล่าวระบบต้องรองรับ 20,000 จุด ไม่ใช่ 600 จุด ซึ่งทำให้เห็นว่า คนทดสอบระบบกำลังทดสอบระบบที่อัตราความสามารถระบบที่เพียง 1 ใน 30 ของระบบที่กำลังจะต้องไปใช้งานจริงในอนาคต
ลองนึกภาพตามง่ายๆ ว่ามีเซเว่นอีเลฟเว่นและจุดขายเคาน์เตอร์เซอร์วิส กดปุ่มซื้อพร้อมกันในวินาทีเดียวกัน ตอนเปิดขายบัตร เกือบ 20,000 จุดทั่วประเทศ ระบบที่รองรับได้วินาทีละ 11.57 รายการจะรองรับไหวไหม? เพราะระบบที่จะรองรับการทำรายการแบบนี้ได้ต้องพูดว่า “ระบบรองรับธุรกรรมสูงสุดระดับ 1,728,000,000 รายการภายใน 1 วัน” มันถึงจะถูกมากกว่า วิธีการแก้ไขที่ดีอีกวิธีคือการเลี่ยงยิงระบบโดยเพิ่มระบบคิว แบบคล้ายๆ กับจองตั๋วของ AirAsia ก็เป็นการแก้ปัญหาที่ถือว่าโอเคระดับหนึ่ง แต่ก็ยังทำให้ระบบโดยรวมจองตั๋วไปได้ตลอดจนจบทุกๆ รายที่เข้าไปจอง ส่วนอีกแบบคือใช้พวก Cloud service เอาก็ได้นะ ถ้าระบบที่คาดการณ์ไว้แล้วมันไม่ไหวก็ scale เอาได้ทันที แต่ส่วนตัวคิดว่า วิธีคิดของผู้ใหญ่ที่ตัดสินใจคงยังยึดติดกับอะไรเดิมๆ ก็ได้แต่ยืนไว้อาลัย เช่นเรื่องความลับของข้อมูลอะไรพวกนี้ เพราะงานระดับใหญ่แบบนี้มักเลือก Cloud ระดับ Enterprise ที่ค่อนข้าง private และมี NDA Agreement ที่ค่อนข้างเชื่อถือได้อยู่แล้ว
เรากลับมาที่ส่วนการออกแบบ ส่วนตัวผมเชื่อว่าระบบออกแบบให้รองรับคนเยอะ มันก็รองรับได้นะ คือจากระบบที่ผมดูแลและยังคงปรับปรุงระบบอยู่เรื่อยๆ นั้น การรองรับการทำงานแบบวินาทีต่อวินาทีที่มีการกระหน่ำเข้ามาแบบนี้ ปัญหานี้ส่วนใหญ่ที่เจอคือ I/O ระหว่าง DB กับ App มันตันครับ ผมเจอเยอะที่ว่า CPU ทำงานยังไม่ถึง 10% เลย แต่ process มันไปค้างที่ I/O ที่กำลังอ่าน-เขียนกันอยู่ โดยผมลอง top ดูรายการของ process จะเห็นเลยว่า process ฝั่ง App ถูก fork เป็นพันตัว แต่โดน waiting เพียบ เพราะมันไป waiting ข้อมูลที่รอจากฝั่ง DB ซึ่ง DB มันก็กำลังปิดงานที่กำลัง process อยู่เรื่อยๆ ซึ่งในระดับของ DB มันมีคิวอยู่แล้ว มันค่อยๆ ทำไปตามสภาพและความสามารถของ H/W ที่มีอยู่ แต่เมื่อคิวมันเริ่มตัน มันทำงานช้าจนไม่พอที่จะตอบสนองได้ทุก process ที่กำลังกระหน่ำเข้ามา มันเลยพาลทำล่มหมดเพราะหน่วยความจำไม่พอที่จะให้ process ของ App มันไปรอ waiting ได้ทุกตัวครับ
วิธีการแก้ของพวกนี้คือทำยังไงก็ได้ให้ I/O ฝั่ง DB มันทำงานให้ตอบหนองทันกับ process ฝั่ง App ให้ได้ เพื่อไม่ให้เกิด waiting ค้างในระบบนานจนล้นกว่าหน่วยความจำที่มีน่ะครับ เดี่ยวนี้ที่เจอๆ ก็มีหลายแบบนะ คือจับ DB ใช้ SSD ตัวแรงสุด ก็ช่วยได้มาก หรือเอา DB ใส่พวก MEMORY DB แทน ก็ทำงานได้เร็วมากๆ (แต่ตัวหลังไฟดับทีนี่งานเข้าเลยนะ) หรือจะแบ่งโหลดไปเลยก็ได้นะ โดยมี App จัดนึงในการคิวขั้นกลางว่า DB ตัวไหนรับโหลดของ process ID อะไรแบบนั้น ซึ่งถ้าเป็นแบบจองตั๋วแบบนี้แบ่งไปเป็น farm server เอาก็ได้นะ ตัวเลือกรอบการแสดง ก็รู้แล้วว่า farm server ตัวไหนจะรับโหลดรอบไหนไปแทน หรือจะให้ละเอียดกว่านั้นก็คือกระจายระดับ zone ของแต่ละรอบก็ทำให้ระบบโดนกระจายโหลดไปได้มาก ไม่ได้กระหน่ำเข้ามาที่ระบบตัวเดียว แล้วพาลทำล่มทั้งระบบ
คือวิธีการแก้ไขหรือวางแผนมีหลายรูปแบบมากๆ อยู่ที่ว่าตอนทดสอบระบบคิดถึงระดับความเลวร้ายที่สุดที่ระบบจะรองรับได้หรือไม่มากกว่า งานนี้คนทดสอบระบบโลกสวยเกินไปหน่อย (╯°□°)╯︵ ┻━┻)