
จากการแบ่งปันความรู้และประสบการณ์เรื่องของ Idempotency
โดยเกิดจากปัญหาการทำซ้ำของระบบ
ทั้งจากผู้ใช้งาน หรือ process/workflow การทำงานของระบบก็ตาม เช่น
- ผู้ใช้งานสั่งซ้ำ ๆ แบบไม่ตั้งใจ เช่นกดปุ่มซ้ำ ๆ เมื่อระบบช้า เป็นต้น
- ระบบการทำงานมีการจัดการ timeout และ retry
- ระบบ network มีการ retry
- Load balancer และ API gateway มีการตั้งค่าr retry
ซึ่งปัญหาเหล่านี้เราควรวางแผน ออกแบบระบบการทำงาน
เพื่อป้องกันไม่ให้ปัญหานี้เกิดขึ้น
โดยแนวคิดเรื่องนี้คือ Idempotency
นั่นคือเมื่อมีการทำ process หนึ่ง ๆ ซ้ำ ๆ ไม่ว่าจะกี่ครั้งก็ตาม
ก็จะได้ผลลัพธ์เหมือนกับครั้งแรกเสมอ
ยกตัวอย่างเช่น
ในระดับ UI นั้นมักจะทำการ disable ปุ่มบนหน้าจอ
หลังจากที่ผู้ใช้งานกดไปแล้ว และ แสดง progress bar
เพื่อไม่ให้ผู้ใช้งานกดปุ่ม หรือ ทำงานซ้ำ
หรือป้องกันการ refresh หน้า browser อีก
ในระดับ code เมื่อมีการเรียกใช้ function/method หนึ่ง ๆ ซ้ำ ๆ
จะได้ผลลัพธ์การทำงานเหมือนครั้งแรกเสมอ
นั่นคือสถานะหลังการทำงานเสร็จแล้ว จะมีค่าเท่าเดิม
ยกตัวอย่างเช่น
ในระดับ business process ก็ต้องทำการตรวจสอบเช่นกัน
เช่น ถ้ามีการสั่งซื้อสินค้า หรือ ทำการชำระเงิน ก็ต้องทำเพียงครั้งเดียวเสมอ
มิเช่นนั้น จะเกิด duplicate order
และยิ่งแย่ไปกันใหญ่ เมื่อมีการชำระเงินซ้ำ ๆ (double spending)
ซึ่งจะทำให้ปัญหาเกิดกับฝั่งของ business และ operation เยอะแน่นอน !!
ตัวอย่าง process การทำงาน จะตรวจสอบอย่างไร ?
ว่าคือการสั่งซ้ำ ?
เช่น hash ข้อมูล + เวลา ของ order นั้น ๆ
เช่น การใช้ idempotent key หรือ reference key เพื่อใช้ในการตรวจสอบ
เช่น การใช้ความสามารถของ database เพิ่ม idempotent key ที่ unique เข้ามา

โดยปกติแล้วทาง client
จะต้องทำการสร้าง idempotent key ขึ้นมา ก่อนจะเริ่ม process การทำงาน
เช่นในการสั่งซื้อสินค้านั้น
จะเริ่มสร้าง idempotent key ตั้งแต่ checkout process ในฝั่ง client
จากนั้นเมื่อมีการ submit order เข้ามายังระบบงาน
จะทำการตรวจสอบ idempotent key และ order detail เสมอ เช่น
- ถ้า idempotent key ซ้ำหรือเคยทำงานแล้ว ต้องตรวจสอบสถานะของ order นั้นก่อนว่า ทำงานเสร็จแล้ว (success) หรือ ยังทำงานอยู่ (in-process)
- ถ้าทำงานเสร็จแล้ว จะทำการส่งผลการทำงานเดิมกลับไป
- ถ้ายังทำงานอยู่ จะ return error code = 409 with Conflict processing กลับไป
- ถ้า idempotent key ไม่ซ้ำ หรือ ไม่มีในระบบ จะเริ่มทำงานด้วย status=in-process นั่นเอง
หรือบางระบบจะเปลี่ยนการสร้าง idempotent key มาเป็นฝั่ง server แทน
เช่นอาจจะใช้ชื่อว่า reference key ก็ได้
ซึ่งจะทำการส่ง request มาเพื่อขอ reference key ก่อนการทำงานนั่นเอง
ตัวอย่าง flow การทำงานคร่าว ๆ

โดยการจัดเก็บและตรวจสอบ idempotent key นั้น
อาจจะใช้พวก key-value database เข้ามาจัดการก็ได้
ซึ่งง่ายต่อการจัดการ ทั้งเรื่องของ expire time ของ key
และความรวดเร็วของการทำงาน (อย่าตรวจสอบผ่าน RDBMS มากนัก มันเหนื่อย !!)
ส่วนข้อมูลที่จัดเก็บลง database ก็เพิ่ม idempotent key เข้าไปด้วย (unique key)
เพื่อความมั่นใจว่า จะไม่มีข้อมูลที่ซ้ำถูกบันทึกลงไปในระบบ
สามารถใช้หลายวิธีการร่วมกันได้
เพื่อลดหรือแก้ไขปัญหาที่เกิดขึ้นได้
ปัญหาหนึ่ง ๆ มีแนวทางการแก้ไขมากกว่าหนึ่งทางเสมอ
ขึ้นอยู่กับความสำคัญของการทำงานนั้น ๆ ด้วย
รวมทั้งเรื่องของจำนวนของผู้ใช้งานด้วย (Request per Seconds ?)
ว่าเพิ่มขั้นตอนเหล่านี้ไปแล้ว เพิ่มหรือลด performance ของระบบ และ response time !!
ลองนำไปปรับปรุงการทำงานของระบบกันดูครับ
ขอให้สนุกกับการ coding
แก้ไขปัญหา ไม่ใช่สร้างปัญหา !!