เมื่อเช้าวันที่ 24 มกราคม 2564 มีคนแห่จองหุ้น OR ทางเว็บ K-My Invest เป็นจำนวนมาก จนเว็บล่มเป็นระยะๆ เลยจะมาเล่าไอเดียการออกแบบระบบจอง แบบสนุกๆ กัน 😉 (แต่ผมจองได้นะ เจอหน้า error ไม่กี่ครั้ง สาเหตุปลายทางน่าจะ test พลาด สาเหตุต้นทางน่าจะประเมิน scenario พลาด และการพัฒนาระบบพลาด แต่ก็เอาใจช่วยครับ สู้ๆ เลิฟๆ ปรึกษาอดีตผู้บริหารที่ย้ายไปอยู่ KTB ได้ครับ ว่าเขาทำยังไงให้รับมือคนเข้ามาสมัครสิทธิโครงการคนละครึ่งได้ 1.34 ล้านคนเสร็จใน 9 นาที)
ระบบจองแบบที่ ‘อาจชนกันระดับข้อมูล’ มีหลายประเภท เช่น ระบบจองตั๋วภาพยนตร์, ระบบจองตั๋วการแสดงโชว์/คอนเสิร์ตแบบตั๋วผูกกับเลขที่นั่ง, ระบบจองตั๋วเครื่องบิน/รถไฟ/รถโดยสาร และรวมถึงระบบจองหุ้น, ระบบสมัครใช้สิทธิโครงการ ‘คนละครึ่ง’ และอีกหลายโครงการของภาครัฐ
ระบบแบบนี้มีคุณลักษณะ (characteristics) คล้ายกันหลักๆ ได้แก่
- คนจำนวนมากจากทุกสารทิศเข้ามา access ระบบพร้อมๆ กัน
- สินค้า (ตั๋ว/ที่นั่ง/สิทธิ/จำนวนหุ้น) มีจำนวนจำกัด
- มีความต้องการจองสินค้าเดียวกันพร้อมกัน (แบบจองตั๋วหนักสุด)
- มีระยะเวลาจองจำกัด
technical concern สำคัญ ได้แก่
- load & I/O ไล่ตั้งแต่เน็ตเวิร์กยัน bus ในเครื่องเลย
- state ของสินค้า
- operation เช่น ค้นหา แสดงผล จอง ยกเลิก ชำระเงิน
- ลูกค้า/ผู้ใช้บริการ ซื้อ/จอง/ใช้สิทธิ ได้ครั้งละเท่าไหร่ เช่น โครงการคนละครึ่งใช้ได้ 1 คน/1 สิทธิ, จองหุ้น OR ขั้นต่ำ 300 หุ้น
- resource utilization เช่น IT resource capacity ที่มีในมือ
- existing resources เช่น database, web/app server เป็นแบบไหน รองรับ scale out ได้หรือไม่ และยิ่งถ้ามีแต่ RDBMS ก็ฉิบหายแน่ ไม่ต้องเปิดตัว รอล่มได้เลย
โซลูชั่น คร่าวๆ แบบไม่แตะทฤษฎีและศัพท์เฉพาะ และขออธิบายเฉพาะท่อนสินค้า เพราะท่อนจัดการ load & scale out สมัยนี้ทำไม่ยากแล้ว ใช้ตังค์โยนงานขึ้นไปรันบนเมฆโลด
- แบ่งสินค้าออกเป็นหลายๆ ส่วน หากแบ่งแต่ละส่วนจำนวนเท่าๆ กันก็ง่ายหน่อย เช่น สมมุติหุ้น OR ที่เปิดจองมีทั้งหมด 120 ล้านหุ้น แบ่งเป็น 400,000 ส่วน ส่วนละ 300 หุ้น เศษที่เหลือก็อยู่ในส่วนสุดท้ายไป
- จัดกลุ่มสินค้าแต่ละส่วนเป็นจำนวน N กลุ่ม เช่น จัดกลุ่มละ 1,000 ส่วน จะได้กลุ่มละ 300,000 หุ้น ให้นึกถึงการเอาลูกสตรอเบอรี่ใส่กล่องกล่องละ 300 ลูก แล้วเอามาจัดกลุ่มกลุ่มละ 1,000 กล่อง
- กระจายสินค้าแต่ละกลุ่มไปเก็บคนละเครื่องกัน
- แต่ละเครื่องลง agent เพื่อติดตามสถานะคงเหลือของจำนวนกลุ่มสินค้า แล้วแจ้งสถานะไปยังเครื่องกลางที่แยกต่างหากเพื่อติดตามสถานะสินค้าในทุกเครื่อง
- ใช้การกระจาย load และ I/O โดยเมื่อมี request ของลูกค้า/ผู้ใช้บริการเข้ามาถึงระบบ ผ่านจุดต่างๆ เข้ามา จนจะถึงส่วนสินค้า ก็กระจาย request ไปยังเครื่องต่างๆ แบบสุ่ม
- หากจำนวนกลุ่มสินค้าในเครื่องใดมีเหลือน้อยกว่าความต้องการซื้อ/จองของลูกค้า/ผู้ใช้บริการคนใด ก็ฟอร์เวิร์ด request ไปยังเครื่องอื่นที่มีจำนวนเหลือพอ
- มีระบบ registry เพื่อบันทึกและค้นคืนสถานะจำนวนกลุ่มสินค้าในแต่ละเครื่อง จะได้ทราบว่าเครื่องไหนเหลือเท่าไหร่ แล้วหากเครื่องไหนไม่พอควรฟอร์เวิร์ด request ไปเครื่องไหนดี
- หาก stream I/O (request) ไหลทะลักเข้ามาล้นหลามราวน้ำป่าไหลหลาก ก็ต้องมีการ ‘หน่วงน้ำ’ และ ‘พักน้ำ’ และ ‘ระบายน้ำ’- หน่วงน้ำ และ พักน้ำ ด้วยการเอา request ไปเข้าคิว ในหน้าจอก็ขึ้นอะไรเพลินๆ ให้ลูกค้า/ผู้ใช้บริการดูหรือเล่นสนุกๆ รอไป แต่อย่าเสือกขึ้น error มันไม่เท่ จะทำให้ UX เสีย- พักน้ำ ข้อมูลกลุ่มสินค้าควรใช้เป็น in-memory เพื่อลด latency ในการ access disk แต่ถ้าใช้ cloud ค่า memory usage มันแพง จะใช้ disk ก็ได้ ถ้าลูกค้าไม่ด่าหากช้า- ระบายน้ำ ด้วยการโยน request ไปรันบนเมฆ แต่ต้องทำ provisioning รอไว้ก่อน ไม่ใช่อิมโพรไวซ์ด้นสด การ spawn instance ใหม่ไม่ใช่ 2 วิเสร็จ
- ออกแบบการจัดการทรานแซกชั่นจังหวะ จอง ยกเลิก จองเพิ่ม จองใหม่ โดยจัดการ state ดีๆ พยายามให้เป็น stateless ให้มากที่สุดเท่าที่จะเป็นได้ เช่น ถ้าจองปุ๊บก็ล็อกปั๊บ แล้วให้เวลาไปจ่ายเงิน เช่น 15 นาที ไม่เสร็จก็ยกเลิกการจองอัตโนมัติไป
- การแบ่งกลุ่ม, การกำหนดจำนวนกลุ่ม, การกำหนดจำนวนสินค้าต่อกลุ่ม, การออกแบบทรานแซกชั่น ต้องเข้าใจ business logic & business process & business concern & business constraint & business goal & requirement อย่างดี ไอทีอย่านั่งเทียนมั่วนิ่มคิดเอง
จริงๆ ยังมีอีกครับ แต่ขี้เกียจพิมพ์ละ ชักยาว จริงๆ มันคือการทำ multiple pool & pool partition, การจัดคิว, การทำ shadow process (หลอกให้ผู้ใช้เพลินกับหน้าจอไปก่อน แล้วแอบทำบางอย่างไป) จริงๆ มีศัพท์ที่คนทำส่วน frontend เค้าใช้กัน แต่ผมจำชื่อไม่ได้ นอกจากนี้ก็ใช้ cache, cloud, logging & monitoring, asynchronous, load balance
ที่เล่ามาทั้งหมด สังเกตได้ว่า ผมไม่แตะเทคโนโลยีสักเท่าใดเลยนะครับ เพราะผมไม่ชอบเริ่มแก้ปัญหาด้วยเทคโนโลยี แต่เริ่มด้วย design principle แทนครับ เพราะมัน beyond technology & implementation
ซึ่ง technology & implementation หรือ How ควรมาทีหลังครับ เราต้องเคลียร์กับ problem context, problem domain, business & system characteristics ก่อน
หุ้น และ สิทธิโครงการคนละครึ่ง มันไม่มี identity ไม่เหมือน ตั๋วภาพยนตร์ ตั๋วเครื่องบินที่มี identity เพราะผูกกับที่นั่ง ดังนั้น การจอง หุ้น และ สิทธิโครงการคนละครึ่ง จึงง่ายกว่าหน่อย และ เล่นกับการกระจาย I/O ได้เต็มที่กว่าจริงๆ ระบบจองตั๋วที่ผูกกับที่นั่งจะเล่นกับการกระจาย I/O จัดๆ ก็ได้ แต่ต้องออกแบบระบบ registry ดีๆ เร็วๆ
ในโลกการลงทุน มีระบบประเภทหนึ่งที่รันอยู่ในโลกตรงกลางระหว่างลูกค้า/ผู้ใช้บริการ กับ ปลายทาง (ตลาด/โบรกเกอร์) เรียกว่า dark pool เราจองหุ้น ซื้อ/ขายหุ้น เราไม่เห็นอยู่แล้วนี่ ว่า…เกิดอะไรขึ้นในนั้น ตั้งแต่คำสั่งออกจากเครื่องของเรา ก่อนไปถึงปลายทางหรือตลาดฯ หรือแม้แต่เมื่อไปถึงปลายทางแล้ว?
หวังว่าที่พิมพ์มายาวเหยียดจะพอเป็นประโยชน์ไม่มากก็น้อยนะครับ ^^