- Published on
การแยกข้อมูลระหว่างโมดูล (Data Isolation)
- Authors
- Name
- Somprasong Damyos
- @somprasongd
การแยกข้อมูลระหว่างโมดูล (Data Isolation)
ในสถาปัตยกรรมแบบ Modular Monolith ที่ได้รับความนิยมเพิ่มขึ้นเรื่อยๆ ซึ่งเป็นการผสมผสานข้อดีของ Monolith และ Microservices เข้าไว้ด้วยกัน แนวทางนี้ช่วยแก้ปัญหาเรื่องการผูกแน่นของส่วนประกอบต่างๆ (tight coupling) ที่มักพบในสถาปัตยกรรมแบบ Monolith ดั้งเดิม โดยบังคับใช้แนวทางปฏิบัติทางสถาปัตยกรรมที่ดีขึ้นด้วยการกำหนดขอบเขตโมดูลและรูปแบบการสื่อสารที่ชัดเจน
อย่างไรก็ตาม สิ่งหนึ่งที่มองข้ามไม่ได้คือ การแยกข้อมูลระหว่างโมดูล (Data Isolation) ซึ่งช่วยให้โมดูลมีความเป็นอิสระและมีการผูกแน่นที่หลวม (loosely coupled) สถาปัตยกรรมแบบ Modular Monolith มีกฎที่เข้มงวดสำหรับการรักษาความสมบูรณ์ของข้อมูล:
- แต่ละโมดูลสามารถเข้าถึงได้เฉพาะตารางของตนเองเท่านั้น
- ไม่มีการแชร์ตารางหรืออ็อบเจกต์ระหว่างโมดูล
- การ Join สามารถทำได้เฉพาะตารางภายในโมดูลเดียวกันเท่านั้น
ประโยชน์ของการออกแบบนี้คือการส่งเสริมความเป็นโมดูลาร์และการผูกแน่นที่หลวม ทำให้ง่ายต่อการเปลี่ยนแปลงระบบและลดผลข้างเคียงที่ไม่พึงประสงค์
ระดับการแยกข้อมูล (Data Isolation Levels)
นี่คือสี่แนวทางในการแยกข้อมูลสำหรับ Modular Monoliths:
Level 1 - Separate Table (ไม่แนะนำ)
เป็นวิธีการที่ง่ายที่สุดคือไม่มีการแยกข้อมูลในระดับฐานข้อมูล ทุกตารางของทุกโมดูลจะอยู่ในฐานข้อมูลเดียวกัน ทำให้ยากที่จะระบุว่าตารางใดเป็นของโมดูลใด แม้จะใช้ได้กับแอปพลิเคชันขนาดเล็ก แต่ยิ่งมีตารางมากเท่าไหร่ก็ยิ่งรักษาสภาพการแยกข้อมูลได้ยากขึ้นเท่านั้น
┌─────────────────────────────────┐
│ Single Database │
│ ┌─────────────────────────────┐ │
│ │ Module A │ │
│ │ Table A1 Table A2 ... │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ Module B │ │
│ │ Table B1 Table B2 ... │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ Module C │ │
│ │ Table C1 Table C2 ... │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────┘
Level 2 - Separate Schema (Logical Isolation)
วิธีนี้เป็นการจัดกลุ่มตารางที่เกี่ยวข้องเข้าด้วยกันในฐานข้อมูลโดยใช้ Database Schemas แต่ละโมดูลมี Schema เฉพาะของตนเองที่มีตารางของโมดูลนั้นๆ ทำให้ง่ายต่อการจำแนกว่าตารางใดเป็นของโมดูลใด คุณสามารถกำหนดกฎเพื่อป้องกันการสืบค้นข้อมูลจากโมดูลอื่นได้ เช่น การใช้ Architecture Tests เป็นจุดเริ่มต้นที่ดีในการสร้าง Modular Monolith
┌─────────────────────────────────┐
│ Single Database │
│ ┌─────────────────────────────┐ │
│ │ Schema A │ │
│ │ Table A1 Table A2 ... │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ Schema B │ │
│ │ Table B1 Table B2 ... │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ Schema C │ │
│ │ Table C1 Table C2 ... │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────┘
Level 3 - Separate Database (Physical Isolation)
ระดับถัดไปคือการย้ายข้อมูลของแต่ละโมดูลไปยัง ฐานข้อมูลที่แยกจากกัน วิธีนี้มีการจำกัดมากกว่าการแยกข้อมูลด้วย Schema และเป็นทางเลือกที่ดีหากคุณต้องการกฎการแยกข้อมูลที่เข้มงวดระหว่างโมดูล แม้จะมีข้อเสียคือความซับซ้อนในการจัดการโครงสร้างพื้นฐานสำหรับฐานข้อมูลหลายตัว แต่ก็เป็นขั้นตอนที่ยอดเยี่ยมในการแยกโมดูลออกไปเป็น Microservices ในอนาคต
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Database A │ │ Database B │ │ Database C │
│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │
│ │ Module A │ │ │ │ Module B │ │ │ │ Module C │ │
│ │ Table A1 │ │ │ │ Table B1 │ │ │ │ Table C1 │ │
│ │ Table A2 │ │ │ │ Table B2 │ │ │ │ Table C2 │ │
│ │ ... │ │ │ │ ... │ │ │ │ ... │ │
│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Level 4 - Different Persistence (Polyglot Persistence)
วิธีนี้ไปไกลกว่านั้นโดยการใช้ ฐานข้อมูลประเภทที่แตกต่างกัน สำหรับแต่ละโมดูล ตัวอย่างเช่น โมดูลหนึ่งอาจใช้ฐานข้อมูลเชิงสัมพันธ์ (SQL) ในขณะที่อีกโมดูลหนึ่งอาจใช้ฐานข้อมูลเอกสาร (Document Database) หรือฐานข้อมูลกราฟ (Graph Database) เพื่อแก้ปัญหาเฉพาะทาง การเลือกใช้ Persistence Model ที่แตกต่างกันนี้ต้องมีการวางแผนอย่างรอบคอบ แต่สามารถเป็น Trade-off ที่คุ้มค่าสำหรับ Use Case ของคุณ
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Database A │ │ Database B │ │ Database C │
│ (Relational DB) │ │ (Document DB) │ │ (Graph DB) │
│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │
│ │ Module A │ │ │ │ Module B │ │ │ │ Module C │ │
│ │ Table A1 │ │ │ │ Doc B1 │ │ │ │ Node C1 │ │
│ │ Table A2 │ │ │ │ Doc B2 │ │ │ │ Edge C1 │ │
│ │ ... │ │ │ │ ... │ │ │ │ ... │ │
│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
สรุป
Modular Monoliths เป็นตัวเลือกที่ยอดเยี่ยมหากคุณยังไม่ต้องการ Microservices ทันที คุณสามารถพัฒนาแอปพลิเคชันของคุณเป็น Monolith ที่มีขอบเขตที่ชัดเจนภายในระบบ และยังคงมีความยืดหยุ่นในการแยกโมดูลและย้ายไปยัง Microservices ได้ในอนาคต โดยที่ยังคงความเร็วในการพัฒนาที่เร็วกว่า Modular Monolith กำหนดให้โมดูลต่างๆ ปฏิบัติตามกฎบางอย่าง เช่น การเข้าถึงเฉพาะตารางของตนเอง ไม่แชร์ตารางกับโมดูลอื่น และไม่สืบค้นตารางของโมดูลอื่นโดยตรง กฎเหล่านี้ช่วยบังคับใช้การแยกข้อมูลระหว่างโมดูล
โดยทั่วไปแล้ว การเริ่มต้นด้วยการแยกข้อมูลแบบ Logical Isolation โดยใช้ Schemas เป็นวิธีที่ง่ายต่อการนำไปใช้และช่วยให้เข้าใจขอบเขตของระบบได้ดีขึ้น และคุณสามารถพิจารณาใช้ฐานข้อมูลแยกกัน (Separate Database) ในภายหลังได้ตามความต้องการของระบบที่เปลี่ยนแปลงไป