เรียกว่าจดไว้กันลืม และกัน หัวข้อจะประมาณนี้
ก่อนจะมารู้จัก 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 หลายตัวที่เก็บได้ อาทิ เช่น
- EventStore- DB เฉพาะ
- MongoDB
- Kafka
- RabbitMQ
- Postgres - RDBMS ที่พ่อทุกสถาบันจริงๆ pgmq
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
- Event Sourcing pattern - Azure Architecture Center | Microsoft Docs
- Event sourcing (microservices.io)
- Event Sourcing (martinfowler.com)
- Two-Phase Commit (martinfowler.com)
- Two Phase Commit (https://p-org.github.io/P/tutorial/twophasecommit/)
Discover more from naiwaen@DebuggingSoft
Subscribe to get the latest posts sent to your email.