تقارن هذه المقالة بنية أدوات التجميع الثلاثة: اللغة، وأوضاع التجميع، والنموذج الفردي أو المتعدد المستأجرين، والوظائف التي تتجاوز التجميع النقي. وقد نشر كل من Tembo وPkgPulse مقارنات عددية لهذه الأدوات الثلاث، لكننا لم نقم بإعادة إنتاج أي من قياساتها بأنفسنا. إن موقفنا التحريري بشأن المعايير، المفصل في منهجية قياس الأداء ، هو عدم إعادة نشر رقم لم نتحقق منه بأنفسنا أبدًا. ما ستجده هنا بدلاً من ذلك: البنية الفعلية لكل أداة، وكيف تقوم Aurabase فعليًا بتوجيه حركة مرور Postgres الخاصة بها، والتي تم التحقق منها قسمًا تلو الآخر في الكود المصدري.
- يظل PgBouncer (C) هو المُجمِّع الأكثر إثباتًا والأفضل تكاملًا مع Kubernetes: يعتمد CloudNativePG عليه مباشرةً في مورده
Pooler. - يستهدف Supavisor (مشروع Elixir، Supabase) مشكلة مختلفة: خدمة آلاف قواعد البيانات من نفس الخدمة، بدلاً من مُجمِّع واحد لكل قاعدة بيانات.
- يضيف PgCat (Rust) تقسيم التطبيق وموازنة التحميل بين النسخ المتماثلة وتجاوز الفشل التلقائي إلى التجميع الأولي.
- يعرض مستودع Aurabase استخدام PgBouncer على مستويين: نشر مشترك للأسطول المشترك، ومورد
Poolerتتم إدارته بواسطة CloudNativePG لكل مستأجر مخصص. كلاهما يعمل في وضع المعاملة. - يظل PostgREST وتجمع الإدارة
aura-dbطوعًا على اتصال مباشر بـ Postgres، دون المرور عبر المجمع: سيؤدي تجميع المعاملات إلى كسر إعادة تحميل المخطط وأقفال الجلسة الخاصة بهم.
ثلاثة مجمعات، ثلاث فلسفات
يعمل PgBouncer على تقليل تجمعات Supavisor على نطاق متعدد المستأجرين، ويضيف PgCat وظائف الشبكة إلى التجميع الأولي. لا يعد أي من الثلاثة بديلاً مباشرًا للاثنين الآخرين، على الرغم من أنه غالبًا ما تتم مقارنتهما بمصطلح بمصطلح في نفس الصفحات.
| اللغة | C | إكسير (شعاع) | الصدأ |
|---|---|---|---|
| أوضاع التجميع | الجلسة، المعاملة، البيان | جلسة، معاملة | الجلسة، المعاملة، البيان |
| نموذج الإيجار | مجموعة مستهدفة واحدة لكل مثيل، مصممة لتكون مستأجرًا واحدًا | مستأجر متعدد أصلي: خدمة للعديد من قواعد البيانات | مجموعة مستهدفة، مقسمة بواسطة مفتاح القسم |
| أبعد من التجميع | لا توجد وظائف إضافية، الحد الأدنى عمدا | واجهة برمجة تطبيقات HTTP للمسؤول، تسجيل المستأجر الديناميكي | المشاركة وموازنة التحميل وتجاوز الفشل بين النسخ المتماثلة |
| تكامل Kubernetes الأصلي | نعم: مُجمّع موارد CloudNativePG | لم يتم توثيقه أصلاً حتى الآن | لم يتم توثيقه أصلاً حتى الآن |
| الأصل | المعيار التاريخي لتجميع Postgres | تم إنشاؤها بواسطة Supabase لسحابتها الخاصة متعددة المستأجرين | وُلد في Instacart، وتتم صيانته اليوم بواسطة PostgresML |
الأعمدة بالترتيب: PgBouncer، Supavisor، PgCat. خصائص البنية وفقًا للملفات الرسمية لكل مشروع، والتي سيتم تأكيدها في الإصدار الذي تقوم بنشره، يتطور النظام البيئي بسرعة في هذه المرحلة.
المعيار التاريخي، خفيف الوزن ومدمج في Kubernetes
يقوم PgBouncer بشيء واحد فقط: تجميع اتصالات Postgres، دون أي وظائف إضافية. يفسر هذا النطاق الضيق بشكل متعمد إلى حد كبير طول عمره واعتماده كوحدة بناء أساسية في معظم مجموعات Postgres في الإنتاج.
تتوفر ثلاثة أوضاع للتجميع. يفتح وضع الجلسة اتصال خادم واحد لكل اتصال عميل، وهو الأكثر سماحًا. يعيد وضع المعاملة استخدام اتصال الخادم بين العديد من العملاء، والذي يتم إصداره في نهاية كل معاملة. يذهب وضع البيان إلى أبعد من ذلك، ونادرا ما يستخدم في الإنتاج. إن وضع المعاملة هو الذي يحقق مكاسب التجميع الحقيقية، ولكنه يفرض قواعد صارمة. أي حالة جلسة (SETمتغيرات، أقفال استشارية، LISTEN/NOTIFY) لا تبقى بعد المعاملة. قمنا بتفصيل هذه القواعد ومزالقها في مقالتنا المخصصة حول وضع تجميع المعاملات الخاص بـ PgBouncer.
من الناحية التاريخية، تستخدم عملية واحدة، مثيل PgBouncer نواة وحدة المعالجة المركزية (CPU) واحدة بشكل افتراضي. يعد تشغيل مثيلات متعددة خلف نفس المنفذ (عبر SO_REUSEPORT) تطورًا أحدث للمشروع، وليس ميزة تصميم أولية. من ناحية المصادقة، يدعم PgBouncer وظيفة auth_queryالقابلة للتكوين، وهي وظيفة SQL يتم تنفيذها عند كل اتصال لحل كلمة مرور الدور ديناميكيًا. تتجنب هذه الآلية الاعتماد على ملف ثابت يسرد كل مستخدم مقدمًا. وهذه هي بالضبط الآلية التي تستخدمها Aurabase لأدوارها لكل مشروع (القسم 05).
PgBouncer هو المُجمّع الذي ينشره CloudNativePG أصلاً خلف مورده Pooler. في مجموعة Postgres التي يديرها مشغل CloudNativePG، يؤدي تنشيط مجمع مُدار إلى تنشيط PgBouncer دون تكوينه يدويًا.
مجمع Supabase السحابي الأصلي متعدد المستأجرين
يعالج Supavisor مشكلة لم يتم تصميم PgBouncer لحلها على هذا النطاق. يتضمن ذلك خدمة عدد كبير جدًا من قواعد بيانات المستأجرين المميزة من خدمة واحدة، بدلاً من مثيل مجمّع واحد لكل قاعدة بيانات. تمت كتابة المشروع بلغة Elixir وتم تنفيذه على جهاز Erlang الظاهري (BEAM)، وتم تطوير المشروع وصيانته بواسطة Supabase، في مصدر مفتوح، على مستودع GitHub الخاص بها.
النموذج الأصلي متعدد المستأجرين هو الفرق الهيكلي الحقيقي. حيث يتطلب أسطول PgBouncer الكلاسيكي عملية واحدة (أو مجموعة من الاتصالات المخصصة) لكل قاعدة مستهدفة، فإن Supavisor يعمل بشكل مختلف. فهو يسجل المستأجرين ديناميكيًا عبر واجهة إدارة HTTP، ويوجه كل اتصال وارد إلى قاعدة البيانات الصحيحة دون إعادة تشغيل الخدمة. قامت Supabase بترحيل مشاريعها السحابية الخاصة من PgBouncer إلى Supavisor لهذا السبب بالذات. لا يمكن توسيع مجموعة التجميع الكلاسيكية، واحدة لكل قاعدة بيانات، إلى سحابة متعددة المستأجرين تستضيف مئات الآلاف من المشاريع.
هذا الاختيار المعماري له جانب سلبي موثق. استغرق تكافؤ الميزات مع PgBouncer في الحالات المتقدمة بعض الوقت حتى يستقر بعد إطلاق المشروع. مثالان: سلوكيات معينة لـ LISTEN/NOTIFYوالإدارة الدقيقة للبيانات المعدة في وضع المعاملة. تحقق من الإصدار الخاص بك قبل الترحيل إذا كان تطبيقك يعتمد على هذه السلوكيات المحددة.
الصدأ الخارجي: المشاركة الأصلية وموازنة التحميل
تم وضع PgCat بشكل واضح كبديل لـ PgBouncer، المكتوب بلغة Rust. فهو يضيف وظائف الشبكة إلى التجميع الكلاسيكي الذي لا يقوم PgBouncer أو Supavisor بتضمينه أصلاً. ثلاثة على وجه الخصوص: تقسيم التطبيق عن طريق مفتاح القسم، وموازنة التحميل بين النسخ المتماثلة المقروءة، وتجاوز الفشل التلقائي بعيدًا عن النسخة المتماثلة الفاشلة. وُلد المشروع في Instacart قبل أن يتم الاستحواذ عليه وصيانته اليوم بواسطة PostgresML.
بشكل ملموس، يمكن لـ PgCat أن تلعب الدور الذي تشغله عادةً طبقتان مختلفتان: مُجمّع الاتصال ووكيل التطبيق للتوجيه بين العديد من مثيلات Postgres. يمكن للفريق الذي كان يشارك بياناته يدويًا بالفعل تبسيط التعليمات البرمجية الخاصة به باستخدام PgCat. نفس الشيء بالنسبة لمنطق توزيع القراءات بين النسخ المتماثلة التي تم تطويرها داخليًا: تحل طبقة الشبكة المخصصة محلها مباشرة.
يوجد أيضًا حل وسط معاكس: PgCat هو مشروع أحدث، مع نظام بيئي أصغر بكثير من التوثيق وردود الفعل على الإنتاج من PgBouncer. إن اعتماد وظائف التقسيم وتجاوز الفشل يعني أيضًا الموافقة على الاعتماد على نضج هذا المكون المحدد، وليس فقط على قدرته التجميعية.
ما يظهره كود Aurabase: PgBouncer في كل مكان، باستثناء الأماكن التي يؤدي فيها تجميع المعاملات إلى كسر كل شيء
ينشر مستودع Aurabase PgBouncer في مستويين منفصلين، كلاهما في وضع المعاملة. بالنسبة للأسطول المشترك، يحدد مخطط Helm عملية نشر PgBouncer مخصصة أمام مستوى البيانات المشترك (deploy/helm/aurabase/templates/infra/pgbouncer.yaml، الصورة edoburu/pgbouncer). بالنسبة للمستأجر في مثيل مخصص، يقوم الموفر بإنشاء مورد Pooler تتم إدارته أصلاً بواسطة CloudNativePG (deploy/cnpg/tenant-pooler.yaml، يتم تقديمه بواسطة k8s_tenant.rs). لا يستخدم أي منهما Supavisor أو PgCat. لا يوثق الكود مقارنة صريحة سبقت هذا الاختيار. من ناحية أخرى، فإنه يُظهر تكاملًا عميقًا وتشغيليًا بالفعل مع النظام البيئي CloudNativePG، بما يتوافق مع حقيقة أن PgBouncer هو لبنة التجميع الأصلية.
ومع ذلك، لا يمر كل شيء عبر المجمع، وهذا اختيار متعمد موثق في الكود نفسه. يظل PostgREST متصلاً مباشرةً بـ Postgres، وليس عبر PgBouncer أبدًا. تعليق مخطط Helm واضح بشأن السبب: قد يؤدي تجميع المعاملات إلى تعطيل إعادة تحميل المخطط الخاص به، والذي يعتمد على LISTEN على القناة pgrst. هذه الآلية غير متوافقة مع اتصالات الخادم المعاد تدويرها بين العملاء. يظل تجمع الإدارةaura-db (المخطط، DDL، الأقفال الاستشارية للجلسة) أيضًا على اتصال مباشر، لنفس السبب الأساسي. لا ينجو SET search_path وتأمين الجلسة الذي لا يشمل نطاق المعاملة من مجمع وضع المعاملة.
تتبع المصادقة نمط auth_query الموضح في القسم 02: AUTH_QUERY: SELECT * FROM pgbouncer.user_lookup($1)، بدون ملف userlist.txt ثابت. هذا هو ما يسمح للأدوار التي تم إنشاؤها ديناميكيًا لكل مشروع (project_<uuid>_authenticator) بالمصادقة عبر PgBouncer دون إعادة نشر المجمع لكل مشروع جديد.
يُظهر تعليق PgBouncer healthcheck في Kubernetes المحلي وجود خطأ حقيقي، تم إصلاحه بالفعل. يؤدي تشغيل pg_isready مقابل PgBouncer إلى التحقق من صحة مصافحة الوكيل فقط، وليس الاتصال الفعلي بالواجهة الخلفية لـ Postgres مطلقًا. يستجيب PgBouncer "لقبول الاتصالات" حتى عندما تكون الواجهة الخلفية متوقفة، مما يؤدي إلى وضع الطلبات في قائمة الانتظار. النتيجة التي تمت ملاحظتها أثناء الاختبار المدمر: ظلت الخدمة healthy لمدة 5 دورات متتالية بينما كان Postgres غير قابل للوصول. يستبدل الإصلاح عملية التحقق بطلب حقيقي شامل psql من خلال المجمع، وصولاً إلى الواجهة الخلفية. النتيجة بعد التصحيح، في نفس الاختبار المعاد: unhealthy تم اكتشافه في 7 دورات، حوالي 35 ثانية.
تفصيل أخير، بسيط ولكنه كاشف: دبابيس مخطط Helm edoburu/pgbouncer:v1.24.1-p1 افتراضيًا، بينما يستخدم مقعد k3d المحلي v1.25.2-p0. إنه ليس خيارًا معماريًا، بل مجرد نقص طفيف في مزامنة الإصدار بين بيئتين، وهو نوع التفاصيل التي تلتقطها مراجعة التعليمات البرمجية بشكل أسرع من منشور المدونة. نحن نوثقها كما هي بدلاً من تلبيسها. للحصول على تفاصيل حول تقسيم المخطط الذي يخدمه هذا المجمع، راجع مقالتنا حولعزل RLS متعدد المستأجرين.
كيفية الاختيار بين الثلاثة
اختر PgBouncer إذا...
- مجموعة Postgres مُدارة بواسطة CloudNativePG أو Kubernetes بشكل عام
- تريد المجمع الأكثر إثباتًا وتوثيقًا
- القاعدة المستهدفة لكل مثيل من أدوات التجميع تناسبك
اختر Supavisor إذا...
- مئات أو آلاف القواعد وراء نفس الخدمة
- تحتاج إلى تسجيل المستأجرين ديناميكيًا عبر واجهة برمجة التطبيقات (API)، دون إعادة التوزيع
- موجود بالفعل في نظام Supabase البيئي أو يرغب في الاعتماد عليه
اختر PgCat إذا...
- مشاركة التطبيقات موجودة بالفعل أو مخطط لها على مستوى المجمع
- موازنة التحميل والنسخ المتماثل لتجاوز الفشل بدون طبقة تطبيق منفصلة
- مريح مع مشروع أصغر سنًا وأقل توثيقًا من PgBouncer
مهما كان المجمع الذي تم اختياره، فهو لا يحل محل حجم Postgres نفسه. يجب التفكير في حجم التجمع والخادم max_connections معًا، وليس واحدًا تلو الآخر. يؤدي وجود حوض سباحة كبير أمام max_connections منخفض جدًا إلى تحويل التشبع من مستوى إلى آخر. دليلنا حول ضبط max_connections يوضح تفاصيل صيغة التحجيم التي يجب تطبيقها قبل تحديد حجم حمام السباحة الخاص بك.
ما نسأل عنه في أغلب الأحيان
لا يوجد مجمع عالمي، فقط ما يناسب إيجارك
تعمل PgBouncer وSupavisor وPgCat على حل ثلاثة أشكال مختلفة لنفس المشكلة، وليس ثلاثة إصدارات من نفس الأداة. يظل PgBouncer هو الخيار الأكثر أمانًا عندما تعتمد منصتك بالفعل على Kubernetes وCloudNativePG، أو عندما تريد ببساطة المجمع الأكثر توثيقًا. يصبح Supavisor ذا صلة بما يتجاوز عددًا معينًا من القواعد التي تخدم نفس الخدمة. يستحق PgCat الانعطاف إذا فاتك التقسيم وتجاوز فشل النسخ المتماثلة على مستوى الشبكة، بشرط قبول نضج المشروع الأصغر سنًا.
يُظهر رمز Aurabase خيارًا متسقًا وغير محايد: PgBouncer في وضع المعاملة، على مستويين، وأسطول مشترك ومجمع CNPG لكل مستأجر مخصص. يبقى هناك استثناءان موثقان، لـ PostgREST ولإدارة المخطط. إذا كنت تريد رؤية هذا المشروع منعزلاً على أرض الواقع وليس على الورق، فإن صفحة الأداء توثق منهجية القياس المرتبطة.