Veritabanı yöneticilerinin kabusu nedir diye sorsanız, muhtemelen “tek nokta başarısızlığı” derler. Production ortamında çalışan bir PostgreSQL sunucusu çöktüğünde, yedeği geri yüklemek saatler alabilir ve bu sürede iş durur. İşte streaming replication tam bu sorunu çözmek için var. Gerçek zamanlı veri replikasyonu ile primary sunucunuz çöktüğünde standby sunucunuz saniyeler içinde devreye girebilir.
Bu yazıda PostgreSQL streaming replication’ı sıfırdan kuracağız. İki sunucu senaryosu üzerinden gideceğiz, adım adım yapılandıracağız ve olası hataları da ele alacağız.
Ortam ve Gereksinimler
Kurulumu şu senaryo üzerinden yapacağız:
- Primary sunucu: 192.168.1.10 (pg-primary)
- Standby sunucu: 192.168.1.20 (pg-standby)
- PostgreSQL sürümü: 15.x
- İşletim sistemi: Ubuntu 22.04 LTS
Her iki sunucuda da PostgreSQL kurulu olduğunu varsayıyorum. Kurulu değilse şu şekilde kurabilirsiniz:
# Ubuntu/Debian için
sudo apt update
sudo apt install -y postgresql-15 postgresql-client-15
# PostgreSQL servisini başlat
sudo systemctl enable postgresql
sudo systemctl start postgresql
Streaming replication, PostgreSQL’in WAL (Write-Ahead Log) mekanizmasını kullanır. Primary sunucu WAL kayıtlarını üretir, standby sunucu bu kayıtları alır ve uygular. Sonuç olarak standby, primary ile neredeyse eş zamanlı olarak senkronize kalır.
Primary Sunucu Yapılandırması
postgresql.conf Düzenlemeleri
Primary sunucuda önce postgresql.conf dosyasını düzenlememiz gerekiyor. Bu dosya genellikle /etc/postgresql/15/main/postgresql.conf konumundadır.
sudo nano /etc/postgresql/15/main/postgresql.conf
Aşağıdaki parametreleri bulun ve düzenleyin:
# WAL ayarları
wal_level = replica
max_wal_senders = 5
wal_keep_size = 1GB
max_replication_slots = 5
# Arşivleme (opsiyonel ama önerilen)
archive_mode = on
archive_command = 'cp %p /var/lib/postgresql/wal_archive/%f'
# Bağlantı ayarları
listen_addresses = '*'
Parametrelerin ne işe yaradığını açıklayalım:
- wal_level:
replicaolarak ayarlandığında WAL, streaming replication için yeterli bilgiyi içerir - max_wal_senders: Aynı anda kaç standby sunucunun bağlanabileceğini belirler
- wal_keep_size: Primary’de tutulacak WAL miktarı, standby geride kalırsa bu sayede yakalayabilir
- max_replication_slots: Replication slot sayısı, standby sunucu koptuğunda WAL’ların silinmesini engeller
- archive_mode: WAL arşivlemeyi aktif eder
- listen_addresses: Tüm arayüzlerden bağlantı kabul et
pg_hba.conf Düzenlemeleri
Standby sunucunun bağlanabilmesi için erişim izni vermemiz gerekiyor:
sudo nano /etc/postgresql/15/main/pg_hba.conf
Dosyanın sonuna şu satırı ekleyin:
# Streaming replication için standby erişimi
host replication replicator 192.168.1.20/32 scram-sha-256
Bu satır, 192.168.1.20 adresinden replicator kullanıcısının replication bağlantısı kurmasına izin verir.
Replication Kullanıcısı Oluşturma
Primary sunucuda PostgreSQL’e bağlanarak replikasyon kullanıcısını oluşturun:
sudo -u postgres psql
-- Replication kullanıcısı oluştur
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'guclu_bir_sifre_koy';
-- Kullanıcıyı kontrol et
du replicator
-- Çıkış
q
WAL Arşiv Dizinini Oluşturma
Arşivlemeyi aktif ettiyseniz dizini oluşturmanız gerekiyor:
sudo mkdir -p /var/lib/postgresql/wal_archive
sudo chown postgres:postgres /var/lib/postgresql/wal_archive
sudo chmod 700 /var/lib/postgresql/wal_archive
Primary Sunucuyu Yeniden Başlatma
Yapılandırma değişikliklerini uygulamak için PostgreSQL’i yeniden başlatın:
sudo systemctl restart postgresql
# Servis durumunu kontrol et
sudo systemctl status postgresql
# Logları kontrol et
sudo tail -f /var/log/postgresql/postgresql-15-main.log
Standby Sunucu Yapılandırması
pg_basebackup ile İlk Veri Kopyası
Standby sunucuyu kurmadan önce, primary sunucunun mevcut veri dizininin tam bir kopyasını almamız gerekiyor. pg_basebackup bu iş için biçilmiş kaftan.
Standby sunucuda önce mevcut veri dizinini temizleyelim:
# Standby üzerinde PostgreSQL'i durdur
sudo systemctl stop postgresql
# Mevcut veri dizinini yedekle veya sil
sudo -u postgres mv /var/lib/postgresql/15/main /var/lib/postgresql/15/main.bak
# pg_basebackup ile primary'den veri al
sudo -u postgres pg_basebackup
-h 192.168.1.10
-U replicator
-p 5432
-D /var/lib/postgresql/15/main
-Fp
-Xs
-P
-R
Bu komutun parametrelerine bakalım:
- -h: Primary sunucunun IP adresi
- -U: Kullanıcı adı (oluşturduğumuz replicator)
- -p: Port numarası
- -D: Hedef dizin
- -Fp: Format plain, dizin yapısını olduğu gibi kopyalar
- -Xs: WAL’ları stream yöntemiyle kopyalar
- -P: İlerleme çubuğu göster
- -R:
standby.signaldosyasını vepostgresql.auto.confbağlantı bilgilerini otomatik oluşturur
Komut çalışırken şifre sorulacak, guclu_bir_sifre_koy girip devam edin. Veritabanı büyüklüğüne göre bu işlem biraz zaman alabilir.
Standby postgresql.conf Düzenlemeleri
pg_basebackup -R parametresi sayesinde postgresql.auto.conf dosyası otomatik oluşturuldu. Ama biraz daha ince ayar yapalım:
sudo nano /var/lib/postgresql/15/main/postgresql.conf
# Standby özel ayarları
hot_standby = on
hot_standby_feedback = on
primary_conninfo = 'host=192.168.1.10 port=5432 user=replicator password=guclu_bir_sifre_koy application_name=pg-standby'
# Recovery hedef
recovery_target_timeline = 'latest'
Parametreler:
- hot_standby: Standby üzerinde sadece okuma sorgularına izin verir, bu süper kullanışlı
- hot_standby_feedback: Standby’ın hangi satırları okuduğunu primary’ye bildirir, vacuum conflict’ini önler
- primary_conninfo: Primary sunucuya bağlantı bilgisi
- recovery_target_timeline: Failover sonrası yeni timeline’ı otomatik takip et
standby.signal Dosyasını Kontrol Et
pg_basebackup -R parametresi bu dosyayı zaten oluşturdu, ama kontrol edelim:
ls -la /var/lib/postgresql/15/main/standby.signal
Dosya varsa PostgreSQL bu sunucunun bir standby olduğunu anlıyor. Yoksa manuel oluşturun:
sudo -u postgres touch /var/lib/postgresql/15/main/standby.signal
Standby Sunucuyu Başlatma
sudo systemctl start postgresql
# Durum kontrolü
sudo systemctl status postgresql
# Logları izle
sudo tail -f /var/log/postgresql/postgresql-15-main.log
Logda şuna benzer bir mesaj görmelisiniz:
LOG: started streaming WAL from primary at 0/3000000 on timeline 1
Bu mesaj, replikasyonun başarıyla kurulduğunu gösteriyor.
Replikasyonun Doğrulanması
Primary Tarafında Kontrol
Primary sunucuda replikasyon durumunu sorgulamak için:
sudo -u postgres psql -c "SELECT * FROM pg_stat_replication;"
Beklenen çıktı şöyle görünmeli:
pid | usesysid | usename | application_name | client_addr | ...
------+----------+------------+------------------+--------------+----
1234 | 16384 | replicator | pg-standby | 192.168.1.20 | ...
Daha detaylı bilgi için:
sudo -u postgres psql -c "
SELECT
client_addr,
application_name,
state,
sent_lsn,
write_lsn,
flush_lsn,
replay_lsn,
sync_state,
pg_size_pretty(pg_wal_lsn_diff(sent_lsn, replay_lsn)) AS replication_lag
FROM pg_stat_replication;
"
replication_lag sütununda 0 bytes veya çok küçük bir değer görüyorsanız replikasyon sağlıklı çalışıyor demektir.
Standby Tarafında Kontrol
sudo -u postgres psql -c "SELECT * FROM pg_stat_wal_receiver;"
# Standby'ın recovery modunda olup olmadığını kontrol et
sudo -u postgres psql -c "SELECT pg_is_in_recovery();"
Bu sorgu t (true) döndürüyorsa, sunucu standby modunda çalışıyor.
Pratik Test
En güzel test, gerçek veri yazıp standby’da görmek:
# Primary'de test veritabanı ve tablo oluştur
sudo -u postgres psql
CREATE DATABASE replication_test;
c replication_test
CREATE TABLE test_table (id SERIAL PRIMARY KEY, message TEXT, created_at TIMESTAMP DEFAULT NOW());
INSERT INTO test_table (message) VALUES ('Replikasyon calisiyor mu?');
INSERT INTO test_table (message) VALUES ('Umarim calisiyor!');
q
Birkaç saniye bekleyip standby’da kontrol edin:
# Standby üzerinde
sudo -u postgres psql -c "SELECT * FROM replication_test.test_table;" replication_test
Verileri görüyorsanız her şey mükemmel çalışıyor!
Replication Slot Kullanımı
Replication slot, standby sunucu bağlantısı koptuğunda bile WAL dosyalarının silinmesini engelleyen bir mekanizma. Özellikle ağ kesintileri için çok önemli.
Primary üzerinde slot oluşturun:
sudo -u postgres psql -c "
SELECT pg_create_physical_replication_slot('standby_slot');
"
# Mevcut slotları listele
sudo -u postgres psql -c "SELECT * FROM pg_replication_slots;"
Standby’ın bu slotu kullanması için postgresql.conf dosyasını güncelleyin:
primary_slot_name = 'standby_slot'
Değişikliği uygulamak için PostgreSQL’i yeniden başlatın:
sudo systemctl restart postgresql
Dikkat: Replication slot kullanırken standby uzun süre kapalı kalırsa, primary’nin disk dolabilir çünkü WAL dosyaları birikmaya devam eder. wal_keep_size parametresini ve disk kullanımını düzenli izleyin.
Monitoring ve İzleme
Replikasyonu sürekli izlemek için basit bir script yazalım:
#!/bin/bash
# /usr/local/bin/check_replication.sh
PRIMARY="192.168.1.10"
PGUSER="postgres"
echo "=== Replication Durumu: $(date) ==="
# Primary'de çalışıyorsa
if sudo -u postgres psql -h $PRIMARY -c "SELECT 1" > /dev/null 2>&1; then
echo "Primary sunucu: ONLINE"
echo ""
echo "Aktif standby bağlantıları:"
sudo -u postgres psql -h $PRIMARY -c "
SELECT
application_name,
client_addr,
state,
sync_state,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)) AS lag
FROM pg_stat_replication;
"
else
echo "UYARI: Primary sunucuya erişilemiyor!"
fi
echo ""
echo "Replication slot durumu:"
sudo -u postgres psql -h $PRIMARY -c "
SELECT slot_name, active, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained_wal
FROM pg_replication_slots;
"
Script’i çalıştırılabilir yapın:
sudo chmod +x /usr/local/bin/check_replication.sh
# Cron ile her 5 dakikada bir çalıştır
echo "*/5 * * * * root /usr/local/bin/check_replication.sh >> /var/log/replication_check.log 2>&1" | sudo tee -a /etc/cron.d/replication_monitor
Senkron Replikasyon (Opsiyonel)
Varsayılan olarak PostgreSQL asenkron replikasyon yapar. Yani primary, commit işlemini standby’ın onayını beklemeden tamamlar. Bu performans açısından iyidir ama failover anında birkaç transaction kaybedilebilir.
Sıfır veri kaybı istiyorsanız senkron replikasyona geçebilirsiniz:
# Primary postgresql.conf
synchronous_standby_names = 'FIRST 1 (pg-standby)'
synchronous_commit = on
Uyarı: Senkron replikasyon performansı belirgin şekilde düşürür. Primary, her commit için standby’ın onayını bekler. Standby sunucu kapalıysa tüm yazma işlemleri bloke olur! Bunu yalnızca kritik veritabanlarında kullanın.
Yaygın Hatalar ve Çözümleri
“could not connect to the primary server”
# Önce ağ bağlantısını kontrol et
ping 192.168.1.10
telnet 192.168.1.10 5432
# pg_hba.conf'ta izin verildi mi?
sudo grep replication /etc/postgresql/15/main/pg_hba.conf
# PostgreSQL firewall kuralı var mı?
sudo ufw status
sudo ufw allow from 192.168.1.20 to any port 5432
“FATAL: could not open file base/…”
Bu hata genellikle pg_basebackup sırasında veri bütünlüğü sorunu yaşandığında olur:
# Standby veri dizinini temizleyip pg_basebackup'ı tekrar çalıştır
sudo systemctl stop postgresql
sudo -u postgres rm -rf /var/lib/postgresql/15/main/*
sudo -u postgres pg_basebackup -h 192.168.1.10 -U replicator -D /var/lib/postgresql/15/main -Fp -Xs -P -R
sudo systemctl start postgresql
Replikasyon Gecikmesi Yüksek
# WAL sender/receiver istatistiklerini kontrol et
sudo -u postgres psql -c "SELECT * FROM pg_stat_wal_receiver;" # Standby'da
# Network bant genişliğini kontrol et
iftop -i eth0
# wal_keep_size'ı artır
sudo -u postgres psql -c "ALTER SYSTEM SET wal_keep_size = '2GB';"
sudo -u postgres psql -c "SELECT pg_reload_conf();"
Failover Senaryosu
Primary sunucu çöktüğünde standby’ı promote etmek için:
# Standby sunucuda - PostgreSQL 12+ için
sudo -u postgres pg_ctl promote -D /var/lib/postgresql/15/main
# veya pg_promote() fonksiyonu ile
sudo -u postgres psql -c "SELECT pg_promote();"
Promote sonrası standby standby.signal dosyasını siler ve primary rolüne geçer. Bu noktada artık yazma işlemleri kabul etmeye başlar.
Uygulama bağlantılarını yeni primary’ye yönlendirmeyi unutmayın. Bunun için HAProxy veya Patroni gibi araçlar işinizi çok kolaylaştırır, ama bu konuyu ayrı bir yazıda ele alacağız.
Sonuç
PostgreSQL streaming replication kurmak düşündüğünüzden çok daha az karmaşık. Özetlemek gerekirse şu adımları izledik:
- Primary’de WAL level’ı
replicaolarak ayarladık ve replication kullanıcısı oluşturduk pg_hba.confile standby erişimine izin verdikpg_basebackupile standby’ı başlangıç verisiyle doldurduk- Standby’da
hot_standbyve bağlantı bilgilerini yapılandırdık pg_stat_replicationile sağlık kontrolü yaptık- Replication slot ile WAL güvenliğini artırdık
Replikasyon kurulumu sonrası yapmanız gereken en önemli şey, düzenli failover testi yapmak. Çoğu ekip replikasyonu kurar, çalıştığını görür ve bir daha test etmez. Ta ki gerçek bir disaster yaşayana kadar. Ayda bir kez planlı bir failover testi yapın, prosedürlerinizi belgeleyin ve ekibinizi bu süreçte eğitin.
Bir sonraki adım olarak Patroni ile otomatik failover veya pgBouncer ile bağlantı havuzlama konularına bakabilirsiniz. Ama temeli sağlam attıysanız, bu araçları entegre etmek de o kadar zor olmayacak.