Event Sourcing Pattern

เรียกว่าจดไว้กันลืม และกัน หัวข้อจะประมาณนี้

ก่อนจะมารู้จัก Event Sourcing Pattern แบบเดิมทำอย่างไร

  • OLTP - ทำข้อมูลเล็กๆ ถี่ๆ เป็น Transactional ตัว Database เน้น Normalize
  • OLAP - ออกแบบมาเพิ่ม Analytics จับข้อมูลเยอะ ไม่เหมือน OLTP จะไปทำ De-Normalize แทน

เห็นไหมครับว่า ทั้ง OLTP และ OLTP มี Concept ที่ต่างกันไป

Event Sourcing อยู่ตรงไหน

  • จุดสมดุลระหว่าง OLTP และ OLAP สิ่งที่มันพยายามจะทำ
  • เอา Event (อาจจะมองว่าเป็น Log) ณ ช่วงเวลานึงมาประมาณผล เพื่อให้ทราบถึง State ปัจจุบัน ที่เกิดจาก Action ตัวอย่างที่สาย Dev พบกัน Git Commit หรือมอง General Case สุดๆ ยอดเงินของบัญชีใน App Mobile Banking จาก 2 ตัวอย่างนี้ Event มัน คือ อะไร
    - Git - ตัว Commit Action - Add / Remove Line หรือ Add / Remove File
    - ยอดเงินของบัญชีใน App Mobile Banking - Event มัน ได้แก่ Deposit / Withdraw / Transfer หรือ Balance Forward (ยอดยกมา ถ้าเคสยังใช่เล่ม สมุดหมดเป็นเล่มใหม่ จะได้ยอดนี้มาแปะตั้งต้น)
  • ตอนนี้เราเข้าใจแล้วว่า Event มันเป็นสรุปผลของการเปลี่ยน State จาก A -> B โดยมี Command ทำให้เกิดการเปลี่ยนแปลง ยกตัวอย่าง เช่น การ Deposit
    - State เดิมยอดเงิน 50 บาท
    - Command มี payload Deposit 50 บาท
    - เกิด Event Deposit ขึ้น
    - State เปลี่ยนและจาก 50 -> 100 บาท
    - หรือ เราจะมองเป็น Function จะได้ประมาณนี้

Fcommand(state, payload) => [New State / events];

  • Event vs State ขยายความนิดนึงเผื่อใครงงๆกัน
    - State - Snapshot ปัจจุบัน Data นั้นๆมีสถานะอะไร
    - Event - History ที่เป็นเหตุ และผลที่ทำให้ State เปลี่ยนแปลง โดยที่ Event หลายๆอันมาต่อกันจะเรียกว่า Event Logs
    - ตัวอย่าง จากภาพซ้าย เราจะเห็นว่าเงินของ A 15 / B 10 จากนั้น A 10 / B 15 ตรงนี้ คือ State แล้วการ Transfer เงิน 5 บาทจาก A > B ตรงนี้ คือ Event Logs ที่ประกอบไปด้วย Event ต่างๆนั้นเอง

Event Sourcing ensures that all changes to application state are stored as a sequence of events.

Ref: Event Sourcing (martinfowler.com)

เอาอะไรมาเก็บ Event Store

มี Open Source หลายตัวที่เก็บได้ อาทิ เช่น

Update พี่ปุ๋ย Somkiat.cc มีมาเสริมนะ ถ้าไม่ซับซ้อนมากสามารถใช้ File System ได้นะ

Use-Case Example

- Blockchain
  • Blockchain ตัว Fcommand(state, payload) มัน คือ Smart Contract ครับ เหมือนจะมีมาตรฐานด้วยนะ ERC-20
- Microservice เอาแนวคิดของ Event Sourcing + CQRS
  • Event Sourcing - เอามาพัก Event ก่อนให้ Microservice แต่ละอันที่เกี่ยวข้องกัน Publish / Subscribe เอาไปทำงานต่อไป
  • Command Query Responsibility Segregation (CQRS) - แยกส่วนการทำงาน เช่น Read / Write ออกจากกัน
  • ตัวอย่าง เช่น
    - Order Service Publish Event ลง Event Store แล้วให้ Customer Service มัน Subscribe มันไปทำงานต่อ
    - หรือ Database Sync ของ Microservice โดยใช้ตัว Event Sourcing มาช่วย แต่ Consistency จะได้เป็นแบบ Eventual Consistency (Keyword นี้คุ้นๆไหม ผมรู้จักจาก Azure Cosmos DB พอมาดูเรื่องนี้แล้ว อ๋ออออ)

เอา Event Sourcing ต้องดูอะไร เพิ่มไหม ?

  • มีหลาย Keyword เลย อย่างในตัว Microservice จะมี CQRS ขึ้นมาและ
  • ต้องดู write consistency / Optimistic concurrency control เพื่อให้ Result เวลาที่ Call API มัน Idempotent
  • หรือ แม้แต่กระทั่งตัว Event Store ต้องทำ High Availability / Fault Tolerance

อีก Blog ที่แนะนำ Lightweight implementation of Event Sourcing using PostgreSQL as an event store 🚀🕗🔙🕘 - DEV Community

มองการทำงานแบบ Event Performance จะแย่ไหมนะ

  • ถ้าเข้าใจ Event Logs ที่เก็บความสัมพันธ์ของ Event เราจะรู้ความเป็นเหตุ และผลของมัน (causality) ยกตัวอย่าง เช่น เราจะถอนเงิน(Withdraw) ได้ ต้องมีการฝากเงิน(Deposit) เข้าไปก่อน
  • แล้วทุกๆเรื่องมันจะเป็นต้องเรียงด้วยกันไหม ?
    ไม่จำเป็น แต่เราต้องรู้จุดที่เป็น Partition Key ตัวแบ่งข้อมูลเป็นกลุ่มได้ เพื่อแบ่งกลุ่มของข้อมูล และเพิ่มตัว Process เช่น เราตรวจสอบว่าถอนเงินได้ไหม จำเป็นต้องตรวจบัญชีของคนอื่นไหม ก็ไม่ แสดงว่าเอา UserId แบ่ง Partition และแยกกันประมวลผลได้นะ
    และก็ตัว Correlation Id จะได้ไล่สายได้

Sample ที่เคยลอง Spilt Monolith + POC นิดหน่อย

ลองมาดูภาพด้วย ว่าถ้าเราจะ Spilt Monolith ที่ดูออกมาส่วนย่อยๆ ได้อะไรบ้าง จะตามนี้เลย ผมจะเน้นเส้นสีแดง มองว่าทำระบบบันทึกข้อมูลการลงทุน

  • Flow ทำ Transaction
    - Client ส่ง Order มาที่ Order Service ซึ่ง ลงDB มันเองก็ ส่ง Event แล้วไปส่วน Billing Service
    - Billing Service ไปตัดเงิน และก็บันทึก //จริงๆ มันต้องมาทำ Flow ส่วน Alternative ด้วยนะ
    - ต่อมาถ้าไม่ติดอะไร ก็มา Portfolio Position Service สรุปข้อมูลข้อมูลการลงทุน หรือ ค่าสำคัญทางการเงินต่างๆ อันนี้ผมแยก DB Write / Read ออกจากกัน ตอน Process มีข้อมูลจาก Master Data จาก Service ต่างๆ Customer / Security / Market Data
    - ถ้าทำเสร็จก็ส่ง Event เพื่อให้ Noti ออกไปครับ รวม Alternative Flow ด้วย เงินไม่พอ บราๆ
  • อีกมุมจะส่วนของ Dashboard / Report มันทำคล้าย BFF เอาข้อมูลจาก Service ต่างๆมารวมกัน และส่งไปให้ Client ครับ

แล้วพวก Transaction หละ ?

เดิม Relational Database มันทำให้แล้ว พอเรามาแยกระบบพวกคุณสมบัติ ACID จะหายไปด้วย

- Atomicity - transaction is treated as a single unit ทำสำเร็จจบ ถ้าไม่ ตี Fail
- Consistency - ใน Single Unit มันต้องสอดคล้อง โอนจาก A -> B เงินหัก A ไปเพิ่ม B เก็บตาม data type / Schema
- Isolation - concurrent transactions โอนเงินพร้อมกัน มันไม่ต้องเข้ามั่ว / หลบ race condition
- Durability - อะไรที่ Commit ไปแล้วสถานะคงเดิม เช่น ปิด DB ไปเปิดมาก็เหมือนเดิม

แต่ยอดนิยมที่ต้องเจอ Rollback หรือ Retry Flow ถ้างานไม่สำเร็จ สำหรับงาน  distributed system มีที่นิยมหลายแบบ ถ้ายุคเก่าหน่อย

  • Two-Phase Commit - ผมเองนึกถึงพวก network งานออกแนว Synchronous ส่งไปแล้ว ต้องรอปลายทาง Acknowledge กลับมาว่า Success / Fail แล้วจึงค่อยมาชิ้นงานถัดไป

ถัดมาเป็นตัว

  • Outbox Pattern - pattern ทำ temporary storage (outbox table) จดว่าเราจะส่งอะไรออกไป จาก A > B ถ้าส่งเสร็จอาจจะกำหนดให้ลบทิ้ง ถ้ามันทำครบ ต้นทางต้องไม่มี Record ค้าง
  • SAGA Pattern - pattern มีหลาย action เกิดขึ้นต่อเนื่องกัน และมีความสัมพันธ์กัน เช่น ซื้อตั๋ว และ จองโรงแรม และ จองเครื่องบิน ถ้าสำเร็จหมด ถือว่าจองทริปสำเร็จ ถ้าไม่ต้อง Rollback ส่วนตัวผมนึกถึงภาพ Flow แบบ BPMN ที่มี่ Flow Happy Flow / Alternative Flow (Compensation) หรือจะ Retry ก็ได้ ถ้าคุยกับ Business แล้วว่าทำได้

อื่นๆ ที่ควรสนใจ

พอเดิม 1 ระบบ ตอนนี้แยกเป็นหลายระบบย่อยๆ แสดงว่าเราต้องรู้ความสัมพันธ์ของแต่ละ Action หรือ Request มันจะมีศาสตร์ด้วยนี้แล้วนะ observability (Log / Trace / Metric) สำคัญจะเป็น Log / Trace มันจะต้องมี Tracing / Correlation ใส่ไปด้วย มันจะได้ Link กันได้ครับ ถ้าพวก dotnet observability แบบพื้นฐานดูได้จากอันนี้เลยครับ GitHub - pingkunga/dotnet23observability ครับ //เดี๋ยวมีเวลาจะมาทำแบบมีหลาย Service ครับ

Resource


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts sent to your email.