23 คะแนน โดย xguru 2023-04-13 | 6 ความคิดเห็น | แชร์ทาง WhatsApp
  • เลิกใช้ RabbitMQ และเปลี่ยนมาใช้คิวบน PostgresDB ที่อาศัย SQL
  • ใช้เวลาเปลี่ยนประมาณครึ่งวัน และซอร์สโค้ดลดลง 580 บรรทัด
  • ที่สำคัญกว่านั้นมากคือความเสถียรและความสามารถในการฟื้นตัว (Resiliency) ดีขึ้นอย่างมาก
  • นี่ไม่ใช่การพูดถึงปัญหาของระบบคิวอย่าง RabbitMQ แต่เป็นส่วนหนึ่งของความพยายามในการทำให้ระบบเรียบง่ายขึ้น
    • Prequel ผู้เขียนบทความนี้ เป็นผลิตภัณฑ์ที่ช่วยให้บริษัท B2B SaaS ซิงก์กับฐานข้อมูลของลูกค้าผ่าน data pipeline ขนาดใหญ่
  • เดิมประกอบด้วย RabbitMQ + AQMP + Helm + GoLang wrapper ซึ่งช่วงหนึ่งทำงานได้ดี แต่หลังจากนั้นปัญหาก็เริ่มปรากฏ
    • การส่งข้อความล่าช้านานเกินไปจนทำให้ข้อความถูกยกเลิก
    • เมื่อ consumer ทำ prefetch ข้อความ จะเกิดสถานการณ์ที่ข้อความถัดไปถูกจองค้างไว้จนกว่าจะประมวลผลข้อความปัจจุบันเสร็จ
    • หากตั้งค่า prefetch เป็น 0 จะกลายเป็นอนันต์ ทำให้ไม่สามารถปิดการทำงานของ prefetch ได้
    • ปัญหานี้เกิดขึ้นเพราะงานที่รับข้อความไปประมวลผลมักเป็นงานระยะยาว (การส่งข้อมูล)
  • แม้จะเข้าใจอย่างชัดเจนแล้วว่าเกิดอะไรขึ้น แต่ก็ไม่มีวิธีแก้ได้ทันที และเพราะปัญหานี้เกิดกับลูกค้าในโปรดักชันจึงไม่สามารถรอได้
  • จึงเปลี่ยนมาใช้วิธีอ่านและเขียนผ่านตารางเดียวแบบเรียบง่ายใน Postgres
    • ใช้ Row-Level Lock สำหรับการอ่าน/เขียน เพื่อรับประกันว่าจะมี consumer เพียงตัวเดียวที่อ่านงานนั้นได้
    • เรียบง่ายจนแทบไม่น่าเชื่อ แต่ทำงานได้อย่างสมบูรณ์แบบ
  • ข้อดีคือสถานะของแอปพลิเคชันไม่ถูกแยกออกเป็น RabbitMQ กับ Postgres อีกต่อไป แต่ถูกรวมอยู่ในที่เดียว

6 ความคิดเห็น

 
galadbran 2023-04-15

ผมเองก็เคยทำคิวขึ้นมาใช้โดยตรงด้วย row level lock บน MySQL และมันก็ทำงานได้ดีในโปรดักชันมาหลายปีแล้วครับ
ผมต้องการเพียงแค่สิ่งที่ให้ความสามารถคล้ายคิวกับ worker หลายตัวได้อย่างง่าย ๆ พร้อมกับเก็บ payload ที่มีสถานะรอ/กำลังดำเนินการ/ล้มเหลว (ถ้าเสร็จแล้วก็ลบ) ไว้ในคิวเดียวกันได้

จากในบทความที่เปลี่ยนจาก RabbitMQ ไปเป็นฐานข้อมูลได้ในเวลาสั้น ๆ ก็ดูเหมือนว่าน่าจะเป็นเพราะจริง ๆ แล้วไม่ได้จำเป็นต้องใช้ความอเนกประสงค์ ฟีเจอร์ที่หลากหลาย หรือความสามารถในการตั้งค่าต่าง ๆ ของบริการคิวเฉพาะทางแยกต่างหาก

 
pseudojo 2023-04-15

ดูเหมือนว่าจะเกิดปัญหาจากการคลาดกันระหว่างการส่ง ACK แบบแมนนวลกับทรานแซกชันของ DB,
แต่ที่น่าสนใจคือเขาเลือกแก้ด้วยการถอด RabbitMQ ออก แทนที่จะเป็นการแก้เชิงวิศวกรรม
ทั้งที่ RabbitMQ เองก็คงไม่ได้ผิดอะไร...

 
laracool 2023-04-13

https://news.ycombinator.com/item?id=35526846
มีความคิดเห็นกันเยอะมากในคอมเมนต์

 
dddddd 2023-04-13

มีของแบบนี้ที่ทำงานคล้ายกันอยู่เหมือนกันนะครับ https://github.com/pjongy/jasyncq

 
laracool 2023-04-13

ดูเหมือนว่าจะมีโอกาสถูก select พร้อมกันได้ เลยอยากทราบว่าแก้ปัญหานั้นอย่างไรครับ

 
dddddd 2023-04-13

ดูเหมือนว่าจะเขียนว่า row level lock นะครับ