ป้องกัน Overselling — ทีมงานตรวจความจุและคำสั่งซื้อในระบบขายตั๋ว

ป้องกัน Overselling ในระบบขายตั๋ว: คู่มือคุมโควตาให้ถูกต้อง

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

ป้องกัน Overselling — ทีมงานตรวจความจุและคำสั่งซื้อในระบบขายตั๋ว
ภาพประกอบแนวคิด: ทีมงานตรวจความจุและคำสั่งซื้อในระบบขายตั๋ว

ป้องกัน Overselling หมายถึงอะไร

Overselling คือยืนยันการขายเกิน Capacity ที่มีอยู่ ในระบบตั๋วต้องนับทั้งตั๋วที่ยืนยันแล้วและสิทธิ์ที่ถืออยู่ตามนโยบาย รวมช่องทางเว็บ เคาน์เตอร์ และคู่ค้าซึ่งใช้โควตาร่วมกัน

กฎพื้นฐานคือ Confirmed + Active Holds ต้องไม่เกิน Capacity และจำนวนขายได้ต้องไม่ติดลบ ทุกช่องทางต้องใช้แหล่งตัดสินเดียวกันหรือโควตาย่อยที่แบ่งไว้ชัดเจน

กลไกควบคุมคำขอพร้อมกัน

ใช้ Atomic Conditional Update หรือ Transaction พร้อม Lock ที่เหมาะสม ตัวอย่างคืออัปเดตจำนวนคงเหลือเฉพาะเมื่อเพียงพอ แล้วตรวจจำนวนแถวที่เปลี่ยน ไม่ใช้การอ่านค่าเก่ามาตัดสินภายนอกธุรกรรม

เอกสาร PostgreSQL Explicit Locking อธิบาย Row-level Lock และผลต่อธุรกรรมที่แข่งขันกัน ต้องเลือกวิธีและ Isolation ให้ตรงกับทุกเส้นทางที่แก้ Inventory

Architecture ของ Inventory ที่เชื่อถือได้

ป้องกัน Overselling — แผนภาพองค์ประกอบระบบและจุดควบคุมสำคัญ
แผนภาพองค์ประกอบและจุดควบคุมสำคัญ

ทุกช่องทางขาย → Inventory Service → Database Transaction → Reservation/Order → Payment Confirmation ใช้ Cache สำหรับแสดงจำนวนโดยระบุว่าอาจเปลี่ยนระหว่างซื้อ

Reservation ต้องมี ID, Owner, จำนวน, วันหมดอายุ และสถานะ ในคำขอซ้ำ กุญแจรายการต้องทำให้ได้ผลเดิมแทนการถือโควตาเพิ่ม การสร้าง Hold กับการลดจำนวนต้องอยู่ในธุรกรรมที่สัมพันธ์กัน

Workflow ตัดและคืนโควตา

ป้องกัน Overselling — ลำดับขั้นตอนการทำงานและจุดตรวจสอบ
แผนภาพลำดับการทำงาน
  1. ตรวจคำขอและกุญแจป้องกันรายการซ้ำ
  2. ถือโควตาด้วยธุรกรรมที่ตรวจจำนวนเพียงพอ
  3. สร้างหรือคืน Reservation เดิมสำหรับคำขอซ้ำ
  4. รับผลชำระเงินและยืนยัน Hold ตามสถานะ
  5. ปล่อย Hold ที่หมดอายุหรือยกเลิกเพียงครั้งเดียว
  6. กระทบยอด Inventory กับ Hold และ Ticket

ประโยชน์ทางธุรกิจและเทคนิค

ธุรกิจลดเหตุที่รับเงินแล้วต้องปฏิเสธลูกค้า ทีมเทคนิคมี Invariant ที่ทดสอบได้ แต่การควบคุมถูกต้องอาจเพิ่มเวลารอเมื่อหลายคำขอแข่งขันกับแถวเดียวกัน ต้องวัดและเลือกโครงสร้างตามโหลด

ต้นทุนต้องรวมการแก้รายการชำระล่าช้า การคืนเงิน และการเฝ้าระวังโควตา ไม่ควรแลกความถูกต้องของ Inventory กับการตอบเร็วโดยไม่ประเมินผลธุรกิจ

กรณีใช้งาน: 50 คนซื้อโควตาที่เหลือ 2 ใบ

ตัวอย่างสมมติ: มี 50 คำขอซื้อใบละหนึ่งในเวลาใกล้กัน ระบบควรให้ Hold สำเร็จไม่เกินสองรายการ ที่เหลือได้ผลว่าไม่มีโควตาหรือเข้าคิวตามนโยบาย

ทดสอบทั้งคำขอจริงหลาย Connection และการ Retry หลัง Timeout หากใช้คำขอเดิมซ้ำต้องไม่ลดจำนวนอีก ก่อนเปิดขายควรพิสูจน์ยอดรวมหลังจบทดสอบ

Security ของจำนวนและคำขอ

ตรวจจำนวนเป็นจำนวนเต็มบวกและจำกัดตามนโยบายฝั่ง Server ไม่รับค่าติดลบที่ทำให้จำนวนคงเหลือเพิ่ม จำกัดอัตราคำขอและการถือสิทธิ์เพื่อป้องกันกักโควตาโดยไม่ชำระ

ตรวจว่า Reservation เป็นของผู้ใช้หรือ Session ที่ได้รับอนุญาตก่อนยืนยันหรือยกเลิก การรู้ Reservation ID ไม่ควรทำให้เปลี่ยนรายการของคนอื่นได้

Scalability และ Integration กับ Payment

แบ่งโควตาตามรอบหรือ Pool เพื่อลดแถวที่มีการแข่งขันสูง หากกระจายหลายภูมิภาคต้องเลือกว่าใครเป็นแหล่งเขียนหลักหรือแบ่งโควตาอย่างไร ไม่อาศัยข้อมูล Replica ที่หน่วงเพื่อตัดขาย

Payment อาจสำเร็จหลัง Hold หมดอายุ ต้องมีนโยบายรับมือ หากโควตาถูกขายแล้ว ห้ามยืนยันเพิ่มโดยอัตโนมัติ ให้เข้า Exception และจัดการตามผลชำระจริง

ปัญหาที่พบบ่อยและ Best Practices

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

ใช้ Reconciliation ตรวจว่าจำนวนรวมยังตรง พร้อมแจ้งเมื่อมีค่าผิด Invariant งานหมดอายุและงานยืนยันจ่ายต้องแข่งขันกันอย่างปลอดภัยใน Transaction

แนวทางระยะถัดไป

เมื่อโหลดเพิ่ม อาจใช้ Admission Queue และจำกัดงานเข้าเพื่อลดการแข่งขัน แต่ยังต้องรักษาความถูกต้องที่ฐานข้อมูล การเพิ่ม Redis หรือ Queue ไม่ได้ทำให้ Inventory ถูกต้องเองโดยไม่ออกแบบสถานะ

สรุปการป้องกัน Overselling

ป้องกัน Overselling ด้วยแหล่งตัดสินกลาง ธุรกรรมที่เปลี่ยนจำนวนแบบมีเงื่อนไข และ Idempotency ทดสอบทั้งซื้อพร้อมกัน คืนโควตาซ้ำ และชำระล่าช้าก่อนเปิดขาย

จุดตรวจสำคัญของ ป้องกัน Overselling

  • Confirmed + Active Holds ไม่เกิน Capacity
  • Atomic Update ตรวจจำนวนแถวที่เปลี่ยน
  • Hold และการลดโควตาบันทึกสัมพันธ์กัน
  • คืนโควตาได้ครั้งเดียว
  • ทดสอบหลาย Connection และ Late Payment

เตรียมข้อมูลเพื่อประเมินระบบกับ Zairosoft

หากต้องการประเมินแนวทางพัฒนาหรือปรับระบบ เตรียมช่องทางขายและโหลดในช่วงเปิดขาย เพื่อให้การคุยเริ่มจากขอบเขตและความเสี่ยงที่ชัดเจน ดูข้อมูลบริการและช่องทางติดต่อได้ที่ Zairosoft

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

ปิดปุ่มเมื่อขายหมดป้องกัน Overselling ได้ไหม?

ช่วยลดคำขอแต่ไม่เพียงพอ ต้องตรวจและตัดโควตาฝั่ง Server แบบ Atomic เพราะหลายคนอาจส่งคำขอพร้อมกัน

ใช้ Redis Lock แล้วพอไหม?

ไม่ควรถือว่าพอโดยลำพัง ต้องมีการรักษา Invariant ในแหล่งข้อมูลหลักและรับมือหมดอายุ การล่ม และการส่งซ้ำ

Hold หมดอายุแล้วจ่ายสำเร็จควรทำอย่างไร?

ตรวจว่ามีสิทธิ์และโควตายังจัดสรรได้หรือไม่ตามนโยบาย หากไม่ได้ให้เข้า Exception และคืนเงินหรือจัดทางเลือก ไม่ออกตั๋วเกินจำนวน

ต้องทดสอบโหลดแบบใด?

ทดสอบคำขอพร้อมกันกับโควตาน้อย คำขอซ้ำ การปล่อย Hold และการชำระมาชนกัน แล้วตรวจจำนวนและสถานะท้ายสุด

เราใช้คุกกี้เพื่อปรับปรุงประสบการณ์ของคุณบนเว็บไซต์ของเรา การเรียกดูเว็บไซต์นี้แสดงว่าคุณยอมรับการใช้คุกกี้ของเรา