1 คะแนน โดย GN⁺ 1 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ล็อกแบบ exclusive ระดับโกลบอล ของ Postgres LISTEN/NOTIFY จำกัดปริมาณงานของการใช้งานแบบตรงไปตรงมา แต่ถ้าบัฟเฟอร์การแจ้งเตือนแล้วส่งแบบเป็นชุด ก็สามารถรองรับ การเขียนสตรีมได้สูงสุด 60,000 ครั้งต่อวินาที บนเซิร์ฟเวอร์เดียว
  • ทรานแซกชันที่เรียกใช้ NOTIFY จะคง ล็อกระดับโกลบอล ไว้จนกว่าการคอมมิตและ fsync() จะเสร็จสิ้น เพื่อรับประกันลำดับการคอมมิตของการแจ้งเตือน ทำให้การคอมมิตถูกทำแบบอนุกรม และไม่สามารถใช้ group commit ได้
  • อิมพลีเมนเทชันแรกที่เรียก NOTIFY ผ่านทริกเกอร์ทุกครั้งที่มีการเขียนลงตารางสตรีม ให้ค่าหน่วงต่ำ แต่ติดคอขวดที่ 2,900 ครั้งต่อวินาที ทั้งที่ยังใช้ CPU, หน่วยความจำ และ IOPS ได้ไม่เต็มที่
  • หากใช้ตารางฐานข้อมูลเป็น แหล่งความจริง แทนการแจ้งเตือน และรวมการแจ้งเตือนไว้ในหน่วยความจำก่อนส่งเป็นระยะภายในทรานแซกชันเดียว จะลดจำนวนครั้งที่ต้องแย่งล็อกได้มาก
  • ความเป็นไปได้ที่การแจ้งเตือนในบัฟเฟอร์จะสูญหายเมื่อโปรเซสล่ม สามารถชดเชยได้ด้วยการโพลเป็นช่วงๆ ที่ความถี่ต่ำ และยังทำได้ถึง ค่าหน่วง 15~100ms พร้อมทรูพุตสูงขึ้น 20 เท่าจากเดิม

สตรีมค่าหน่วงต่ำที่สร้างด้วย Postgres

  • สตรีมที่อิงกับ Postgres จะเก็บแต่ละชิ้นของสตรีมเป็นแถวใหม่ในตาราง streams โดยโทเคนคำตอบจาก LLM ก็อาจเป็นหนึ่งชิ้นได้
  • ฝั่งการอ่านไม่รู้ได้ว่าชิ้นถัดไปจะมาถึงเมื่อไร จึงรออย่างมีประสิทธิภาพได้ยากหากใช้แค่การคิวรีธรรมดา
  • การโพลเป็นช่วงๆ หากเว้นช่วงนาน ค่าหน่วงจะสูงเกินไปสำหรับงานโต้ตอบอย่างแชตออนไลน์ แต่ถ้าโพลถี่เกินไป ตัวโพลจำนวนมากพร้อมกันก็จะถล่มฐานข้อมูล
  • เมื่อใช้ LISTEN/NOTIFY โปรเซสฝั่งอ่านสามารถรอแบบบล็อกอยู่ได้ แล้วตื่นขึ้นทันทีพร้อมการแจ้งเตือนว่ามีการบันทึกชิ้นใหม่ จึงหลีกเลี่ยงการโพลที่ไม่จำเป็นได้

คอขวดของการส่ง NOTIFY ทุกครั้งที่เขียน

  • ในอิมพลีเมนเทชันแรก ทุกครั้งที่มีการบันทึกชิ้นใหม่ลงตาราง streams ทริกเกอร์จะเรียกฟังก์ชันเพื่อ ส่ง NOTIFY หนึ่งครั้ง และโปรเซสฝั่งอ่านจะรอการแจ้งเตือนก่อนอ่านชิ้นใหม่
  • แม้จะได้ทั้งความถูกต้องและค่าหน่วงต่ำ แต่ก็ไม่สามารถรักษา การเขียนสตรีมเกิน 2,900 ครั้งต่อวินาที ได้ แม้บนฐานข้อมูล Postgres ขนาดใหญ่
  • ระหว่างที่เกิดคอขวด การใช้ CPU, หน่วยความจำ และ IOPS ไม่ได้สูงอย่างมีนัยสำคัญ โดยสาเหตุคือ ล็อกระดับโกลบอลในเส้นทางคอมมิตของ NOTIFY

ล็อกระดับโกลบอลที่รับประกันลำดับการคอมมิต

  • ทรานแซกชันที่เรียกใช้ NOTIFY จะเข้ายึด ล็อกแบบ exclusive ระดับโกลบอล เมื่อเริ่มคอมมิต และจะไม่ปล่อยจนกว่าจะคอมมิตสมบูรณ์และข้อมูลถูกเขียนลงดิสก์ด้วย fsync()
  • Postgres รับประกันว่าการแจ้งเตือนจะถูกส่งตามลำดับการคอมมิตของทรานแซกชัน และเก็บการแจ้งเตือนขาออกทั้งหมดไว้ในคิวภายในแบบโกลบอลที่ต้องตรงกับลำดับคอมมิตทุกประการ
  • การเพิ่มการแจ้งเตือนลงคิวต้องทำแบบทรานแซกชันเป็นส่วนหนึ่งของการคอมมิตด้วย แต่เนื่องจากแต่ละทรานแซกชันใช้เวลาคอมมิตไม่เท่ากัน จึง ไม่สามารถกำหนดลำดับได้ก่อนคอมมิตเสร็จ
  • ล็อกระดับโกลบอลจึงทำให้การคอมมิตของทรานแซกชันที่มีการแจ้งเตือนต้องเป็นแบบอนุกรม เพื่อกำหนดลำดับล่วงหน้า และให้ถูกเพิ่มลงคิวการแจ้งเตือนภายในด้วยลำดับเดียวกัน

การคอมมิตแบบอนุกรมจำกัดทรูพุตอย่างไร

  • เพราะการเขียนสตรีมทุกครั้งเรียก NOTIFY ผ่านทริกเกอร์ ทรานแซกชันการเขียนแต่ละครั้งจึงถือล็อกระดับโกลบอลตลอดช่วงคอมมิตและการ flush ลงดิสก์
  • เมื่อทรานแซกชันคอมมิตทีละตัว จึงไม่สามารถใช้ group commit ของ Postgres ที่จัดการหลายทรานแซกชันด้วย fsync() ครั้งเดียวได้
  • ทรูพุตจึงไม่อาจสูงเกินความเร็วที่ Postgres คอมมิตทรานแซกชันเดี่ยวได้ และงานต่างๆ ต้องรอล็อก ทำให้ทั้ง CPU และดิสก์ถูกใช้งานได้ไม่เต็มที่
  • แพตช์ที่จะรวมใน Postgres 19 ไม่ได้ลบล็อกระดับโกลบอลออก จึงไม่สามารถแก้คอขวดนี้ได้
    • แต่จะไปปรับแต่งกรณีเฉพาะที่มีหลายช่องทางการแจ้งเตือน และแต่ละ listener รอเพียงช่องทางเดียว

การบัฟเฟอร์การแจ้งเตือนและส่งแบบเป็นชุด

  • สำหรับการใช้งาน LISTEN/NOTIFY หลายแบบรวมถึงสตรีม การแจ้งเตือนไม่ใช่ แหล่งความจริง แต่เป็นเพียงสัญญาณให้ไปตรวจตารางที่เก็บข้อมูลจริง
  • ในโครงสร้างแบบนี้ ตัวการแจ้งเตือนเองไม่จำเป็นต้องมีลำดับโกลบอลที่สมบูรณ์แบบหรือความทนทานครบถ้วน จึงสามารถบัฟเฟอร์ไว้ในหน่วยความจำแล้วส่งเป็นระยะผ่านทรานแซกชันแบบแบตช์เดียวได้
  • ล็อกระดับโกลบอลจะถูกเข้ายึดไม่ใช่ทุกครั้งที่เขียนสตรีม แต่เฉพาะตอน ระบายบัฟเฟอร์ เท่านั้น
  • การเขียนแต่ละครั้งจึงดำเนินไปได้รวดเร็วโดยแยกจากการส่งการแจ้งเตือนเบื้องหลัง และใช้ประโยชน์จากการปรับแต่งของ Postgres อย่าง group commit เพื่อเพิ่มทรูพุตได้

การโพลความถี่ต่ำเพื่อชดเชยการแจ้งเตือนที่สูญหาย

  • หากโปรเซสหยุดทำงานขณะที่การแจ้งเตือนยังอยู่ในหน่วยความจำ การแจ้งเตือนนั้นอาจไม่ถูกส่งออกไป
  • โปรเซสฝั่งอ่านจึงรอการแจ้งเตือนไปพร้อมกับคิวรีฐานข้อมูลเป็นระยะ เพื่อตรวจว่ามี ข้อมูลสตรีมที่ถูกบันทึกโดยไม่มีการแจ้งเตือน หรือไม่
  • เพราะการโพลนี้เป็นเพียงวิธีเสริมเพื่อกู้คืนเฉพาะการแจ้งเตือนที่หายไป จึงสามารถทำที่ความถี่ต่ำและแทบไม่กระทบต่อประสิทธิภาพ

ทรูพุตและค่าหน่วง

  • อิมพลีเมนเทชันที่ปรับแต่งแล้วสามารถรองรับ การเขียนสตรีมสูงสุด 60,000 ครั้งต่อวินาที ในสภาพแวดล้อมที่มีโปรเซสอ่านพร้อมกัน ให้ทรูพุตสูงกว่าอิมพลีเมนเทชันแรก 20 เท่า
  • แม้เพิ่มทรูพุตแล้ว ค่าหน่วงก็ยังอยู่ในช่วง 15~100ms
  • ที่ทรูพุตสูงสุด CPU ของ Postgres ถูกใช้จนเต็ม แสดงว่าไม่ได้ติดที่การแย่งล็อกอีกต่อไป แต่แตะจุดอิ่มตัวจริงของฐานข้อมูลแล้ว
  • ดูโค้ดเบนช์มาร์กทั้งหมดได้ที่ dbos-postgres-benchmark

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

 
GN⁺ 1 시간 전
ความเห็นจาก Hacker News
  • ความสามารถในการขยายระบบเป็นสเกลต่อเนื่อง ไม่ใช่เรื่องแบบมีหรือไม่มี 6 หมื่นรายการต่อวินาทีอาจมากกว่าที่บางระบบต้องการถึง 1 แสนเท่า แต่ก็อาจน้อยกว่าที่อีกระบบต้องการอยู่ 1 แสนเท่าได้ ความผิดพลาดที่นักพัฒนาพบได้บ่อย อยากยกให้เป็น การเลือกเทคโนโลยีที่มีคุณสมบัติด้านการขยายระบบไม่ตรงโจทย์ มากกว่า “การ optimize เร็วเกินไป”
    เทคโนโลยีที่เล็กเกินไป เมื่อเกินขีดจำกัดแล้วจะล้มเหลวอย่างชัดเจน แต่เทคโนโลยีที่ขยายได้มากเกินความจำเป็นก็เพิ่มภาระการดูแลและข้อจำกัดเช่นกัน การนำเทคโนโลยีแบบนี้ไปใช้กับระบบขนาดเล็กที่สามารถลดความพยายามในการพัฒนาได้มากด้วยโมเดลที่สมบูรณ์กว่าก็เป็นทางเลือกที่ไม่ดีเช่นกัน
    ข้อจำกัดของ LISTEN/NOTIFY ต่ำพอที่จะต้องระวัง ดังนั้นแม้จะคำนวณโหลดสูงสุดแบบมองโลกในแง่ร้ายแล้ว ก็ควรเผื่อไว้อย่างน้อย 10 เท่า แต่สำหรับหลายโปรเจกต์ก็ยังเพียงพอ ด้วยข้อดีเรื่องการผสานกับฐานข้อมูล, ความพร้อมใช้งาน, และไม่ต้องดูแลบริการแยก จึงไม่ใช่ตัวเลือกที่ควรตัดทิ้งไปเลย และแม้แต่ 2 พันรายการต่อวินาทีที่ยกมาก่อนหน้านี้ ก็ยังถือว่าสูงมากสำหรับระบบที่ประมวลผลข้อความละ 1 วินาที

    • แม้จะเป็นข้อโต้แย้งเล็กน้อยต่อบทความที่ดี แต่ระบบที่รองรับ 6 พันล้านคำขอต่อวินาที แทบไม่มีอยู่จริง และต่อให้มี ก็น่าจะใช้เครื่องมือที่สร้างขึ้นเองให้เหมาะกับจุดประสงค์นั้น
    • ปัญหาแบบคาดว่าจะต่ำกว่า 6 หมื่นรายการต่อวินาที แต่กลับพุ่งจาก 2 หมื่นเป็น 2 แสนรายการต่อวินาที ยังดีกว่าการสร้างระบบเผื่อ 1 ล้านรายการต่อวินาที แต่โหลดจริงมีแค่ 2 หมื่นรายการต่อวินาที ความสำเร็จเกินคาดแบบแรกช่วยจ่ายค่ามาตรการชั่วคราวและต้นทุนการขยายระบบได้ แต่แบบหลังจะติดอยู่กับโครงสร้างต้นทุนที่สูงและการลงทุนล่วงหน้า
      ทางที่ดีกว่าคือออกแบบให้เหมาะกับขนาดที่คาดจริงพร้อมเผื่อพอสมควร แล้วค่อยเลือกมากกว่านั้นเฉพาะเมื่อความสามารถในการขยายเพิ่มขึ้นแทบจะฟรีเท่านั้น ถ้าแค่จ่ายเพิ่มอีกไม่กี่พันดอลลาร์เพื่อซื้อฮาร์ดแวร์ที่ใหญ่ขึ้น หรือเป็นตัวเลือกที่เทียบเท่ากันทุกอย่างนอกจากการขยายระบบ ก็เลือกตัวที่ใหญ่กว่าก็ได้
    • ในกรณีนี้ถือว่าขยายได้ เพราะไปชน ขีดสูงสุดของฮาร์ดแวร์ แล้ว คอขวดไม่ใช่ฐานข้อมูลหรือ I/O แต่เป็นฮาร์ดแวร์ และที่ throughput สูงสุด CPU ของ Postgres ถูกใช้จนเต็ม แสดงถึงการอิ่มตัวของตัวฐานข้อมูลเอง ไม่ใช่การแย่งทรัพยากร
  • เคยประสบความสำเร็จมากกับการใช้ LISTEN/NOTIFY ร่วมกับ Rust GraphQL subscription broker จำนวน subscription มีเป็นหลักหลายหมื่น แต่การเชื่อมต่อ LISTEN มีเพียงโฮสต์ละหนึ่ง รวมทั้งหมดแค่ 3–4 การเชื่อมต่อ
    ส่งทุกการเปลี่ยนแปลงไปยังแต่ละโฮสต์ แล้วให้โฮสต์จัดการ subscription ของผู้ใช้จริงและตัดสินใจว่าจะ publish อะไร หากเปลี่ยนจากโฮสต์ Ruby หรือ Node หลายร้อยเครื่องมาเป็นโฮสต์ Rust ไม่กี่เครื่อง ก็ทำให้สถาปัตยกรรมง่ายลงมาก และแนวทางที่มักถูกมองว่าขยายไม่ได้ก็ยังทำงานได้ดีทีเดียว

    • อยากรู้ว่ามี ไลบรารี GraphQL สำหรับ Rust ตัวไหนที่แนะนำบ้าง
  • ตอนทำงานเป็น CTO เคยเริ่มจากประมาณ 1 แสนรายการต่อวันในทุกบริการ แล้วเติบโตเป็นหลักหลายล้าน จนสุดท้ายเป็นหลักหลายสิบล้าน ระหว่างทาง วิศวกรคนหนึ่งสร้างคิวบนความหมายเชิงพฤติกรรมของ LISTEN/NOTIFY เพื่อใช้ประโยชน์จาก ความสอดคล้องที่เข้มงวด กับ data model มันไม่ได้เข้าใจยาก และในตอนนั้นก็ดูสมเหตุสมผลเพราะช่วยตัดชั้นการจัดเก็บและส่งต่อแยกต่างหากออกไปได้
    แต่พอต้องขยายฟังก์ชันที่ทำขึ้นเอง ก็อึดอัดมากเพราะต้องหลบเลี่ยงการทำงานภายในของ PostgreSQL และควรย้ายไปใช้ระบบอื่นให้เร็วกว่านั้น อีกทั้งยังขยายได้ไม่ดี ทำให้บน RDS มีการแย่ง disk อย่างหนักจนหาสาเหตุได้ยาก และการทำ VACUUM ของตารางนั้นก็เป็นฝันร้าย การนำคิวที่คุ้นเคยไปทำใหม่ในรูปแบบแปลกประหลาดด้วยฟีเจอร์ภายใน PostgreSQL ทำให้วิศวกรคนอื่นกลัว ไม่อยาก debug และไม่อยากเป็นเจ้าของมัน
    บทเรียนสำคัญที่ไม่เกี่ยวกับรายละเอียดอย่าง schema หรือ index คือ ควรเริ่มจาก เทคโนโลยีที่เรียบง่ายและคาดเดาได้ เสมอ หากไม่จำเป็นต้องมีความสอดคล้องของข้อมูลที่เข้มงวดมาก การเพิ่มองค์ประกอบในอินฟราฯ อีกหนึ่งตัวก็มักคุ้มกว่า ถ้าแลกกับการใช้คิวที่มีสัญญา API เรียบง่ายอย่าง SQS หรือ Redis queue แล้วปรับส่วนที่เหลือให้เข้ากับมัน ยิ่ง data store หลักตัวเดียวมีภาระเชิงกลไกน้อยเท่าไร ก็ยิ่งดี

    • สุดท้ายแล้วอาจสรุปได้ว่า “ถ้าใช้โดยไม่เข้าใจวิธีทำงาน มันก็ขยายไม่ได้” LISTEN/NOTIFY แบบพื้นฐานนั้นขยายไม่ได้ แต่บทความต้นฉบับได้หาวิธีทำให้มันขยายได้จริงแล้ว ดังนั้นแต่ละทีมไม่จำเป็นต้องแก้โจทย์นี้ใหม่
      เมื่อ ecosystem ของ distributed systems พัฒนาขึ้น เราก็เข้าใจมากขึ้นว่าแต่ละองค์ประกอบทำอะไรได้บ้าง การเริ่มต้นด้วย องค์ประกอบให้น้อย แล้วค่อยเพิ่มเมื่อจำเป็นจริง ๆ จะทำให้ระบบแข็งแรงกว่า
    • กรณีที่องค์ประกอบใหม่มีน้ำหนักมากกว่าปัจจัยอื่นนั้นพบไม่บ่อย แต่การ รันคิวให้แยกจากองค์ประกอบสถาปัตยกรรมอื่น มีข้อดีมาก คิวถูกสร้างมาเพื่อ store-and-forward อยู่แล้ว ดังนั้นการแยกวงจรชีวิตของมันออกมา ทำให้ระบบอื่น ๆ แยกจากกันได้ระหว่างการอัปเดต การวิเคราะห์เหตุขัดข้อง และช่วงเวลาการแพตช์
    • เรื่องนี้ใกล้เคียงกับปัญหาด้านการจัดการมากกว่า และไม่เห็นด้วยกับข้อสรุปว่าต้องเพิ่มองค์ประกอบใหม่ในอินฟราฯ การเพิ่ม network node ใหม่ เพียงเพราะนักพัฒนาไม่อยากแตะบางส่วนของสแตกนั้นไม่สมเหตุสมผล ควรมอบหมายให้รับผิดชอบส่วนนั้นแทน
  • ยังคงชอบ DBOS ที่ใช้ Postgres และตอนนี้รวมถึง SQLite ได้อย่างเหมาะสม มันแทบใส่เข้าไปในสแตก CRUD เดิมได้โดยไม่ต้องออกแรงมาก
    พอเริ่มใช้ durable workflow ก็จะเห็นจุดที่เอาไปใช้ได้เพิ่มขึ้นเรื่อย ๆ ช่วงนี้กำลังลองมองอีเมลแต่ละฉบับเป็น durable workflow โดยให้ผู้ใช้, คู่สนทนา, เอเจนต์, และเครื่องมืออย่าง GitHub หรือ Attio เข้าร่วมใน flow ตามลำดับ
    https://housecat.com/blog/gmail-durable-workflows-sandbox-vm

  • บทความแบบนี้โดยมากคือผลจากการที่แต่ละคนประเมินปัญหา ความเข้าใจ และทางแก้ของตัวเองอย่างอิสระ จะเรียกว่าไม่เชี่ยวชาญเพียงเพราะคาดหวัง performance บางอย่างจากค่าเริ่มต้นของเครื่องมือก็กำกวม และทุกคนก็เรียนรู้ต่อไปผ่านความล้มเหลว
    การใช้เซิร์ฟเวอร์ฐานข้อมูล 96 คอร์·RAM 384GB ในการทดลอง (https://github.com/dbos-inc/dbos-postgres-benchmark/blob/mai...) เป็นประเด็นสำคัญมากและควรระบุให้ชัดเจน ฐานข้อมูลสามารถ scale up แนวตั้งได้ แต่ก็มีขีดจำกัดเช่นกัน ใครเชื่อมต่อจากที่ไหนก็ส่งผลต่อ performance และ latency โดยรวม
    6 หมื่นรายการต่อวินาทีอาจดูมาก แต่สิ่งที่ทำให้ระบบจริงล่มมักเป็น การพุ่งขึ้นของทราฟฟิกแบบฉับพลัน มากกว่าทราฟฟิกปกติ หากไม่ใช่บริษัทใหญ่ ก็คงไม่เริ่มต้นด้วยเซิร์ฟเวอร์ขนาดใหญ่อย่างนี้ และถ้ารวม read replica กับการทำซ้ำข้าม region แล้ว database cluster สำหรับ production หนึ่งชุดก็มีค่าใช้จ่ายเกิน 1 แสนดอลลาร์

  • น่าจะเป็นโพสต์ที่เกี่ยวข้อง: Postgres LISTEN/NOTIFY does not scale - https://news.ycombinator.com/item?id=44490510 - กรกฎาคม 2025, ความคิดเห็น 321 รายการ

  • ดูเหมือนว่าบทความจะขาดส่วนที่สำคัญที่สุด คือวิธี กำหนดออฟเซ็ตหรือหมายเลขลำดับ เพื่อให้ติดตามได้ว่าผู้บริโภคอ่านถึงไหนแล้ว และให้ไปดึงข้อความใหม่จากเส้นทางสำรองได้ มีหลายวิธี แต่แก้ให้ได้โดยไม่มีความซับซ้อนหรือการแย่งล็อกนั้นไม่ง่าย และถ้าทำผิดก็อาจเกิด race condition กับฝั่งผู้บริโภคได้ โดยทั่วไปผู้เขียนคงต้องล็อกแถวเดียวในตารางสถานะหรืออะไรทำนองนั้น เพื่อกำหนดหมายเลขถัดไปของหัวข้ออีเวนต์
    สงสัยว่าวิธีที่ดีที่สุดคืออะไร เครื่องมือที่อ่าน change data capture (CDC) แล้วเขียนหมายเลขอีเวนต์ที่จัดสรรแล้วลงอีกตารางหนึ่งก็ดูอาจใช้ได้ แต่ latency อาจสูงขึ้น และตัวประมวลผล CDC นั้นก็ต้องทำ NOTIFY ด้วย
    ฝั่งผู้บริโภคเองก็มีกรณีใช้งานที่สามารถเพิ่ม throughput ได้มากด้วยการ ประมวลผลแบบแบตช์ ในกรณีนี้ไม่ต้องใช้ LISTEN/NOTIFY ก็ได้ แค่รันผู้บริโภควนซ้ำและประมวลผลข้อความใหม่ที่ยังไม่ถูกจัดการทั้งหมดในแต่ละรอบ แล้วบันทึกหมายเลขลำดับล่าสุดไว้ระหว่างรอบ

  • เท่าที่จำได้ ในรีลีสแรกที่รองรับ LISTEN/NOTIFY นั้น การทำล็อกยังไม่ดีนักจึงมีปัญหาด้านประสิทธิภาพ และบทความเก่าที่ถูกวิจารณ์ที่นี่ก็แก้ไขเรื่องนี้ไว้แล้วในคำชี้แจงหลังย่อหน้าแรก
    ถ้าวันที่แก้ไขคือ 8 พฤษภาคม ก็ต้องยอมรับว่าโพสต์วันที่ 24 กรกฎาคมที่บอกว่าฟีเจอร์นี้ขยายขนาดไม่ได้ อาจไม่ได้เขียนด้วยเจตนาร้าย และก็อาจไม่ได้ผิดตามบริบทในตอนนั้น

    • ถ้าหมายถึงการปรับแต่งที่จะเข้า Postgres 19 ต้นฉบับก็พูดถึงเหมือนกัน แพตช์นั้น(https://github.com/postgres/postgres/commit/282b1cde9dedf456...) ไม่ได้เอา global lock ออก หรือแก้คอขวดที่สังเกตพบ
      แต่เป็นการปรับให้เหมาะกับกรณีที่จำกัดมากกว่า คือมีช่องแจ้งเตือนจำนวนมาก และผู้รับแต่ละรายรอเพียงช่องใดช่องหนึ่งโดยเฉพาะ
  • ครั้งล่าสุดที่ตรวจสอบ LISTEN/NOTIFY มี เพดาน 8,000 ไบต์ สำหรับข้อมูลแจ้งเตือน ซึ่งเป็นมุมที่เห็นได้ชัดว่ามันขยายขนาดไม่ได้ ถ้าข้อมูลนั้นไม่สามารถเก็บเป็นแถวแล้วส่งแค่ ID แจ้งเตือนได้ ก็ใช้งานได้ยาก
    อีเวนต์ของเว็บเกมเป็นข้อมูลชั่วคราวที่อธิบายการเปลี่ยนสถานะ จึงไม่มีเหตุผลจะเก็บไว้ในฐานข้อมูล และมันอาจเกิน 8,000 ไบต์ จึงไม่เหมาะกับงานลักษณะนี้

    • ถ้าจะออกแบบระบบแจ้งเตือนที่ขยายขนาดได้ ผมจะกำหนด เพดานขนาดของการแจ้งเตือน ไว้ เพื่อคงขนาดข้อความให้เป็น O(1) และโฟกัสกับการขยายจำนวนการแจ้งเตือน เพราะข้อความที่ใหญ่ได้ตามอำเภอใจอาจทำให้ประสิทธิภาพหยุดชะงัก และยังเป็นสัญญาณว่าคุณอาจกำลังใช้ระบบแจ้งเตือนผิดวิธี
    • สงสัยว่าจะส่งข้อความที่อ้างอิงถึงสถานะที่เปลี่ยนไปได้ไหม แม้จะไม่ได้ชี้ไปยังแถวใดแถวหนึ่งโดยตรงก็ตาม
  • บทความพูดถึงการแย่งล็อกของคิวส่วนกลาง แต่ดูเหมือนจะไม่กล่าวถึงอีกปัญหาหนึ่งของ คิวส่วนกลางขนาดคงที่ คือผู้รับที่ช้าเพียงรายเดียวในช่องหนึ่ง สามารถบล็อกการเขียนของทุกช่องได้ อย่างน้อยเมื่อไม่กี่ปีก่อน ความล้มเหลวลักษณะนี้ยังเกิดขึ้นได้ และตอนนี้อาจเปลี่ยนไปแล้ว