แนวทางเรื่องของการแก้ไขปัญหาทำซ้ำของระบบงาน (Prevent Duplication)

ในระบบงานทำงานต่าง ๆ ตั้งแต่เรียบง่ายไปจนถึงระบบแบบกระจาย (distributed system)
มักจะเจอปัญหาปวดหัวเรื่องของ การทำงานซ้ำ ๆ (duplication)
ส่งผลให้ระบบงานทำงานผิดพลาด
และส่งผลกระทบไปยังผู้ใช้งานอีก
ซึ่งถ้าไม่ได้ออกแบบระบบงานเพื่อป้องกันปัญหานี้ไว้
น่าจะมองโลกในแง่ดีเกินไปแน่ ๆ
เรื่องจากระบบต่าง ๆ มันพร้อมพัง หรือ มีปัญหาเสมอ
มาดูแนวทางในการป้องกันปัญหาการทำซ้ำบ้าง ว่ามีอะไรบ้าง ?
ถ้าเป็นการใช้ผ่าน web/mobile มักจะทำการ disable ปุ่มต่าง ๆ
เพื่อไม่ให้ผู้ใช้งานกดซ้ำ ๆ เข้ามา
แต่ถ้าผู้ใช้งานยังกดเรื่องเดิมซ้ำ ๆ มาอีกหลังจากทำงานเสร็จแล้ว
จะด้วยความตั้งใจหรือไม่ตั้งใจ จะจัดการอย่างไร
ต้องมีการทำ maker-checker เพิ่มอีกไหม (ตรวจสอบซ้ำก่อนทำงานจริง ๆ)
หรือระบบต้องมีการจัดการ policy ขึ้นมา
ว่าในแต่ละ operation เดิม ๆ คนเดิม ๆ เรื่องเดิม ๆ ห้ามทำงานซ้ำภายใน x นาที/ชั่วโมง เป็นต้น
มันคือการกำหนด rate limit ต่าง ๆ นั่นเอง
ยิ่งถ้าการทำงานต้องไปเรียก 3-party API อีก ก็จำเป็นต้องจัดการเรื่อง resource consumption อีกด้วย
มิเช่นนั้นอาจจะทำให้เกิดปัญหาตามมา รวมทั้งค่าใช้จ่ายอาจจะสูงเกินความจำเป็น
ยิ่งถ้าระบบการทำงานเป็น batching process หรือตั้งเวลาทำงาน
ยิ่งต้องระมัดระวังอย่างมาก ในการทำซ้ำ ๆ
ทั้งจากเรื่องของ network มีปัญหา
ทั้งจาก retry policy ของการทำงาน
แนวทางในมักจะใช้งานกันอีกคือ Idempotency Keys
โดยในทุก ๆ request หรือ process การทำงานจะส่ง unique Idempotency Key ไปด้วย
ซึ่งมักจะเป็น UUID (Universally unique identifier)
จากนั้น service ที่รับ request/process มาทำงาน
จะต้องทำการตรวจสอบก่อนว่า UUID นั้นทำงานไปแล้วหรือยัง
ถ้ายังไม่ทำงาน ก็จะเริ่มทำงานนั่นเอง
แต่ถ้าทำงานไปแล้ว ก็จะไม่ทำงาน (และส่งผลการทำงานก่อนหน้ากลับไปนั่นเอง)
เพื่อไม่ให้เกิดการทำงานซ้ำ ๆ
มักจะจัดเก็บ UUID ในพวก memory store

หรืออาจจะใช้งาน Database constraint เข้ามาจัดการเรื่องนี้ก็ได้เช่นกัน
แต่ระวังเรื่องของการ scaling และ locking ของ database ด้วย
หรืออาจจะใช้งาน Distributed lock มาใช้งานก็ได้
ความซับซ้อนเอาตามที่เชี่ยวชาญกันได้เลย
สามารถเอา API gateway เข้ามากั้นเพื่อจัดการสิ่งต่าง ๆ เหล่านี้ได้
โดยไม่ต้องไปแก้ไขระบบเดิม ก็เป็นอีกทางเลือกที่น่าสนใจ
บางระบบมีการทำงานแบบ fire-and-forgot
ซึ่งทำให้เกิดปัญหาได้ เช่นทำงานสำเร็จหรือไม่
ถ้าทำงานไม่สำเร็จ จะจัดการอย่างไร
และไม่ให้เกิดการทำงานซ้ำ ๆ ที่ส่งผลต่อระบบและผู้ใช้งาน
นั่นแสดงว่า ต้องทำการ tracking หรือ เก็บ state ของแต่ละขั้นตอนของทำงานนั้น ๆ ไว้ด้วยหรือไม่
เพื่อให้การ retry เริ่มในจุดที่มีปัญหาจริง ๆ ไม่ใช่เริ่มใหม่ทั้งหมด

แน่นอนว่า แต่ละวิธีการนั้น ก็ต้องดูทั้งความต้องการ ข้อจำกัดต่าง ๆ
ซึ่งล้วนแตกต่างกันตามระบบนั้น
ก็เลือกให้เหมาะสมครับ
Article by Somkiat Puisungnoen
To be Craftmanship