เอกสารอ้างอิงการประยุกต์ใช้งาน นี่เป็นสถาปัตยกรรมตัวอย่างและรายการตรวจสอบขอบเขตงาน ไม่ใช่โครงการลูกค้าที่ผ่านการตรวจสอบหรือการติดตั้งใช้งานที่มีการวัดผล เทคโนโลยี ขอบเขตการผสานระบบ และรายการส่งมอบจะตกลงกันตามโจทย์งานจริง
สถานการณ์และข้อจำกัด
แบรนด์ค้าปลีกที่จำหน่ายผ่านมินิโปรแกรม WeChat และมีหน้าร้านด้วย ข้อกำหนดสำคัญคือสต็อกต้องถูกต้องตรงกันระหว่างช่องทางในช่วงโปรโมชัน: การอัปเดตสต็อกของแต่ละช่องทางแยกจากกันอาจเสี่ยงต่อการขายเกินสต็อก หากไม่ได้กำหนดกฎการจอง การซิงโครไนซ์ และการกระทบยอดไว้อย่างชัดเจน คะแนนสมาชิกและคูปองก็ต้องตัดยอดอย่างสอดคล้องกันด้วย เพราะการใช้ส่วนลดซ้ำสองครั้งทำให้เกิดความเสียหายทางการเงินโดยตรง
สถาปัตยกรรม
ชั้นระบบและหน้าที่รับผิดชอบ
| ชั้นระบบ | เทคโนโลยี | หน้าที่รับผิดชอบ |
|---|---|---|
| ไคลเอ็นต์ | UniApp (WeChat + Douyin จากโค้ดเบสเดียว) | เรียกดูแค็ตตาล็อก ตะกร้าสินค้า ชำระเงิน และศูนย์สมาชิก ไม่เชื่อถือกฎทางธุรกิจใด ๆ ที่ฝั่งนี้ ไคลเอ็นต์มีหน้าที่แสดงสถานะที่เซิร์ฟเวอร์ยืนยันแล้วเท่านั้น |
| API | Go + Gin ทำงานแบบไร้สถานะหลังโหลดบาลานเซอร์ | ตรวจสอบคำขอ ยืนยันตัวตน กฎทางธุรกิจ และขอบเขตธุรกรรม รองรับการขยายระบบในแนวราบได้ เพราะไม่มีสถานะเซสชันอยู่ในโปรเซส |
| แคช | Redis | ข้อมูลแค็ตตาล็อกที่เรียกใช้บ่อย ตัวนับสต็อกสำหรับแฟลชเซล ล็อกแบบกระจาย และคีย์ idempotency สำหรับ callback การชำระเงิน |
| พื้นที่จัดเก็บข้อมูล | MySQL พร้อมรีพลิกาสำหรับอ่าน | ข้อมูลหลักที่ใช้อ้างอิง การเขียนข้อมูลไปยังฐานข้อมูลหลัก ส่วนการอ่านแค็ตตาล็อกและรายงานอาจกำหนดเส้นทางไปยังรีพลิกาได้เมื่อปริมาณการอ่านมีเหตุผลรองรับ |
| ระบบผู้ดูแล | Vue 3 + Element Plus | จัดการแค็ตตาล็อก คำสั่งซื้อ สินค้าคงคลัง โปรโมชัน และร้านค้า โดยบังคับใช้สิทธิ์จากแบ็กเอนด์ |
| งานอะซิงโครนัส | เวิร์กเกอร์ประมวลผลคิว | กระทบยอดการชำระเงิน ส่งข้อความ สรุปรายงาน และคืนสต็อกเมื่อคำสั่งซื้อหมดเวลา — งานใดก็ตามที่ต้องไม่ขัดขวางคำขอในขั้นตอนสั่งซื้อ |
โมเดลข้อมูล
ตารางด้านล่างมีชุดกฎที่ทุกส่วนอื่นต้องอาศัย หากออกแบบส่วนนี้ผิด จากเดโมที่ใช้งานได้ก็อาจกลายเป็นระบบที่ต่อยอดไม่ได้
เอนทิตีหลัก
| เอนทิตี | ฟิลด์หลัก ความสัมพันธ์ และกฎ |
|---|---|
| product / sku | หนึ่ง product เชื่อมโยงกับ SKU หลายรายการตามชุดค่าคุณลักษณะ ราคาและสต็อกผูกกับ SKU ไม่ใช่ product มิฉะนั้นจะต่อยอดการกำหนดราคาสำหรับสินค้าหลายรูปแบบไม่ได้ |
| inventory | แถวข้อมูลที่ใช้ (sku_id, location_id) เป็นคีย์ และเก็บ on_hand กับ reserved สต็อกคงเหลือพร้อมจำหน่ายคำนวณจาก on_hand ลบ reserved ทั้งนี้ยังต้องทดสอบธุรกรรมและการกระทบยอดเพื่อค้นหาความคลาดเคลื่อน |
| inventory_txn | บัญชีรายการที่เพิ่มรายการได้เท่านั้น ห้ามแก้ไขหรือลบ บันทึกทุกความเคลื่อนไหวของสต็อกพร้อมรหัสเหตุผลและคำสั่งซื้อต้นทาง สต็อกปัจจุบันต้องสร้างกลับขึ้นมาได้เสมอโดยเล่นรายการในบัญชีนี้ซ้ำ นี่ทำให้ตรวจสอบความคลาดเคลื่อนได้ แทนที่จะเป็นเรื่องโต้แย้งกัน |
| order / order_item | คำสั่งซื้อเก็บสถานะตามลำดับขั้นและยอดรวม ส่วนรายการสินค้าบันทึกภาพข้อมูลชื่อ SKU ข้อมูลจำเพาะ และราคาต่อหน่วย ณ เวลาที่ซื้อ เพื่อป้องกันไม่ให้การแก้ไขแค็ตตาล็อกในภายหลังเปลี่ยนประวัติคำสั่งซื้อ |
| payment_txn | รหัสธุรกรรมของเกตเวย์ จำนวนเงิน สถานะ และเนื้อหา callback ดิบ กำหนดให้รหัสธุรกรรมไม่ซ้ำ เพื่อไม่ให้ callback WeChat Pay ที่ส่งซ้ำถูกนำไปใช้สองครั้ง |
| member / point_txn / coupon | ยอดคงเหลือและคะแนนของสมาชิกคำนวณจากบันทึกธุรกรรมที่เพิ่มรายการได้เท่านั้น ห้ามแก้ไขหรือลบ แถวคูปองเก็บขอบเขต เกณฑ์ขั้นต่ำ ลำดับความสำคัญในการใช้ร่วมกัน และเวลา used_at เพื่อบังคับใช้การใช้ได้ครั้งเดียว |
อินเทอร์เฟซหลัก
เอนด์พอยต์ที่บังคับใช้กฎทางธุรกิจ
| เอนด์พอยต์ | วัตถุประสงค์และข้อควรพิจารณาด้านการทำงานพร้อมกัน |
|---|---|
| POST /api/v1/orders | สร้างคำสั่งซื้อและจองสต็อกภายในธุรกรรมฐานข้อมูลเดียว ในช่วงที่มีแฟลชเซล การจองจะเริ่มด้วยการลดค่า Redis แบบอะตอมิก โดยใช้ MySQL เป็นแหล่งข้อมูลหลักสำหรับการตัดยอด ไคลเอ็นต์ส่งคีย์ idempotency เพื่อป้องกันการแตะซ้ำแล้วสร้างคำสั่งซื้อสองรายการ |
| POST /api/v1/payments/callback | callback จากเกตเวย์ ใช้รหัสธุรกรรมเกตเวย์เพื่อให้ทำงานแบบ idempotent ตรวจสอบลายเซ็น และเลื่อนสถานะคำสั่งซื้อไปข้างหน้า ส่งคืนผลสำเร็จก็ต่อเมื่อบันทึกการเปลี่ยนสถานะแล้ว มิฉะนั้นเกตเวย์จะลองส่งซ้ำต่อไป |
| POST /api/v1/orders/{id}/cancel | คืนสต็อกที่จองไว้และคืนการใช้คูปองกับคะแนนในธุรกรรมเดียวกับที่ปิดคำสั่งซื้อ |
| GET /api/v1/skus/{id}/availability | อ่านสต็อกพร้อมจำหน่ายผ่านแคชที่มี TTL สั้น ยอมให้ข้อมูลสต็อกที่แสดงล่าช้ากว่าความเป็นจริงได้โดยตั้งใจ โดยมีเพียงธุรกรรมคำสั่งซื้อเท่านั้นที่เป็นข้อมูลชี้ขาด |
| POST /api/v1/admin/inventory/adjust | เขียน inventory_txn พร้อมรหัสเหตุผลและรหัสผู้ปฏิบัติงาน แทนการแก้ตัวเลขสต็อกโดยตรง การปรับแก้ด้วยมือทุกรายการจึงยังตรวจสอบย้อนกลับได้ |
การตัดสินใจด้านเทคนิค
- เลือก UniApp แทนการแยกมินิโปรแกรมเนทีฟ WeChat และ Douyin ใช้ขั้นตอนอีคอมเมิร์ซส่วนใหญ่ร่วมกัน การใช้โค้ดเบสเดียวจึงลดการดูแลรักษาส่วนที่ซ้ำซ้อน แยกการชำระเงินและการเข้าสู่ระบบเฉพาะแพลตฟอร์มไว้หลังชั้นอะแดปเตอร์ แทนการกระจายไว้ทั่วหน้า
- จองสต็อกเมื่อวางคำสั่งซื้อ ไม่ใช่เมื่อชำระเงิน หากจองเมื่อชำระเงิน ลูกค้าอาจชำระเงินซื้อสินค้าที่ขายไปแล้ว ข้อแลกเปลี่ยนคือคำสั่งซื้อที่ยังไม่ชำระจะกักสต็อกไว้ จึงกำหนดเวลาให้การจองหมดอายุและให้เวิร์กเกอร์คืนสต็อก
- คำนวณสต็อกพร้อมจำหน่าย ไม่จัดเก็บไว้ การเพิ่มค่า available_qty ในแคชทำให้เกิดเส้นทางซิงโครไนซ์อีกเส้นทางหนึ่ง การคำนวณสต็อกพร้อมจำหน่ายช่วยลดข้อมูลซ้ำซ้อนได้ ควรเปรียบเทียบประสิทธิภาพการอ่านและพฤติกรรมการกระทบยอดตามภาระงานจริง
- ใช้บัญชีรายการที่เพิ่มข้อมูลได้เท่านั้น ห้ามแก้ไขหรือลบ สำหรับสต็อก คะแนน และยอดคงเหลือ ตัวเลขใด ๆ ที่ลูกค้าอาจโต้แย้งได้ต้องสร้างกลับขึ้นมาได้จากบันทึก มิฉะนั้นฝ่ายสนับสนุนจะไม่มีวิธีอธิบายความคลาดเคลื่อน
- ใช้ Go กับชั้น API ภาระงานประกอบด้วยคำขอสั้น ๆ จำนวนมากที่ทำงานพร้อมกันรอบฐานข้อมูล ซึ่งเหมาะกับโมเดลการทำงานพร้อมกันของ Go และไบนารีแบบสแตติกไฟล์เดียวช่วยให้การติดตั้งใช้งานและการย้อนกลับทำได้ง่าย
เป้าหมายการออกแบบสมมติ
ตัวเลขด้านล่างเป็นตัวอย่างสมมติสำหรับการวางแผนขีดความสามารถ ไม่ใช่ผลลัพธ์ที่วัดจากลูกค้า คำแนะนำการกำหนดขนาดที่ผ่านการตรวจสอบ หรือ SLA กำหนดเป้าหมายการยอมรับเฉพาะโครงการหลังจากระบุภาระงาน อุปกรณ์ ข้อมูล ฮาร์ดแวร์ และการพึ่งพาบริการของบุคคลที่สามแล้ว ตรวจสอบเป้าหมายผ่านโครงการนำร่องและการทดสอบโหลดก่อนให้คำมั่นต่อเป้าหมายสำหรับระบบจริง
เป้าหมายด้านขีดความสามารถและประสิทธิภาพ
| เป้าหมาย | ค่าและสมมติฐาน |
|---|---|
| เวลาแฝงในการอ่านแค็ตตาล็อก | p95 ต่ำกว่า 150 ms ที่ API โดยสมมติว่าข้อมูลที่เรียกใช้บ่อยอยู่ใน Redis และฐานข้อมูลอยู่ในเครือข่ายส่วนตัวเดียวกัน |
| การสร้างคำสั่งซื้อ | p95 ต่ำกว่า 400 ms รวมการจองสต็อก บนฐานข้อมูลหลักหนึ่งชุดที่มีการทำดัชนีตารางคำสั่งซื้อด้วย (site_id, status, created_at) |
| โหลดพุ่งช่วงแฟลชเซล | กำหนดขนาดเส้นทางคำสั่งซื้อให้รองรับคำขอระดับหลักพันรายการต่อนาทีต่อ SKU โดยลดค่า Redis แบบอะตอมิกก่อนตัดยอดใน MySQL หากเกินกว่านั้น จะเพิ่มระบบรับคำขอผ่านคิว — เกณฑ์ดังกล่าวยืนยันด้วยการทดสอบโหลดกับปริมาณข้อมูลจริงของคุณ |
| callback การชำระเงิน | ประมวลผลแบบ idempotent ภายในช่วงเวลาที่เกตเวย์ใช้ลองส่งซ้ำ และปฏิเสธ callback ซ้ำด้วยรหัสธุรกรรมเกตเวย์ที่ไม่ซ้ำ |
สิ่งที่รวมอยู่ในการส่งมอบ
- ซอร์สโค้ดมินิโปรแกรม แบ็กเอนด์ Go และระบบผู้ดูแล Vue ในรีโพซิทอรีของคุณ
- สคีมาฐานข้อมูลพร้อม migration เหตุผลในการทำดัชนี และเอกสารประกอบตารางบัญชีรายการ
- เอกสาร API ที่ครอบคลุมการยืนยันตัวตน รหัสข้อผิดพลาด และข้อกำหนด idempotency
- บันทึกการติดตั้งใช้งานสำหรับ Linux, Docker และ Nginx รวมถึงขั้นตอนการสำรองและกู้คืน
- การสนับสนุนการผสานบัญชีการชำระเงินและบัญชีข้อความ ส่วนผลการตรวจสอบจากแพลตฟอร์มยังขึ้นอยู่กับ WeChat หรือ Douyin
วางแผนระบบนี้ให้ธุรกิจของคุณ
โมดูลข้างต้นเป็นจุดเริ่มต้น ไม่ใช่แพ็กเกจตายตัว โดยปกติเราจะกำหนดรุ่นแรกให้ครอบคลุมเวิร์กโฟลว์หลักหนึ่งรายการและเวิร์กโฟลว์ผู้ดูแลหนึ่งรายการ จากนั้นค่อยขยายเมื่อการใช้งานจริงแสดงให้เห็นว่าภาระงานและกรณีขอบอยู่ตรงไหน ส่งรายละเอียดขอบเขตงาน แล้วเราจะเทียบกับสถาปัตยกรรมนี้และแจ้งว่าส่วนใดที่คุณยังไม่จำเป็นต้องใช้

