Switchover, Primary ve Standby sunucularımızın rollerini değiştirmesi işlemidir. Switchover işlemi primary sunucusuna bakım gereksiniminden dolayı olabileceği gibi veritabanınızın çalıştığı sunucuyu en az kesinti ile değiştirmek için de kullanılabilir.

PostgreSQL, primary’deki bir arızayı tanımlamak ve standby veritabanı sunucusunu bilgilendirmek için gerekli olan sistem yazılımını sağlamaz. Farklı yüksek erişilebilirlik çözümleri bu işlemleri sizin için otomatik yapabileceği gibi bu işlemi elle de gerçekleştirebilirsiniz. Birçok yük devretme sistemi, ikisi arasındaki bağlantıyı ve primary sunucunun kullanılabilirliğini sürekli olarak doğrulamak için bir tür heartbeat mekanizması kullanır veya gereksiz yük devretme durumlarını önlemek için üçüncü bir sistem (witness server olarak da adlandırılır) kullanmak da mümkündür, ancak yeterli özen ve titiz testlerle kurulmadıkça yapıyı karmaşıklaştırmak kaş yapayım derken göz çıkarma gibi bir şey olur. (Sonunda bir deyimi tam yerinde kullanabildim 🙂 )

Standby’ı yeni primary olarak tanıtmanın iki yolu vardır. Switchover, değişimin planlı bir şekilde gerçekleşmesidir. Biz bu yazımızda switchover işlemini manuel yapacağız; Kabaca aşağıdaki adımların işletilmesi ile rol değiştirme işlemi gerçekleştirilebilir.

  1. Veritabanına yeni veri gelmesini engelemmek için tüm client bağlantıları kesilir.
  2. WAL kayıtlarının standby lara aktarılması beklenip, onaylanır.
  3. Primary sucunu temiz bir şekilde kapatılır.
  4. Standby sunucu kontrol edilerek primary haline getirilir.
  5. Eski primary sunucusu uygun yapılandırma ile Stanby olarak açılır.

Adımlar doğru bir şekilde gerçekleştirilmediği taktirde eski Primary sunucusu yeni Primary’e Standby olarak bağlanamayacaktır. Bu durumda replikasyonu yeniden başlatabilmek için yedekten dönmemiz gerekebilir yada aradaki farkı bulup işlemek için pg_rewind aracından yararlanabiliriz.

pg_rewind : pg_rewind, 9.5 sürümünden beri bir PostgreSQL aracıdır. Özellikle pg_rewind büyük veritabanları için avantaj sağlar. Veritabanlarını pg_basebackup kullanmadan senkronize edebilirsiniz. pg_rewind, eski primary veritabanının pgdata klasörünü tarar ve standby sunucusuna geçiş sırasında değiştirilen veri bloklarını tanımlar, ardından yalnızca ilişki dosyalarından değiştirilen blokları kopyalar; diğer tüm dosyalar, yükseltilmiş standby sunucudaki yapılandırma dosyaları dahil tam olarak kopyalanır. Ve eski primary veritabanı, değiştirilen blokların uygulanmasıyla senkronize olur. pg_rewind, hedef sunucunun postgresql.conf içinde wal_log_hints seçeneğinin etkinleştirilmesini veya veritabanı initdb ile başlatıldığında checksums etkinleştirilmesini gerektirir. full_page_writes da açık olarak ayarlanmalıdır, ancak varsayılan olarak etkindir.

NOT : Failover yukarıdaki ilk 3 adım gerçekleştirilemediğinde gerçekleşir, çünkü genellikle primary sunucuya ulaşılamaz veya kullanılamaz durumdadırlar. İşte burada en büyük sıkıntı eğer senkron (synchronous_standby_names) bir standby’ınız yoksa veri kaybı olma ihtimali.

Şimdi bir örnek yapacak olursak;

Aradaki fark çok fazla değilse birinci ve ikinci adımı atlayıp üçüncü adımdan başlayabiliriz, çünkü primary sunucu temiz bir şekilde kapatıldığında (fast veya smart) walsender süreci henüz replika sunucuya iletmediği son işlem kayıtlarını (wal) ileterek kapanacaktır.

pg_ctl -D /var/lib/pgsql/12/data/ stop -m fast

Standby sunucusunu Primary olarak ayağa kaldırmadan önce (promote) senkronizasyon durumunu(daha doğrusu standby gelen wal kayıtlarının işlenip işlenmediği bilgisini) aşağıdaki sorgu ile kontrol edilebilir.

postgres=# SELECT pg_last_wal_receive_lsn(),pg_last_wal_replay_lsn();
-[ RECORD 1 ]-----------+-----------
pg_last_wal_receive_lsn | 0/35290B60
pg_last_wal_replay_lsn  | 0/35290B60

replay ve receive değerlerinin aynı olduğu görüldüğünde artık yeni Primary aktif edilebilir. Bunun üç farklı yolu var.

pg_ctl -D /var/lib/pgsql/12/data/ promote
waiting for server to promote.... done
server promoted

veya aşağıdaki komutla pg_promote fonksiyonunuda kullanabiliriz;

select pg_promote();

veya promote_trigger_file parametresine bir path ve dosya gösteririz, bu dosyanın içinde de switchover işlemlerini scriptize edebiliriz.

log dosyasına aşağıdaki gibi log kayıtları yazıldı.

2020-01-13 17:27:38.286 +03 [55065] LOG:  received promote request
2020-01-13 17:27:38.286 +03 [55065] LOG:  redo done at 0/35290AE8
2020-01-13 17:27:38.286 +03 [55065] LOG:  last completed transaction was at log time 2020-01-11 23:52:35.853684+03
2020-01-13 17:27:38.287 +03 [55065] LOG:  selected new timeline ID: 2
2020-01-13 17:27:38.359 +03 [55065] LOG:  archive recovery complete
2020-01-13 17:27:38.461 +03 [55062] LOG:  database system is ready to accept connections

Yeni Primary kontrol edildiğinde artık recovery modunda olmadığı görülebilir.

postgres=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 f
(1 row)

Eski primary sunucusunu Standby haline getirebilmek için postgresql.auto.conf dosyasının düzenlenmesi gerekiyor. Örnek yapılandırma dosyası aşağıdaki gibidir.

primary_conninfo = 'application_name=standby01 user=replicationuser password=112233ee host=192.168.10.106 port=5432 sslmode=prefer sslcompression=0 gssencmode=prefer krbsrvname=postgres target_session_attrs=any'
primary_slot_name = 'standby01'

NOT 1 : PostgreSQL 12’deki en önemli değişikliklerden biri, recovery.conf’un değiştirilmesi ve recovery.conf parametrelerinin normal PostgreSQL yapılandırma parametrelerine dönüştürülmesidir. Bu, ayrı bir yapılandırma dosyası ihtiyacını ortadan kaldırır ve replikasyonun ALTER SYSTEM komutu dahil olmak üzere diğer yapılandırma parametreleriyle aynı şekilde yapılandırılmasına olanak tanır.

NOT 2 : Parametreleri eski primary yani yeni standby’a göre düzenleriz.(host vb.)

NOT 3 : Eski primary standby.signal dosya oluşturulur. Postgresql.conf dosyasında hot_standby açıksa (varsayılan değer) ve standby.signal dosyası mevcutsa, sunucu Hot Standby modunda çalışacaktır. standby_signal sunucunun hedeflenen recovery modunda başlaması gerektiğini belirtir. Herhangi bir veri içermesine gerek yoktur; mevcut herhangi bir veri göz ardı edilecektir.

touch standby.signal

NOT 4 : pg_hba.conf dosyasını yeni yapıya uygun hale getirmemiz gerek.

NOT 5 : Slot kullanılacaksa yeni primary veritabanında slot oluşturmamız gerek.

SELECT pg_create_physical_replication_slot('standby01');
select * from pg_replication_slots ;

NOT 6 : Yeni primary sunucusu primary olarak ayağa kaldırıldığında timeline değişecektir ve yeni line daki primar’i yeni standby’ın izlemesi için recovery_target_timeline parametresinin ya yeni timeline’a işaret etmesi ya da en yeni timeline’ı takip etmesi için latest değeri verilmesi gereklidir. Aksi durumda loglarda hata alınacaktır. Postgres 12 sürümüyle bu değer varsayılan olarak latest gelmektedir.

recovery_target_timeline='latest'

Eski primary’nin, Standby olarak başlatmak için aşağıdaki komut işletilir.

pg_ctl -D /var/lib/pgsql/12/data/ start

Yeni Standby kontrol edildiğinde artık recovery modunda olduğu görülebilir.

postgres=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 t
(1 row)

Artık sunucular rolleri değiştirmiş, eski Eski primary artık yeni Standby, eski Standby da yeni primary olarak hizmet vermeye başlamıştır. Bu süreç Virtual IP taşınarak veya sunucuların IP adresleri değiştirilerek daha da güzel bir geçiş sağlanabilir. Bu sayede uygulamada herhangi bir değişikliğe gerek kalmadan uygulama düzeyinde süreç sadece kısa bir kesinti olarak hissedilebilir. Bu işlemi elle gerçekleştirmek yerine sizin yerinize bu işlemleri yapacak bir betik yazabilir veya yüksek erişilebilirlik çözümlerinden birini bu işlemleri sizin yerinize yapması için kullanabilirsiniz.

Mustafa Bektaş Tepe
İyi Çalışmalar

Loading