PostgreSQL-Pgbouncer Mimarisi ve Pgbouncer Performans Değişimleri
Merhabalar, bu yazımda biraz daha farklı bir konuyu çalışmaya gayret edeceğim. Bu yazıda, PostgreSQL veritabanı ortamlarında çoğunlukla kullandığımız HAProxy ve pgbouncer araçlarının hangi şartlarda nasıl performans verdiğini ve performans odaklı mimari tasarımlarında bu bileşenleri en doğru ve ihtiyaca en uygun nasıl kullanabileceğimizi inceleyeceğim.
Öncelikle, HAProxy aracını PostgreSQL yüksek erişilebilir sistemler tasarlarken sıkça kullanıyoruz ve doğru veritabanı sunucusuna yükün yönlendirilmesi bununla birlikte de read-only isteklerde de yükün farklı ihtiyaçlara göre load balance edilmesi işlerini yapıyoruz. Pgbouncer aracı ile de veritabanı sistemlerinde connection pooling yönetimini yapıyoruz.
PostgreSQL Yüksek Erişilebilir Mimari Örnekleri
İlk mimaride yani Mimari-1 olarak adlandırdığımız durumda, client’lar(istemciler) öncelikle HAProxy bileşenine erişmektedir. Sonrasında ise proxy uygun olan sunucuya isteği iletir. İstek önce pgbouncer’a gelir. Sonrasında veritabanına gider ve cevapta önce pgbouncer ardından proxy üzerinden geçerek istemciye iletilir.
İkinci mimaride ise, istemci doğrudan pgbouncer bileşenine erişir ve veritabanına inen istek pgbouncer üzerinden istemciye geri döner.
3. mimaride ise, istek proxy üzerinden doğrudan veritabanına iletilir ve istemciye yine proxy üzerinden yanıt gönderilir.
Görüldüğü üzere, aynı amaca ve ihtiyaca hizmet eden birden çok çözüm yada mimari tercih edilebilir. Ancak bu tercih edilirken sorulması ve düşünülmesi gereken birkaç nokta var. Bunlardan en önemlisi de performans olabilir. Çünkü bu mimarilerin birbirlerine üzerine belirli konularda üstünlükleri ve belirli konularda zayıflıkları ortaya çıkabilir. Bu çalışmada performans anlamındaki konuları inceleyeceğiz.
Pgbouncer Mimari Performans Karşılaştırmaları
Bu kısımda ise yukarıda bahsedilen mimarilerin performans anlamındaki karşılaştırmasını tamamlayacağız. Bu üç mimariyi de eşit şartlarda benchmark testine tabi tutacağız. Benchmark testi boyunca kullanılacak sabit değerler ise aşağıdaki gibidir.
- Veritabanı boyutu
- Benchmark sorguları
- Konfigürasyon(değişebilir)
Benchmark senaryosu için oluşturulan ortam ve kullanılan sorgular ise aşağıdaki gibidir.
-- vertiabanı oluşturulmasıCREATE DATABASE benchmark_demo;-- pgbench ile veritabanının populate edilmesipgbench -i -s 500 bench_demo
Buradaki -s argümanı veritabanın boyutunu belirler ve example ise hedef veritabanı ismini temsil eder.
Bu senaryoda birden fazla test senaryosu kullanılmıştır. Detayları aşağıda bulabilirsiniz ancak özetle, daha uzun sürelerde daha yüksek client sayısına maruz kalan mimariler kaynak tüketimi ve performansa göre karşılaştırılmıştır.
Çıkarımlar;
- pgbouncer’ın tek başına yükü karşıladığı mimaride sistemdeki kaynak tüketiminin daha az olduğu görüldü. Buradan aslında, pgbouncer ile daha az kaynak ile daha çok istek karşılamanın münkün olduğu ortaya çıkmıştır. Bu nedenle kaynak/performans konusunda pgbouncer doğrudan birincil erişim merkezi olabilir.
- Kısa süreli yüklerde (60 ve 120 saniye), 3 mimarinin de performans anlamında birbirinden çok farklı olmadıkları görülüyor. Ancak süre ve client sayısı arttıkça sadece pgbouncer ile çalışan mimarinin hem daha az kaynak tükettiği hem de daha performanslı çalıştığı görülmüştür.
Buradan çıkan sonuçlar ile, ikinci bir varyasyon denendi. Bu senaryoda ise, mimari-1 yapısındaki pgbouncer konfigürasyonları revize edildi. Buradaki temel motivasyon ise, daha küçük pool_size kullandığımızda kaynak tüketimi ve performansı ölçümlemekti.
Yukarıdaki değişkenler ile birlikte sadece pgbouncer’daki pool_size değeri değiştirildi. Bunun dışındaki tüm faktorler aynıdır. Bu 3 farklı varyasyona da aynı stres ve yük testi uygulandı.
Çıkarımlar;
- pgbouncer üzerinde daha küçük pool_size ile çalışmak doğrudan performans artışı ve kaynak tüketiminde azalmaya sebebiyet verebilir. Bu nedenle pool_size ayarını yüksek tutmadığımızdan ve optimize edilebileceğinden her zaman emin olmak gerekiyor.
- pgbouncer pool_size ayarını 3. denemedeki gibi çalıştığımız ortama göre “az” verdiğimizde kaynak tüketiminde gözle görülür bir düşüş olsada performans olarak bir miktar değişime (olumsuz anlamda) neden olabilir.
Aşağıdaki grafikte görüleceği üzere, aynı yük ve strese maruz kalan farklı pool_size değerine sahip 2 farklı pgbouncer çalışmasının CPU üzerindeki izdüşümü mevcut.
Tüm bu testler ve çıkarımlar sonrası aslında son bir kısım daha kalıyor. Bu ayarlara dikkat etmemiz yeterli mi ? Yeterli olmadığını düşündüğüm için bu çalışmayı INSERT işlemleri için de genişleteceğim. Buradaki amaç ise, INSERT sorgusunun büyüklüğüne göre aynı mimari ve konfigürasyona sahip pgbouncer üzerindeki performansı analiz edeceğiz.
Aşağıdaki benchmark için veritabanına yeni bir tablo ve 2farklı insert sorgusu hazırlanmıştır. Bu sorguların farkları aynı anda 10 ve 1000 satır INSERT etmeleri. Bir işlem içerisinde geçen verinin hacmi arttıkça nasıl farklar meydana geliyor onu inceleyeğiz.
Test ortamı için kullanılan bloklar aşağıdaki gibidir.
-- tablocreate table bench_table(id varchar not null,value varchar,created_date timestamp default CURRENT_TIMESTAMP not null,updated_date timestamp default CURRENT_TIMESTAMP not null)-- small insertINSERT INTO bench_table (id, value)SELECT x.id, 'article #' || x.idFROM generate_series(1,10) AS x(id);
-- mid insertINSERT INTO bench_table (id, value)SELECT x.id, 'article #' || x.idFROM generate_series(1,1000) AS x(id);
Çıkarımlar,
- Sorgunun içerisindeki verinin hacmi büyüdükçe pgbouncer gibi bir pooling bile olsa performans kaybı kaçınılmaz.
- Sorgunun içerisindeki verinin hacmi büyüdüğünde CPU tüketiminiz düşüş göstersede peformans ve disk üzerindeki yük olumsuz anlamda etkilenmektedir.
INSERT isteklerinde ise 3 farklı pool size ile yapılan benchmark sonucu aşağıdaki sonuçlar ortaya çıkmıştır.
Çıkarımlar,
- pgbouncer’da aynı scale’deki INSERT işlemleri için pool_size değerini arttırdıkça bol bol deadlock aldık. Bu nedenle de latency ve TPS değerleri düştü. pgbouncer pool_size değerini INSERT işlemleri arttırırken analiz etmek ve sonuçlara göre arttırmak gerek.
Pgbouncer Ölçeklenmesi ve Performans Karşılaştırmaları
Yazının bu bölümünde pgbouncer’ın ölçeklenmesi ile birlikte gelen gelişim noktalarını inceleyeceğiz. Özetle, birkaç farklı senaryo ve konfigürasyon ile benchmark testlerine devam edeceğiz.
Buradaki bölümde, 2 farklı konfigürasyon ve ölçekleme yöntemini kullanacağız. İlki, postgresql sunucusunun üzerinde kurgulanan bir ya da birden çok pgbouncer process’i çalışan düzen ikincisi ise ayrı sunucularda birden çok pgbouncer sunucusu ile çalışan düzen. Bu iki farklı yöntemin performans ve kaynak tüketimi konularında birbirine göre farklılığını analiz edeceğiz.
Grafiklerde ve sonuçlarda bahsi geçen modlar ve açıklamaları aşağıdaki gibidir.
local-bouncer: postgresql sunucusunun üzerinde pgbouncer’ın çalıştığı bouncer modu olarak adlandırılabilir.
multi-bouncer: pgbouncer servisinin postgresql sunucusundan farklı bir sunucuda çalıştığı bouncer modu olarak adlandırılabilir.
Buradaki sonuçlara göre ilk olarak pgbouncer’ın birden fazla servis olarak çalışması hem local hem de multiple modlarda performans anlamında olumlu etkiler bırakmaktadır. Ancak multi-bouncer senaryolarında görüleceği üzere her zaman en iyi performansı daha çok pgbouncer process’i almak mümkün değil. pgbouncer sayısı düştüğünde database’in durumuna göre ve iş yüküne göre performans kazanımları elde edilebilir. Bu örnekte daha az pgbouncer process’i daha fazla performans alınabildiği görüldü. Ölçekleme her zaman daha fazla sunucu ve kaynak olmayabiliyor dikkat etmek lazım. Daha da farklı bir gözden kaynak tüketimine bakacak olursakta multiple-bouncer(x3) ve multiple-bouncer(x2) arasında neredeyse performans farkı yokken kaynak tüketimi olarak ortalama %10 daha az kaynak tüketmiştir.
Aşağıdaki sonuçlarda da hem local-bouncer hemde multiple-bouncer’lar arasındaki ve bu modların pgbouncer process sayılarına göre olan performansını görebilirsiniz.
Pgbouncer sayısının 1'den fazla olduğu tüm modlarda daha düşük latency ve daha yüksek TPS elde edebiliyoruz. Ancak bu sayıyı ne kadar artırırsak o kadar performans alırız gibi bir durum da yok. local-bouncer modunda tek process ile çalışan pgbouncer modundan sonra en yüksek latency multi-bouncer(x4)’de.En fazla kaynağa sahip olan mode 2. en kötü performansı da gösterebilir.
Çıkarımlar;
- Remote ve multiple bouncer ile local multiple bouncer arasında performans farkı yok ancak remote bouncer’lı mimari’de resource tüketimi daha az aynı performansı vermesine rağmen.
- Local bouncer’da resource daha agresif kullanıldı.Tekli pgbouncer ile multiple setup arasında performans farkları var multiple bouncer kullanmak TPS’i arttırıp latency değerini düşürüyor.
Biraz uzun bir yazı oldu benim için. Bu çalışmada, sıklıkla kullanılan PostgreSQL HA mimarisindeki bileşenlerin farklı kombinasyonları ile performans değişimlerini incelemeye çalıştım. Pgbouncer’ın farklı iş yükleri ve konfigürasyonlar sonucu verdiği performans değişimlerini incelemeye çalıştım. Buradaki bulgular ve çıkarımlar üzerinde çalıştığımız test ortamı ve iş yüküne göre değişkenlik gösterebilir ancak buradan mimari değişimlerin ve iş tipine göre yapılan konfigürasyonların performansa olumlu ya da olumsuz etki edeceğini bilerek hareket edebiliriz.
Referans
Sevgiler,
Demir.