- Saga Pattern คืออะไร
- ตัวอย่างระบบสั่งซื้อสินค้า
- สองรูปแบบหลัก
- ตัวอย่าง Pseudocode ของ Orchestration
- แนวทางสำหรับ Production
- Workshop ที่แนะนำ
- สรุป
#Saga Pattern คืออะไร
Saga Pattern เป็นรูปแบบการออกแบบสำหรับจัดการธุรกรรมทางธุรกิจที่ครอบคลุมหลาย Microservices โดยแบ่งธุรกรรมใหญ่เป็น Local Transactions แต่ละบริการบันทึกข้อมูลในฐานข้อมูลของตนเอง และประสานขั้นตอนถัดไปผ่านเหตุการณ์ (Events) หรือคำสั่ง (Commands) หากขั้นตอนใดล้มเหลว ระบบจะเรียก Compensating Transactions เพื่อชดเชยผลของขั้นตอนที่ทำสำเร็จไปแล้ว แทนการใช้ Rollback แบบฐานข้อมูลเดียว
การชดเชยไม่จำเป็นต้องคืนสภาพได้อย่างสมบูรณ์เสมอไป เช่น การส่งอีเมลไปแล้วไม่สามารถยกเลิกการรับรู้ของผู้รับได้
#ตัวอย่างระบบสั่งซื้อสินค้า
ประกอบด้วย Order Service, Inventory Service และ Payment Service ซึ่งต่างมีฐานข้อมูลของตนเอง
#เส้นทางสำเร็จ
- Order Service สร้างคำสั่งซื้อสถานะ
PENDING - Inventory Service จองสินค้า
- Payment Service ตัดชำระเงิน
- Order Service เปลี่ยนสถานะเป็น
CONFIRMED
#เส้นทางล้มเหลว
หากการชำระเงินล้มเหลวหลังจากจองสินค้าแล้ว ระบบต้องยกเลิกการจองสินค้า และเปลี่ยนสถานะคำสั่งซื้อเป็น CANCELLED โดยบันทึกเหตุผลไว้
sequenceDiagram
participant O as Order Service
participant I as Inventory Service
participant P as Payment Service
O->>O: Create order (PENDING)
O->>I: Reserve inventory
I-->>O: Reserved
O->>P: Charge payment
alt Payment succeeded
P-->>O: Paid
O->>O: Confirm order
else Payment failed
P-->>O: Failed
O->>I: Release inventory (compensation)
I-->>O: Released
O->>O: Cancel order
end
#สองรูปแบบหลัก
| หัวข้อ | Choreography | Orchestration |
|---|---|---|
| วิธีประสานงาน | บริการตอบสนองต่อ Events | ตัวกลาง Saga Orchestrator สั่งงาน |
| การเชื่อมโยง | Event-driven กระจาย | ขั้นตอนธุรกิจอยู่ในตัวประสาน |
| เหมาะกับ | กระบวนการสั้นและไม่ซับซ้อน | กระบวนการหลายขั้นและมีเงื่อนไข |
| ความท้าทาย | ติดตามลำดับและ dependencies ยาก | ต้องดูแล orchestrator และสถานะ |
#Choreography
OrderCreated -> InventoryReserved -> PaymentSucceeded -> OrderConfirmed
|
+-> PaymentFailed -> InventoryReleased -> OrderCancelled
#Orchestration
Order Service -> Saga Orchestrator
|-> Reserve Inventory
|-> Charge Payment
|-> Confirm Order
+-> On failure: Release Inventory -> Cancel Order
#ตัวอย่าง Pseudocode ของ Orchestration
public void processOrder(String orderId) {
boolean inventoryReserved = false;
try {
inventoryService.reserve(orderId); // idempotent
inventoryReserved = true;
paymentService.charge(orderId); // idempotent
orderService.confirm(orderId);
} catch (Exception error) {
if (inventoryReserved) {
inventoryService.release(orderId); // retry safely
}
orderService.cancel(orderId);
}
}
หมายเหตุ: ตัวอย่างนี้แสดงแนวคิดเท่านั้น ไม่ใช่ production-ready implementation การเรียกบริการผ่านเครือข่ายอาจ timeout หลังจากฝั่งปลายทางทำสำเร็จแล้ว จึงต้องตรวจสอบผลลัพธ์ที่ไม่แน่นอนก่อนชดเชย และต้องบันทึกสถานะ Saga แบบ durable
#แนวทางสำหรับ Production
- Idempotency: ทุกคำสั่งและ Compensation ต้องรองรับการส่งซ้ำโดยไม่เกิดผลซ้ำ เช่น ใช้
orderIdหรือoperationIdเป็น idempotency key - Transactional Outbox: บันทึกข้อมูลธุรกิจและ Outbox Event ใน Local Transaction เดียวกัน เพื่อหลีกเลี่ยงปัญหาบันทึก DB สำเร็จแต่ส่ง Event ไม่สำเร็จ
- Inbox / Deduplication: ผู้รับตรวจสอบ Event ID เพื่อป้องกันการประมวลผลซ้ำ
- Retry และ Backoff: ใช้ retry แบบจำกัดจำนวน พร้อม exponential backoff และ dead-letter queue สำหรับงานที่ต้องตรวจสอบ
- Durable Saga State: บันทึกสถานะ ขั้นตอนที่เสร็จ และขั้นตอนที่ต้องชดเชย เพื่อกลับมาทำงานได้หลังระบบล่ม
- Observability: ติดตาม
sagaId,orderId, trace ID, ระยะเวลา และจำนวน compensation - Business Invariants: กำหนดข้อจำกัด เช่น ห้ามยืนยันคำสั่งซื้อหากยังไม่ได้รับผลยืนยันการชำระเงิน
- Isolation: Saga ไม่ได้ให้ ACID isolation ระหว่างบริการ ต้องออกแบบรับ concurrent updates และความไม่สอดคล้องชั่วคราว
#Workshop ที่แนะนำ
สร้างระบบ order-service, inventory-service, payment-service, saga-orchestrator พร้อม PostgreSQL แยกฐานข้อมูลตามบริการ และใช้ RabbitMQ หรือ Kafka สำหรับการสื่อสารแบบ asynchronous ทดสอบกรณีชำระเงินสำเร็จ ล้มเหลว timeout, duplicate event, orchestrator restart และ compensation ล้มเหลว
เกณฑ์ยอมรับ: คำสั่งซื้อไม่ถูก CONFIRMED หากยังชำระเงินไม่สำเร็จ; สินค้าถูกคืนเมื่อชำระเงินล้มเหลว; ข้อความซ้ำไม่ทำให้ตัดเงินหรือคืนสินค้าซ้ำ; ระบบกู้คืนงานที่ค้างได้หลังรีสตาร์ต
#สรุป
Saga Pattern ช่วยให้ Microservices ดำเนินกระบวนการธุรกิจข้ามฐานข้อมูลได้โดยไม่ต้องพึ่ง Distributed ACID Transaction แต่ต้องยอมรับ Eventual Consistency และออกแบบ Compensation, Idempotency, Durable State และ Monitoring ให้รัดกุม เลือก Choreography สำหรับงานที่ไม่ซับซ้อน และ Orchestration เมื่อต้องควบคุมลำดับงานอย่างชัดเจน