- ทำเบนช์มาร์กประสิทธิภาพของ publish/subscribe (pub-sub) และ คิว (queue) บน Postgres เพื่อชี้ให้เห็นความเป็นไปได้ที่ฐานข้อมูลเพียงตัวเดียวจะใช้แทนระบบส่งข้อความได้
- บนโหนดเดี่ยว 4vCPU ทำได้ เขียน 5,036 ครั้ง/วินาที และอ่าน 25,183 ครั้ง/วินาที และในสภาพแวดล้อมแบบทำสำเนา 3 โหนดก็ยังคงรักษาปริมาณงานใกล้เคียงเดิม โดยมี end-to-end latency 186ms (p99)
- บนโหนดขนาดใหญ่ 96vCPU ทำได้ถึง เขียน 238MiB/s และอ่าน 1.16GiB/s โดยใช้ CPU ไม่ถึง 10% แสดงให้เห็นว่ายังมีเผื่อสำหรับการประมวลผลอีกมาก
- ในการทดสอบคิวก็ทำได้ 2,885 ครั้ง/วินาที บนโหนดเดี่ยว และ 2,397 ครั้ง/วินาที ในสภาพแวดล้อมแบบทำสำเนา ซึ่งเพียงพอสำหรับขนาดองค์กรส่วนใหญ่
- พิสูจน์ให้เห็นว่าแทนที่จะใช้ระบบกระจายที่ซับซ้อน ก็สามารถใช้ โครงสร้างพื้นฐาน Postgres เพียงตัวเดียวเพื่อรองรับเวิร์กโหลดระดับหลาย MB/s ได้ พร้อมตอกย้ำแนวทางปฏิบัติว่า “ใช้เทคโนโลยีที่เรียบง่ายไปก่อนจนกว่าจะจำเป็น”
สองขั้วของการเลือกเทคโนโลยี
- วงการเทคโนโลยีแบ่งออกเป็น ฝั่งที่ยึดคำฮิต กับ ฝั่งที่ยึดสามัญสำนึก
- ฝั่งแรกมักถูกดึงดูดด้วยคำทางการตลาดอย่าง “เรียลไทม์”, “ขยายได้ไม่สิ้นสุด”, “ขับเคลื่อนด้วย AI”
- ฝั่งหลังให้ความสำคัญกับความเรียบง่ายและการใช้งานจริง พร้อมหลีกเลี่ยงความซับซ้อนที่ไม่จำเป็น
- ช่วงหลังมีกระแส Small Data และ ยุคฟื้นฟู Postgres ที่ช่วยหนุนฝั่งหลัง
- ข้อมูลมีขนาดเล็กลง ขณะที่ฮาร์ดแวร์ทรงพลังขึ้น
- Postgres สามารถใช้เป็นระบบเดียวแทนโซลูชันเฉพาะทางหลายแบบได้ (
jsonb, pgvector, tsvector เป็นต้น)
ภาพรวมของเบนช์มาร์ก
- เป้าหมาย: วัดว่า Postgres สามารถขยายตัวได้มากแค่ไหนในงาน ส่งข้อความแบบ pub/sub และ ประมวลผลคิว
- สภาพแวดล้อมทดสอบ: AWS EC2
c7i.xlarge (4vCPU) และ c7i.24xlarge (96vCPU)
- เปรียบเทียบ 3 รูปแบบ
- โหนดเดี่ยว
- คลัสเตอร์ทำสำเนา 3 โหนด
- โหนดเดี่ยวขนาดใหญ่
ผลเบนช์มาร์ก Pub/Sub
- โหนดเดี่ยว 4vCPU
- เขียน 4.8MiB/s (5,036msg/s), อ่าน 24.6MiB/s (25,183msg/s), latency 60ms (p99)
- ใช้ CPU 60%, ดิสก์เขียน 46MiB/s
- ระบบทำสำเนา 3 โหนด 4vCPU
- เขียน 4.9MiB/s, อ่าน 24.5MiB/s, latency 186ms (p99)
- รักษาปริมาณงานไว้ได้ โดยมีค่าใช้จ่ายรายปีประมาณ $11,514
- โหนดเดี่ยว 96vCPU
- เขียน 238MiB/s (243kmsg/s), อ่าน 1.16GiB/s (1.2Mmsg/s), latency 853ms (p99)
- ใช้ CPU ไม่ถึง 10% โดยคอขวดคือความเร็วในการเขียนต่อพาร์ทิชัน
- สรุป: แข่งขันกับ Kafka ได้ในเวิร์กโหลดระดับเล็กถึงกลาง และแม้ใช้โครงสร้างเรียบง่ายก็รองรับงานระดับหลายสิบ MB/s ได้
ผลเบนช์มาร์ก Queue
- ใช้การทำคิวแบบง่ายบนพื้นฐาน
SELECT FOR UPDATE SKIP LOCKED
- โหนดเดี่ยว 4vCPU
- 2.81MiB/s (2,885msg/s), latency 17.7ms (p99), CPU 60%
- ระบบทำสำเนา 3 โหนด 4vCPU
- 2.34MiB/s (2,397msg/s), latency 920ms (p99), CPU 60%
- โหนดเดี่ยว 96vCPU
- 19.7MiB/s (20,144msg/s), latency 930ms (p99), CPU 40~60%
- แม้เป็นโหนดเดี่ยวก็เพียงพอต่อความต้องการด้านปริมาณงานคิวขององค์กรส่วนใหญ่
การตัดสินใจใช้ Postgres
- ในกรณีส่วนใหญ่ การเลือก Postgres เป็นตัวเลือกตั้งต้นถือว่าสมเหตุสมผล
- สามารถดีบัก แก้ไข และ join ข้อความได้ด้วย SQL
- เมื่อเทียบกับ Kafka แล้ว การปฏิบัติการและการดูแลรักษาง่ายกว่า
- Kafka ถูกออกแบบมาเพื่อสมรรถนะสูง แต่สำหรับเวิร์กโหลดขนาดเล็กถือว่าเกินความจำเป็น
- อ้างคำเตือนของ Donald Knuth ที่ว่า “การปรับแต่งเร็วเกินไปคือรากเหง้าของความชั่วร้ายทั้งปวง”
- ถ้าอยู่ในระดับหลาย MB/s นั้น Postgres ก็เพียงพอแล้ว
แนวทาง MVI ด้านโครงสร้างพื้นฐาน
- Minimum Viable Infrastructure: สร้างระบบขั้นต่ำด้วยเทคโนโลยีที่องค์กรคุ้นเคยอยู่แล้ว
- Postgres ถูกใช้อย่างแพร่หลายและหาคนทำงานได้ง่าย
- ยิ่งมีองค์ประกอบน้อย ภาระด้านเหตุขัดข้องและการปฏิบัติการก็ยิ่งลดลง
- การนำเทคโนโลยีที่ไม่จำเป็นเข้ามาจะก่อให้เกิด โอเวอร์เฮดในระดับองค์กร
- ทั้งต้นทุนด้านการเรียนรู้ การมอนิเตอร์ การดีพลอย และการปฏิบัติการ
ประเด็นเรื่องการขยายระบบ
- Postgres ขยายได้จริงในทางปฏิบัติ
- OpenAI ยังใช้ Postgres ที่อิง single write instance อยู่
- และยังปฏิบัติการได้อย่างเสถียรในระดับผู้ใช้หลายร้อยล้านคน
- บริษัทส่วนใหญ่เติบโตอย่างค่อยเป็นค่อยไป จึงมี เวลาอีกหลายปีก่อนจะต้องเปลี่ยนเทคโนโลยี
- การ “ออกแบบเผื่อไวรัล” เป็นการ overdesign ที่เกินจำเป็น
- เปรียบเหมือน “ซื้อ Marshall amp เพื่อไปเล่นเปิดให้ Coldplay”
บทสรุป
- “ใช้ Postgres ไปจนกว่ามันจะพัง”
- เทคโนโลยีที่เรียบง่ายก็ให้ประสิทธิภาพสูงได้เพียงพอ
- การนำระบบกระจายที่ซับซ้อนเกินความจำเป็นมาใช้เป็นเรื่องไม่มีประสิทธิภาพ
- เมื่อจับคู่กับฮาร์ดแวร์ยุคใหม่ Postgres คือ ตัวเลือกเชิงปฏิบัติที่รองรับเวิร์กโหลดส่วนใหญ่ได้
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
การนำ หลัก Pareto ไปใช้กับทุกสถานการณ์เป็นการตีความที่ผิด
การบอกว่า Postgres จัดการได้ 80% ของยูสเคสด้วยความพยายาม 20% เมื่อเทียบกับ Kafka เป็นข้ออ้างที่ไม่มีหลักฐาน
หลัก Pareto มีความหมายเฉพาะในสถานการณ์ที่มี การแจกแจงแบบกฎกำลัง เท่านั้น
แค่บอกว่า Postgres ครอบคลุมยูสเคสได้มากพอ มีความเสถียร และเป็นเครื่องมือที่ผ่านการพิสูจน์แล้วก็พอ
จากประสบการณ์ที่เคยรับมือทั้งระบบขนาดเล็ก (หลายร้อยอีเวนต์ต่อชั่วโมง) ไปจนถึงขนาดใหญ่มาก (หลายล้านล้านอีเวนต์ต่อชั่วโมง) สิ่งแรกที่ต้องถามคือ จำเป็นต้องมีคิวจริงหรือไม่
แนวทางใช้ Postgres กับทุกอย่างมีความเสี่ยง
lock และ serialization level ไม่ได้เข้าใจได้ง่ายแบบสัญชาตญาณ จึงอาจทำให้เกิดคอขวดด้านประสิทธิภาพ
แม้จะใช้ Postgres มาหลายสิบปี ก็ไม่ควรออกแบบระบบด้วยความเชื่อแบบไม่ลืมหูลืมตา
คิดว่าแนวทาง ตาราง event log บน SQL ใช้งานได้ดี
แต่ข้อเสียคือ เครื่องมือฝั่งไคลเอนต์ยังขาดแคลน ขณะที่ Kafka มี ecosystem ของไลบรารีที่สมบูรณ์กว่าซึ่งเป็นข้อได้เปรียบ
บริษัทของเราทำมาตรฐานการส่งอีเวนต์ระหว่างบริการบน SQL แล้ว (feedapi-spec)
มันอาจยังไม่ mature เท่า Kafka แต่มีโอกาสพัฒนาเป็นสแตกไลบรารีกลางที่รองรับ storage engine ได้หลายแบบ
ทุกวันนี้ผู้คนมีแนวโน้มจะหลงใหล เทคโนโลยีใหม่ มากเกินไป
Postgres นั้นยอดเยี่ยม แต่ก็ควรใช้ เครื่องมือที่เหมาะกับปัญหา
Postgres ไม่ได้ถูกออกแบบมาสำหรับ pub-sub ส่วน Kafka ถูกสร้างมาเพื่อสิ่งนั้น
ควรหลีกเลี่ยงกระแสที่ทุกผลิตภัณฑ์พยายาม “ทำได้ทุกอย่าง” เพราะเครื่องมือที่ เก่งเฉพาะทาง มักดีกว่า
การทำ “หมายเลขออฟเซ็ตที่เพิ่มขึ้นแบบ monotonic” เป็นปัญหาที่จัดการยาก
sequence แบบธรรมดาทำให้ลำดับทรานแซกชันกับเวลาคอมมิตไม่ตรงกัน จนเกิดปัญหาได้
สงสัยว่าได้ทำ Kafka benchmark จริงหรือไม่
ผลลัพธ์ที่ได้จากสภาพแวดล้อม 96 vCPU นั้น Kafka ทำได้แม้ตั้งค่าที่ 4 vCPU
ประสิทธิภาพของ Postgres ช้าผิดปกติ
ถ้าไม่จำเป็นต้องใช้ Kafka ก็ไม่ต้องใช้ แต่การอวดว่า Postgres ทำได้ 5k msg/s ไม่มีความหมาย
มีคนสุดโต่งอยู่สองฝั่ง คือ “พวกไล่ตาม buzzword” กับ “พวกยึดติดแต่สิ่งที่เคยเรียนมา”
วิศวกรที่มองโลกตามจริงจะเลือกอย่าง ใช้ได้จริงและเหมาะสม ระหว่างกลาง
ฟังก์ชันหลักของ Kafka คือ การควบคุมออฟเซ็ตแยกตามผู้บริโภค
มันเป็นความสามารถจำเป็นในสภาพแวดล้อมที่หลายทีมอ่าน topic เดียวกัน
ความสามารถในการเลื่อนออฟเซ็ตไปข้างหน้าหรือย้อนกลับได้ช่วยชีวิตมาแล้วหลายครั้ง
เลยสงสัยว่าคิวบน Postgres รองรับฟังก์ชันแบบนี้หรือไม่
กรอบคิดแบบ “ฝ่ายตาม buzzword vs ฝ่ายสามัญสำนึก” นั้นผิดตั้งแต่ต้น
การพยายามสร้าง Kafka ขึ้นมาใหม่บน Postgres ไม่ใช่สามัญสำนึก
ถ้าต้องการฟังก์ชันระดับ Kafka จริง ๆ ก็ใช้ Kafka ไปเลย