لو كل الـ dashboards بتاعتك بتفتح في 4.8 ثانية الساعة 9 الصبح، والسيرفر الواحد PostgreSQL بياكل CPU 92%، أنت مش محتاج تكبّر الـ instance. أنت محتاج تفصل القراءة عن الكتابة. Read Replica بتقفل المعادلة دي بدون ما تلمس سطر كود في التطبيق، وبتنزّل P95 من 480ms لـ 38ms على نفس التكلفة تقريبًا.
Read Replicas في PostgreSQL: لماذا instance واحد لا يكفي بعد 8K طلب/دقيقة
المشكلة باختصار
PostgreSQL الافتراضي بيشغّل process واحد لكل اتصال، والـ buffer pool واحد، والـ WAL writer واحد. لمّا تيجي 8K طلب/دقيقة بـ 70% منهم SELECT و 30% INSERT/UPDATE، الـ writes بتاخد lock على نفس الـ pages اللي الـ reads محتاجاها. النتيجة: queries بسيطة بتاخد 480ms لأن أنا بستنّى writes تخلص.
تخيّل المكتبة العامة (للمبتدئ)
تخيّل مكتبة عامة فيها 200 طالب جايين يستعيروا كتب، و 5 موظفين بيرتّبوا الرفوف ويسجّلوا كتب جديدة. الـ 200 طالب لازم يستنّوا لمّا الموظف يخلّص الترتيب علشان الرف ميتحركش وهم بيدوّروا. لو عملنا فرعين للمكتبة (نسخة من نفس الكتب) وقلنا "الفرع الأول للقراءة بس، الفرع التاني للموظفين والترتيب"، الـ 200 طالب يبقوا أحرار. ده اللي بيحصل بالظبط مع Read Replicas.
التعريف العلمي الدقيق
Read Replica في PostgreSQL هي instance ثانوي (Hot Standby) بتستقبل WAL stream (Write-Ahead Log) من الـ primary بشكل غير متزامن أو شبه متزامن، وتطبّق نفس التغييرات على نسختها من البيانات. الميكانيكية الرسمية اسمها Streaming Replication وموثّقة في PostgreSQL 16 Documentation – Chapter 27. الـ replica بترفض أي عملية كتابة برّيق cannot execute UPDATE in a read-only transaction، فالتطبيق بيعرف يوصلها للـ reads فقط بأمان.
الخطوات العملية: من Primary واحد إلى Primary + Replica
هنفترض إنك شغّال PostgreSQL 16 على Ubuntu 22.04، الـ primary على 10.0.0.5، والـ replica الجديدة على 10.0.0.6.
1) على الـ primary: اسمح بالـ replication
# /etc/postgresql/16/main/postgresql.conf
wal_level = replica
max_wal_senders = 10
wal_keep_size = 2GB
hot_standby = on
# /etc/postgresql/16/main/pg_hba.conf
host replication replicator 10.0.0.6/32 scram-sha-256