ใน course Microservices ที่ Skooldio นั้น
มีคำถามเรื่องเกี่ยวกับรูปแบบของการแลกเปลี่ยนข้อมูลระหว่าง service
ว่า CDC (Change Data Capture) และ Outbox pattern มันเป็นอย่างไร
จึงทำการอธิบายพร้อมตัวอย่าง code และเครื่องมือ
ที่ผมมีโอกาสใช้งานในงานมาบ้าง
เลยทำการสรุปและบันทึกแนวทางไว้นิดหน่อย
ในการแลกเปลี่ยนข้อมูลระหว่าง service นั้นมีหลายรูปแบบ เช่น
- การเรียกหรือส่งข้อมูลแบบตรง ๆ จาก service ไปเลย บ่อยครั้งมีรูปแบบเป็น synchronous ต้องระวังเรื่องของ cascade failure ไว้ด้วย
- เป็น Event-based ในรูปแบบของ one-to-one หรือ one-to-many ก็ว่าไป มีรูปแบบเป็น asynchronous ต้องสร้าง code ทั้งสองฝั่งขึ้นมา เพื่อส่งและรับข้อมูล เช่น producer/consumer หรือ publisher/subscriber เป็นต้น
- Share database กันไปเลย หรือ replicate database ออกมา !! แต่ต้องการข้อมูลทั้งหมดนั้นจริง ๆ ไป
หรือทำการ replicate data แต่แบบเลือกได้
นั่นคือ เมื่อเกิดการเปลี่ยนแปลงใน data ที่เราสนใจใน database (Event/Change logs)
จะทำการจับการเปลี่ยนแปลง ทำการ transform ข้อมูลให้อยู๋ในรูปแบบที่ต้องการ
จากนั้นก็ทำการส่ง หรือ บันทึกไว้อีกที่ที่ต้องการใช้งาน
โดยไม่ต้องไปทำในฝั่งของ app/service
และทำงานร่วมกับ Event-based ก็เป็นอีกทางเลือกหนึ่ง
ซึ่งจะเรียกวิธีการนี้ว่า Change Data Capture (CDC)
โดยเครื่องมือที่ใช้งานเช่น Debezium
มีโครงสร้างการทำงานดังรูป
การทำงานนั้น Debezium จะทำการอ่าน event หรือการเปลี่ยนแปลงใน database แต่ละชนิด
เช่น
- MySQL จะทำการอ่านจาก binlog
- Postgresql จะทำการอ่าจาก logical replication stream
ซึ่งจะมี connector ไปยัง database อื่น ๆ ให้อีกเพียบ
จากนั้นเราสามารถ custom สิ่งที่ต้องการได้อีกด้วย
ด้วยการเขียนตัว transformer data ได้อีก หรือดักบาง event หรือบาง table ก็ได้
ยกตัวอย่างการเขียน transformer เพื่อจัดการกับ event การสร้างเท่านั้น จาก Pogresql database
[gist id="f55057509793ba5edce52868d813858f" file="CustomTransformation.java"]จากนั้นก็อยู่ที่ว่าจะทำการ config เพื่อให้ข้อมูลที่เราดักจับนั้นไปไว้ที่ไหน
โดย Debezium นั้นสามารถส่งข้อมูลไปยัง messaging ได้ เช่น Apahe Kafka
เพื่อให้ใครก็ได้มา subscribe เพื่อนำข้อมูลต่าง ๆ เหล่านี้ไปใช้งานต่อไป
แสดงดังรูป
แต่ก็บ่อยครั้งข้อมูลหรือการเปลี่ยนแปลงใน database จะเยอะมาก ๆ
รวมทั้งไม่มั่นใจอีกว่าการเปลี่ยนแปลงเหล่านั้น
จะถูกดักจับ และ ส่งมายัง messaging ได้ครบหรือไม่
ดังนั้นจึงจำเป็นต้องกาวิธีการจัดการ หนึ่งในแนวคิดคือ Outbox pattern
แนวคิดง่าย ๆ คือ เมื่อมีการเปลี่ยนแปลงของ database เกิดขึ้น
ใน app/service จะทำการเขียน code เพื่อบันทึกลง table หนึ่ง ๆ ไว้
จากนั้นเมื่อทำการส่งข้อมูลไปยัง messaging เรียบร้อยแล้ว
ก็จะทำการ update หรือลบข้อมูลนั้น ๆ ใน table ไป
โดย table นี้เราจะเรียกว่า outbox table
ดังนั้นถ้าเรากำหนดไว้ว่า เมื่อส่งข้อมูลเสร็จแล้ว ข้อมูลต้องโดนลบออกไปเสมอ
ถ้าทำงานได้อย่างถูกต้องใน outbox table ต้องไม่มีข้อมูลเหลือ
แสดงการทำงานดังรูป
จากนั้นเราก็ทำการ config ใน Debezium ว่า
ให้สนใจเฉพาะการเปลี่ยนแปลงใน outbox table ก็พอ
ทำให้ง่าย และ สะดวกต่อการใช้งานอีกด้วย
ตัวอย่างของการ config แบบง่าย ๆ
[gist id="f55057509793ba5edce52868d813858f" file="config.json"]เพียงเท่านี้ก็สามารถใช้งาน Debezium + Apache Kafka
สำหรับการแลกเปลี่ยนข้อมูลระหว่างระบบ หรือ service ได้แล้ว !!
สุดท้ายแล้ว วิธีการเหล่านี้มีความซับซ้อนสูงมาก ๆ
แต่ก็มีประโยชน์มากเช่นกัน
ดังนั้นก่อนใช้งานควรต้องรู้และเข้าใจ
ว่าทำไมเราต้องใช้งาน
มีวิธีการอื่น ๆ ไหม
ที่เหมาสมต่อปัญหา และ ทีม
รวมทั้งเรื่องของการ monitoring และ troubleshooting ต่าง ๆ ด้วย
ทุกอย่างล้วนมี tradeoff ทั้งสิ้น
ใช้อย่างมีสติ
นำมาแก้ไขปัญหา ไม่ใช่นำมาใช้เพื่อสร้างปัญหา
Reference Websites