การบริการคลาวด์ในปัจจุบัน มีบริการหนึ่งคือ SaaS หรือ Software as a Service ซึ่งผู้ให้บริการ SaaS รายใหญ่ๆ ในการบริการให้กับลูกค้า หรือผู้เช่า โดยส่วนมากและให้ความสำตัญไปที่การใช้สถาปัตยกรรม Multi-tenancy การบริการนี้สามารถใช้ทรัพยากร(resources)ร่วมกัน ที่ยังคงมีการแยกความแตกต่างระหว่างผู้เช่า(tenant)แต่ละรายไว้
ตัวอย่างง่ายๆ: ลองนึกถึงอาคารสำนักงาน — ตึกเดียว แต่มีหลายบริษัทเช่าพื้นที่อยู่ แต่ละบริษัทมีห้องและกุญแจของตัวเอง ใช้ลิฟต์และล็อบบี้ร่วมกัน แต่ไม่สามารถเข้าห้องของบริษัทใดบริษัทหนึ่งที่ไม่ใช่เจ้าของได้
การแยกระหว่างผู้ใช้
การออกแบบ multi-tenancy application จะต้องมีการแยกระหว่าง tenant เป็นสิ่งที่ขาดไม่ได้
Application แบบ multi-tenancy จะเป็น single instant (เป็น 1 instant application ที่ทำงานได้หลายๆ tenant) และส่งต่อไปยังฐานข้อมูล ระบบฐานข้อมูลจะแยกตามแต่ละ tenant ในการเข้าถึงการใช้งาน วิธีการแยกตามฐานข้อมูลสามารถทำได้หลายรูปแบบ เช่น
1. แยกฐานข้อมูลเฉพาะ (Database per Tenant)
สร้างฐานข้อมูลแยกสำหรับแต่ละ tenant
Tenant A → Database A
Tenant B → Database B
Tenant C → Database C
| ข้อดี | ข้อเสีย |
|---|---|
| แยกข้อมูลได้สมบูรณ์ที่สุด | ใช้ resources มากที่สุด |
| ปรับแต่งตาม tenant ได้ง่าย | ต้นทุนสูงขึ้นตามจำนวน tenant |
| Backup/Restore แยกรายได้ | การ scale จำนวนมาก ต้องเพิ่ม resource |
เหมาะกับ: ระบบที่มี tenant จำนวนไม่มาก แต่ต้องการความเป็นส่วนตัวและความปลอดภัยสูง เช่น ระบบการเงิน หรือสุขภาพ
2. แยกด้วย Schema (Shared Database, Separate Schema)
Database เดียว
├── Schema: tenant_a
│ └── table: patients, appointments, ...
├── Schema: tenant_b
│ └── table: patients, appointments, ...
└── Schema: tenant_c
└── table: patients, appointments, ...
| ข้อดี | ข้อเสีย |
|---|---|
| ประหยัด resources กว่าแบบแรก | การย้าย tenant ซับซ้อนกว่า |
| ยังคงมีการแยกที่ชัดเจน | ต้องจัดการ schema migration ทุก tenant |
| ง่ายต่อการ query ข้ามบาง use case |
เหมาะกับ: ระบบที่ต้องการสมดุลระหว่างการแยกข้อมูลและการประหยัดต้นทุน
3. แยกด้วยคอลัมน์ / Sharding (Shared Database, Shared Schema)
ใช้ฐานข้อมูลและตารางเดียวกัน แต่มีคอลัมน์ tenant_id เพื่อระบุว่าข้อมูลแถวนี้เป็นของ tenant ใด
ตาราง patients (ร่วมกัน)
┌────────────┬─────────────┬────────────┐
│ tenant_id │ patient_id │ name │
├────────────┼─────────────┼────────────┤
│ tenant_a │ 001 │ สมชาย │
│ tenant_b │ 001 │ John │
│ tenant_a │ 002 │ สมหญิง │
└────────────┴─────────────┴────────────┘
| ข้อดี | ข้อเสีย |
|---|---|
| ประหยัด resources มากที่สุด | ความเสี่ยง data leak สูงสุด |
| ง่ายต่อการพัฒนาและ deploy | ประสิทธิภาพอาจลดลงเมื่อข้อมูลมาก |
| Scale จำนวน tenant ได้ง่าย | ต้องระวัง query ทุกครั้ง |
Database Sharding เป็นอีกรูปแบบที่ขยายจากแนวคิดนี้ โดยแบ่งข้อมูลตามช่วง tenant_id ออกเป็นหลาย shard เพื่อกระจาย load
เหมาะกับ: SaaS ขนาดใหญ่ที่มี tenant จำนวนมาก และ tenant แต่ละรายมีข้อมูลไม่มาก
สถาปัตยกรรม
โครงสร้่างของ multi-tenancy architecture ลักษณะการออกแแบแสดงตามรูปข้างล่าง เป็นดังนี้
- Application - โปรแกรมใช้งาน ทำหน้าที่ติดต่อกับผู้ใช้ตามแต่ละ tenant และเชื่อมไปยังส่วนหลัง middle ware
การปรับหรือ customize ของแต่ละ tenant จะทำที่ชั้น application นี้ และโปรแกรมออกแบบมาให้ทำงานลักษณะ multi-concurrency - Middleware - ทำหน้าที่เชื่อมกับ application และ mapping เข้ากับ database
- Database - ฐานข้อมูลของผู้ใช้งานตามแต่ละ tenant
- Virtual machine/container - สำหรับทำหน้าที่ให้โปรแกรมทำงานโดยใช้ resources จากส่วนกลาง ซึ่งสามารถเป็นได้ทั้ง virtual machine หรือ container(เข่น docker หรือ podman) ในหนึ่ง virtual machine หรือ container สามารถทำงานได้หลายๆ tenant ขึ้นอยู่กับ resources ที่ได้กำหนดไว้
- Common-resources(hardware, networking, etc) - resources ส่วนกลางที่ผู้ให้บริการ(service provider)จัดหาให้ และส่วน networking เชื่อมต่อไปยังปลายทางที่ต่างๆ
นอกจากนี้การออกแบบ multi-tenancy ยังสามารถสร้าง database กลางเพื่อใช้กับ tenant ต่างๆ ซึ่งเป็นข้อมูลที่ต้องการแบ่งปันการใช้ระหว่าง tenant(เป็นข้อมูลเปิด) เช่น ICD-9(Procedure), ICD-10, ICD-11

ประโยชน์
การใช้ multi-tenancy ได้ประโยชน์ดังนี้
- การใช้ resources ได้มีประสิทธิภาพ
- อัปเดตและบำรุงรักษาง่าย แก้ไข bug หรือเพิ่ม feature ครั้งเดียว ทุก tenant ได้รับการอัปเดตพร้อมกัน ไม่ต้อง deploy แยกรายลูกค้า
- Scale ได้ง่าย เพิ่ม tenant ใหม่ได้โดยไม่ต้องตั้งค่า infrastructure ใหม่ทั้งหมด เพียงเพิ่ม entry ใน routing และสร้าง database/schema ใหม่
- การจัดการทำได้จากศูนย์กลาง ผู้ดูแลระบบสามารถ monitor, audit, และจัดการ tenant ทั้งหมดได้จากที่เดียว
Tenant Routing
ระบบโปรแกรมคลินิก kksEHR ใช้ Database Tenant Provider ในการเลือก Data Source ให้ถูกต้องตาม tenant ที่ส่ง request เข้ามา โดยตัวอย่าง log จากระบบจริงแสดงให้เห็นว่าในเวลาเดียวกัน (10:47:58.388) มีสอง thread ทำงานพร้อมกัน และแต่ละ thread ถูก route ไปยัง datasource ของ tenant ที่ถูกต้องอย่างอิสระจากกัน:
...10:47:58.388 [http-thread-pool::http-listener-2(1)] DatabaseTenantProvider use dataSource name: tenant2DS
...10:47:58.388 [http-thread-pool::http-listener-2(3)] DatabaseTenantProvider use dataSource name: tenant1DS
สังเกตได้ว่า:
Thread (1) → ถูก route ไปยัง tenant2DS (ฐานข้อมูลของ tenant 2)
Thread (3) → ถูก route ไปยัง tenant1DS (ฐานข้อมูลของ tenant 1)
ทั้งสอง thread ทำงานที่ เวลาเดียวกันทุกมิลลิวินาที แต่ข้อมูลไม่ปะปนกัน
นี่คือหลักฐานว่าระบบสามารถรองรับการใช้งานแบบ concurrent multi-tenant ได้อย่างถูกต้องและปลอดภัย
Tenant Routing คือหัวใจของ Multi-tenancy — มันทำให้ระบบเดียวรองรับผู้เช่าได้หลายราย โดยที่ข้อมูลของแต่ละรายยังคงแยกกันอย่างชัดเจนในทุกสถานการณ์การใช้งาน
สรุป
ในบทความนี้กล่าวถึงระบบโครงสร้างของ multi-tenancy และประโยชน์จากการใช้ โดยโปรแกรมคลินิก kksEHR เป็น Online Cloud-based Application ใช้สถาปัตยกรรมนี้ด้วยเทคโนโลยี Jakarta EE
Data Compliance: ในบางธุรกิจ เช่น การแพทย์หรือการเงิน กฎหมาย PDPA/HIPAA อาจกำหนดให้ต้องแยก database ตามแต่ละผู้เช่า