ข้ามไปยังเนื้อหา

การดำเนินงานและการขยายระบบ

การเขียน SQL ให้ถูกต้องเป็นเพียงครึ่งหนึ่งของงาน อีกครึ่งหนึ่งคือการทำให้ PostgreSQL server ตัวเดียวยังทำงานได้ดีเมื่อต้องให้บริการผู้ใช้หลายพันคนในทันที รอดจากดิสก์ที่พังลง รองรับ table ที่มีข้อมูลหลายพันล้าน row และปฏิเสธทุกคนที่ไม่ควรเข้ามา กลุ่มของเรื่องเหล่านี้คือสิ่งที่คนเรียกว่า operations — งานของการรันฐานข้อมูลในโปรดักชันแทนที่จะรันบนแล็ปท็อปของคุณ

โมดูลนี้ก้าวออกจาก syntax ของ query ไปมองรูปร่างของการ deploy จริง ไม่มีอะไรในนี้เปลี่ยน SQL ที่คุณรู้อยู่แล้ว แต่เป็นการล้อม server ตัวนั้นด้วยชิ้นส่วนที่ทำให้เชื่อถือได้เมื่อต้องขยายขนาด

แทบทุกหัวข้อด้าน operations ใน PostgreSQL จัดอยู่ภายใต้หนึ่งในสี่หัวข้อนี้ แต่ละหัวข้อตอบคำถามแบบ “จะเกิดอะไรขึ้นเมื่อ…” ที่แตกต่างกัน

เรื่องสำคัญตอบคำถามอะไรคำตอบที่มักใช้กัน
High availabilityจะเกิดอะไรขึ้นถ้า primary server ตาย?Replication และ failover
Client จำนวนมากจะเกิดอะไรขึ้นถ้าแอปหลายพันตัวเชื่อมต่อพร้อมกัน?Connection pooling
table ขนาดใหญ่จะเกิดอะไรขึ้นถ้า table หนึ่งโตถึงหลายพันล้าน row?Partitioning
Durability และ accessจะเกิดอะไรขึ้นถ้าดิสก์พังหรือมีผู้โจมตีเชื่อมต่อ?Backup และ security

โปรเจกต์เล็ก ๆ อาจมองข้ามทั้งสี่ด้านได้ แต่ระบบโปรดักชันที่จริงจังในที่สุดก็ต้องการทุกด้าน และทั้งสี่ด้านนี้มีปฏิสัมพันธ์กัน: replica ช่วยทั้งเรื่องความพร้อมใช้งาน และ กระจายภาระการอ่าน, pooling ปกป้อง primary ที่ป้อนข้อมูลให้ replica อยู่ด้วย และอื่น ๆ อีกมากมาย

แล็ปท็อปรัน PostgreSQL หนึ่ง process กับ client หนึ่งตัว แต่การตั้งค่าในโปรดักชันกระจายงานออกไปยังชิ้นส่วนหลายชิ้น ตัว application server ไม่ได้คุยกับฐานข้อมูลโดยตรง แต่คุยผ่าน connection pooler ที่คอยถือ server connection จำนวนน้อย ๆ ไว้ใช้ซ้ำ มีโหนดหนึ่งคือ primary ที่รับงานเขียน และมี replica หนึ่งตัวหรือมากกว่านั้นที่รับสำเนาการเปลี่ยนแปลงอย่างต่อเนื่องและตอบ query แบบอ่านอย่างเดียว

flowchart TD
  App1[App server] --> Pool[Connection pooler]
  App2[App server] --> Pool
  App3[App server] --> Pool
  Pool --> Primary[(Primary - reads and writes)]
  Primary -->|streams changes| R1[(Replica - reads)]
  Primary -->|streams changes| R2[(Replica - reads)]
  Primary -->|base backup plus WAL| Backup[Backup and archive storage]
การ deploy PostgreSQL ในรูปแบบโปรดักชัน

อ่านไดอะแกรมจากด้านบน app server จำนวนมากถูกรวมผ่าน pooler ตัวเดียว เพื่อให้ primary ไม่ต้องเจอ connection ดิบจำนวนมหาศาล จากนั้น primary ส่ง stream ของทุกการเปลี่ยนแปลงไปยัง replica ซึ่งช่วยรับภาระการอ่านแทน primary และข้อมูลของ primary ก็ถูกคัดลอกไปยัง backup storage อย่างต่อเนื่อง เพื่อให้สร้างทั้งระบบขึ้นใหม่ได้หลังเกิดภัยพิบัติ

  • Replication — การ stream write-ahead log ของ primary ไปยัง read replica เพื่อความพร้อมใช้งาน และ logical replication สำหรับคัดลอก table ที่เลือกระหว่าง server
  • Connection pooling — ทำไม PostgreSQL connection แต่ละตัวจึงเป็น process ของระบบปฏิบัติการ และ pooler อย่าง PgBouncer ทำ multiplex client จำนวนมากเข้ากับ server connection จำนวนน้อยได้อย่างไร
  • Partitioning — การแบ่ง table เชิงตรรกะขนาดมหึมาหนึ่ง table ออกเป็น partition ทางกายภาพจำนวนมาก เพื่อให้ query และงาน maintenance แตะเฉพาะส่วนที่ต้องการ
  • Backup และ security — backup แบบ logical และ physical, point-in-time recovery, role และ GRANT, row-level security, และการ lock ว่าใครเชื่อมต่อได้บ้าง

คุณรู้วิธีออกแบบโมเดลข้อมูล เขียน query สร้าง index และห่อการเปลี่ยนแปลงไว้ใน transaction แล้ว Operations คือสิ่งที่ทำให้ความรู้เหล่านั้นรอดจากการปะทะกับ traffic จริง ไม่มีอะไรในนี้เป็น PostgreSQL คนละตัว ยังเป็น server ตัวเดิม เพียงแต่ตั้งค่าและล้อมรอบไว้เพื่อให้ขีดจำกัดของเครื่องเดียวและความล้มเหลวของเครื่องเดียวไม่กลายเป็นขีดจำกัดและความล้มเหลวของแอปพลิเคชันคุณ

  • อย่าเพิ่งคว้า replication หรือ partitioning มาใช้ตั้งแต่วันแรก server ตัวเดียวที่ปรับแต่งดีพร้อม index ที่ดีรองรับภาระได้มากอย่างน่าประหลาดใจ เพิ่มความซับซ้อนก็ต่อเมื่อคุณวัดความจำเป็นได้แล้วเท่านั้น
  • Replica มีไว้เพื่อความพร้อมใช้งานและการขยายการอ่าน ไม่ใช่เพื่อรับงานเขียน — ทุกการเขียนยังคงไปที่ primary ตัวเดียว
  • Backup ที่คุณไม่เคย restore เลยคือความหวัง ไม่ใช่ backup ข้อพิสูจน์เดียวคือการทดสอบ restore ที่สำเร็จ
  • Security ไม่ใช่ขั้นตอนสุดท้ายที่คุณค่อยติดเข้าไป role แบบ least-privilege และการจำกัดการเข้าถึงเครือข่ายตั้งค่าได้ถูกที่สุดก่อนที่จะมีอะไรพึ่งพาเวอร์ชันที่หละหลวม
งานหลักของ connection pooler ที่อยู่หน้า PostgreSQL คืออะไร?
ในการตั้งค่าแบบ replicate ทั่วไป statement ที่เป็นการเขียนจะไปที่ไหน?
partitioning จัดการเรื่องสำคัญด้านใดในโปรดักชันเป็นหลัก?