PlusMagi's Blog By Pitt Phunsanit Backend,Database Database Caching & Read Replica Routing: เทคนิคการแยก Read/Write Traffic อัตโนมัติในระดับ Application Framework

Database Caching & Read Replica Routing: เทคนิคการแยก Read/Write Traffic อัตโนมัติในระดับ Application Framework

ในโลกของแอปพลิเคชันสมัยใหม่ ปริมาณการอ่านข้อมูล (Read Traffic) มักจะสูงกว่าการเขียนข้อมูล (Write Traffic) อย่างมาก การพึ่งพาฐานข้อมูลหลัก (Master DB) เพียงแหล่งเดียวจึงเป็นจุดคอขวดที่หลีกเลี่ยงไม่ได้ เมื่อระบบเริ่มประสบปัญหา Latency หรือ Downtime บ่อยครั้ง นั่นคือสัญญาณว่าสถาปัตยกรรมพื้นฐานในการจัดการโหลดข้อมูลจำเป็นต้องได้รับการปรับปรุงอย่างเร่งด่วน

หัวใจของการขยายตัว: Read Replica และ Caching

การแก้ไขปัญหาคอขวดนี้คือการใช้หลักการ Workload Separation โดยอาศัยกลไกสำคัญสองส่วน คือ Database Caching และ Read Replica Routing

1. Database Caching Layer

Caching ทำหน้าที่เป็นด่านหน้า (First Line of Defense) ในการลดภาระของฐานข้อมูลจริง ด้วยการเก็บผลลัพธ์ของการ Query ที่ถูกเรียกใช้บ่อยๆ ไว้ในหน่วยความจำระดับแอปพลิเคชัน เช่น Redis หรือ Memcached เมื่อมีการร้องขอข้อมูล ระบบจะตรวจสอบ Cache ก่อนเสมอ หากพบข้อมูลที่ยังไม่หมดอายุ (Cache Hit) ก็จะส่งผลลัพธ์ให้ผู้ใช้ทันที โดยไม่ต้องแตะต้อง Master DB เลย

2. Read Replicas

Read Replica คือการสร้างสำเนาของฐานข้อมูลหลัก ซึ่งในกรณีของ PostgreSQL เราสามารถใช้ Streaming Replication เพื่อให้ Replica เหล่านี้รับภาระงานอ่านทั้งหมด (SELECT statements) ในขณะที่ Write Operations (INSERT, UPDATE, DELETE) ยังคงเกิดขึ้นบน Master DB เพียงแห่งเดียวเท่านั้น การทำเช่นนี้ช่วยกระจายโหลดได้อย่างมีประสิทธิภาพ

การทำให้เป็นอัตโนมัติในระดับ Application Framework

ความท้าทายที่แท้จริงคือการไม่ให้โค้ดส่วนใดส่วนหนึ่งมาจัดการเรื่องนี้เอง แต่ต้องสร้าง Logic ที่สามารถตรวจสอบได้ว่าคำสั่งปัจจุบันเป็น Read หรือ Write และทำการ Routing ไปยัง Cache, Master DB, หรือ Replica DB ได้อย่างชาญฉลาดโดยอัตโนมัติ นี่คือสิ่งที่ Application Framework ระดับ Senior Architect ต้องทำ

ตัวอย่างการจำลอง Logic การอ่านข้อมูลใน PostgreSQL

ในการออกแบบระบบที่ซับซ้อน เราสามารถใช้ฟังก์ชันหรือ View ใน PostgreSQL เพื่อเป็นตัวกลาง (Proxy) ที่ตรวจสอบเงื่อนไขและตัดสินใจว่าจะดึงข้อมูลจากแหล่งใด โดยเฉพาะเมื่อเราต้องจัดการกับ Metadata หรือสถานะของ Cache ซึ่งมักจะถูกเก็บในรูปแบบ JSONB

SQL

-- สมมติว่ามีตาราง metadata_cache ที่ระบุว่าข้อมูลนี้ควรมาจาก Replica (read_source: 'replica') หรือ Master (read_source: 'master') และมีการทำ Cache Key ไว้ด้วย jsonb::jsonb</code>
SELECT
    t.id,
    t.data_field,
    CASE 
        WHEN t.metadata->>'read_source' = 'cache'
            THEN 'Read from Redis/Cache Layer'
        WHEN t.metadata->>'read_source' = 'replica'
            THEN 'Route to Read Replica Pool'
        ELSE
            'Write/Master DB Operation'
    END AS routing_strategy,
    t.data_field::text || ' (Source: ' || t.metadata->>'read_source' || ')' AS final_result
FROM 
    product_catalog t
WHERE
    t.id = 100;

โค้ดตัวอย่างนี้แสดงให้เห็นว่า Application Layer สามารถใช้ฟังก์ชันของ PostgreSQL (เช่น การ Query JSONB) เพื่อตัดสินใจเส้นทางการเข้าถึงข้อมูลได้อย่างเป็นระบบ ทำให้ Service Layer ไม่ต้องรู้รายละเอียดทางกายภาพของฐานข้อมูล แต่แค่ส่งคำขอไปที่ Proxy/Gateway ที่ถูกออกแบบมาแล้ว

สรุป: รากฐานสู่ความยืดหยุ่นระดับองค์กร

การนำเทคนิค Database Caching และ Read Replica Routing มาใช้ ไม่ใช่แค่การเพิ่มประสิทธิภาพเชิงเทคนิคเท่านั้น แต่คือการสร้างรากฐานที่แข็งแกร่งให้ธุรกิจสามารถขยายตัวได้อย่างไร้ขีดจำกัด (Scalability) การลงทุนในสถาปัตยกรรมแบบนี้จึงเป็นการประกันว่าระบบจะยังคงตอบสนองต่อความต้องการของผู้ใช้งานจำนวนมากได้ตลอดเวลา ทำให้องค์กรมีความทนทานและพร้อมรับมือกับการเติบโตอย่างก้าวกระโดด