PgBouncer işlem hacmi nasıl 4 kat ölçeklendi
(clickhouse.com)- ClickHouse Managed Postgres, tek iş parçacıklı PgBouncer'ın tek bir CPU çekirdeğine takılı kalma sınırını aşmak için, çekirdek sayısıyla orantılı çok süreçli bir filoyu varsayılan yapılandırma olarak çalıştırıyor
- Tüm süreçler
so_reuseportile aynı porta bağlanıyor ve çekirdek yeni bağlantıları dağıttığı için, istemci tarafında tek bir endpoint gibi görünüyor - Ayrı bir bağlantı üzerinden gelen Postgres iptal istekleri, oturumu elinde tutmayan bir sürece ulaşabildiğinden, süreç eşleme ile gerçek oturum sahibine iletiliyor
- 16-vCPU
c7i.4xlargeüzerinde tek süreç yaklaşık 87.000 TPS'de tepe yaparken, 16 süreçlik filo yaklaşık 336.000 TPS'ye çıkarak yaklaşık 4 kat işlem hacmi kaydetti - Bağlantı az olduğunda tek süreç benzer veya biraz daha hızlı olabilir, ancak yüksek eşzamanlılıkta tek çekirdek darboğaz haline geldiği için bağlantı bütçesini filonun geneline bölerek Postgres'i aşırı bağlantıya boğmadan işlem hacmi ve bağlantı üst sınırı ölçeklenmeli
Tek sürecin yarattığı CPU darboğazı
- PgBouncer tek iş parçacıklı olduğu için, sistemdeki CPU sayısından bağımsız olarak bir süreç yalnızca tek çekirdek kullanır
- 16-vCPU'lu bir sunucuda bile bağlantı havuzlama işi tek bir çekirdekte yoğunlaşır ve kalan 15 çekirdek boşta kalır
- Bu nedenle, Postgres'in işleme kapasitesi tükenmeden önce havuzlayıcı toplam işlem hacmini sınırlar
- ClickHouse Managed Postgres, kullanılabilir çekirdek sayısıyla orantılı olarak PgBouncer süreç sayısını belirleyen bir süreç filosu çalıştırır
so_reuseport ile bağlantı dağıtımı
- Filodaki tüm süreçler
so_reuseportetkinleştirilmiş halde aynı porta bağlanır - Çekirdek gelen bağlantıları süreçlere dağıttığı için, istemci tek bir endpoint'e bağlanır ve arka planda birden fazla PgBouncer çalıştığını bilmek zorunda kalmaz
- PgBouncer belgeleri de birden fazla çekirdeği kullanmak için birden çok tek iş parçacıklı süreç çalıştırma yöntemi olarak
so_reuseportkullanımını öneriyor
Sorgu iptalini garanti eden süreç eşleme
- Postgres'in iptal isteği, çalışan sorgu bağlantısından ayrı yeni bir bağlantı üzerinden iptal anahtarıyla birlikte gelir
so_reuseportkullanıldığında çekirdek, yeni iptal bağlantısını ilgili oturumu tutan süreç yerine başka bir sürece yönlendirebilir- İsteği alan süreç ilgili sorguyu tanımıyorsa iptal gerçekleşmez
- PgBouncer süreçleri arasında eşleme yapılırsa, yanlış sürece ulaşan istek gerçek oturum sahibi olan sürece iletilebilir
- Böylece isteği hangi süreç alırsa alsın, sorgu iptali filonun tamamında düzgün çalışır
Transaction pooling ve bağlantı bütçesi
- Havuzlama transaction modunda çalışır ve transaction commit edilir edilmez sunucu bağlantısı yeniden havuza döner
max_client_connvemax_db_connections, süreç sayısına bölünerek her sürece tahsis edilir- Bağlantı bütçesini bölmek, filonun toplam bağlantı sayısını Postgres'in güvenli sınırları içinde tutarken toplam bağlantı üst sınırını yükseltmeyi sağlar
- Tek süreç, kendi
max_client_connsınırını aşan yeni istemcileri şu hatayla reddederFATAL: no more connections allowed (max_client_conn)
Aynı donanım üzerinde benchmark
- İki yapılandırma da aynı AWS EC2 ortamında ölçüldü
- Havuzlayıcı sunucu: 16-vCPU
c7i.4xlarge - Postgres: ayrı bir sunucu
- Yük üretici: üçüncü bir sunucuda
pgbench - İş yükü: salt okunur (select-only), transaction pooling modu
- Havuzlayıcı sunucu: 16-vCPU
- Karşılaştırma, PgBouncer tek süreç ile 16 süreçli filo arasında yapıldı; instance tipi, Postgres ve iş yükü aynıydı
- İstemci bağlantıları 8'den 256'ya çıkarılırken işlem hacmi ve 16 çekirdekli sunucunun CPU kullanımı ölçüldü
| İstemci | Tek süreç TPS | Tek süreç sunucu CPU | Filo TPS | Filo sunucu CPU |
|---|---|---|---|---|
| 8 | 8,910 | 0.8% | 6,450 | 2.9% |
| 32 | 54,203 | 5.2% | 64,244 | 12.3% |
| 64 | 86,570 | 8.3% | 219,439 | 31.9% |
| 128 | 83,463 | 8.1% | 320,547 | 45.9% |
| 256 | 76,893 | 7.7% | 336,469 | 48.9% |
İşlem hacmi ve CPU kullanım sonuçları
- Tek süreç yaklaşık 87.000 TPS'de tepe yaptıktan sonra yük arttıkça performansı düştü ve 256 istemcide yaklaşık 77.000 TPS kaydetti
- 16 süreçli filo daha fazla çekirdek kullanarak yaklaşık 336.000 TPS'ye çıktı ve tek sürece göre yaklaşık 4 kat işlem hacmi sağladı
pidstatölçümünde tek PgBouncer süreci yük altında CPU'nun yaklaşık %97'sini kullanarak bir çekirdeği tamamen doldurdu, ancak 16-vCPU'lu sunucunun toplam kullanım oranı %10'un altında kaldı- Filo işi sunucunun geneline dağıtarak yaklaşık 8 çekirdek kullandı; Postgres ve yük üretici sınıra ulaştığında bile ek kapasite kalmıştı
- 256 istemcinin korunduğu ölçümde tek süreç sunucu yaklaşık %9, filo sunucu ise sürekli yaklaşık %52 CPU kullandı
- EC2 CloudWatch üzerinden alınan dış ölçümde tek süreçli instance'ın ortalama CPUUtilization değeri yaklaşık %16, filo için ise yaklaşık %60 oldu
- CloudWatch rakamları misafir sistem içi ölçümlerden biraz daha yüksek olsa da, tek PgBouncer'ın 16-vCPU'nun büyük kısmını kullanamadığı gerçeği değişmiyor
Eşzamanlılığa göre yapılandırma seçimi
- Bağlantı sayısı az olduğunda paralelleştirilecek iş olmadığından ve filonun bağlantıları birden çok sürece dağıldığından, tek süreç yeterli olabilir veya biraz daha hızlı olabilir
- 8 istemcide tek süreç 8.910 TPS, filo ise 6.450 TPS kaydetti
- Eşzamanlılık arttığında tek sürecin kapladığı tek çekirdek işlem hacminin tavanı olur ve filoyla arasındaki performans farkı büyür
- Postgres'in PgBouncer'dan önce sınıra ulaştığı ortamlarda tek süreç de uygun bir varsayılan seçimdir
- Havuzlayıcı işlem hacmini sınırlamaya başladığında, çekirdek sayısına uygun süreç filosu,
so_reuseporttabanlı port paylaşımı ve süreç eşleme birlikte kullanılmadan darboğaz giderilemez - Tüm ClickHouse Managed Postgres sunucuları bu yapılandırmayı varsayılan olarak sunuyor
1 yorum
Hacker News yorumları
https://github.com/yandex/odyssey kullanmak yeterli. Odyssey, ölçeklenebilir bir PgBouncer
PostgreSQL bağlantılarını 10 binin üzerine ölçekleyen çok sayıda müşteri var ve ileride Odyssey ya da pgdog gibi alternatifler de değerlendirilecek. Yine de kişisel olarak PostgreSQL’de 10 binden fazla bağlantı bulundurmayı tercih etmiyorum; birkaç yüz bağlantıyla da yeterince ölçeklenebileceğini düşünüyorum
Kubernetes üzerinde PgBouncer çalıştırıyorsanız, tek bir makinede birden çok süreç başlatmak da kolay, birden çok makineye dağıtmak da
Azure, VM bakımı sırasında tüm sunucu grubunda art arda kesintilere yol açabildiği için çok makineli kurulum özellikle faydalı
Burada sözü edilen peering kavramını anlıyorum ama PostgreSQL’de bunu hiç kullanmadım
A) PostgreSQL’de bunu kolayca yapılandırmaya yarayan bir mod ya da ayar var mı? İptal isteğinin hata alınmayana kadar eşlere sırayla iletildiği ya da yanlış sürecin doğru süreci belirleyebilmesi için iptal isteğinde metadata taşındığı bir yapı hayal ediyorum
B) Tüm PostgreSQL süreçleri istemci isteklerini
so_reuseportile alıyorsa, eşler arası iletişim için ayrıca bir process inter communication (IPC) mekanizması gerekecek gibi görünüyor; pratikte hangi mekanizma kullanılıyor?PgBouncer süreç kimliğini iptal anahtarına ekleyerek bunu nispeten basit biçimde uygulamak mümkün görünüyor
26. slayttan itibaren bakabilirsiniz: https://www.pgevents.ca/events/pgconfdev2024/sessions/sessio...
PgBouncer bakımcısı Jelte’nin sunum videosu da var: https://www.youtube.com/watch?v=X-nCHcZ6vQU
pgdog kullanıyorum ve ihtiyaç duyduğum kullanım senaryosuna çok iyi uyuyor
PgBouncer’ın neden iptal istekleriyle bile ilgilenmesi gerektiğini merak ediyorum. Bunları doğrudan PostgreSQL’e iletse ve PostgreSQL iptal edilen sorguya normal yanıt yerine hata döndürse, o bağlantıyı yöneten PgBouncer bunu ele alsa yeterli olmaz mı?
PgBouncer istemciye sahte ama izlenebilir bir iptal PID’si ve gizli değer verir; iptal isteği geri geldiğinde gerçek sunucu/süreç PID’sini ve gizli değeri bulup iletir. Ayrıca istemci sorgunun hâlâ çalıştığını sanarken PgBouncer bunun zaten bittiğini ve bağlantının yeniden kullanıldığını biliyor olabilir; bu yüzden o bağlantı ve PID’nin gerçekten hâlâ o sorguyu çalıştırıp çalıştırmadığını doğrulaması gerekir
Bu, mikroservislerde PostgreSQL sunucusuna erişimi bağlantı havuzu üzerinden kontrol etmek için mi kullanılıyor? Monolitik bir backend ise gerekli görünmüyor
Düzgün çoğu backend framework’ünde bağlantı havuzu zaten yerleşik gelir ve mikroservis gerektirmeyen ya da önerilmeyen kullanım durumlarının %98’i bununla çözülür
PgBouncer harika bir yazılım. Çok kullanıyorum ve veritabanı operasyonlarını oldukça basitleştiriyor
so_reuseportterimini ilk kez görüyorum, ilginçmiş. Kurulumun anahtarı bununla birlikte peering gibi görünüyor; peering PgBouncer’a gömülü mü ve yapılandırması kolay mı?Kubernetes’te de peering kullanılabiliyor mu? Bu ortamda port yeniden kullanımı gerekmeyecek gibi duruyor; ayrıca her Pod’un ayrı bir bağlantı havuzuna sahip olup bağımsız mı çalıştığını merak ediyorum
Şu an 46 yaşındayım ve 23 yaşımdayken PostgreSQL’in ağır bağlantı modelini görüp şok olduğumu hatırlıyorum. O zamandan beri bu konuda hiç iyileşme olmadı mı?
Yine de bağlantı havuzu kullanılmıyorsa PostgreSQL’in süreç fork etmesi gerektiğinden, yeni bağlantı oluşturmanın maliyeti her zaman onlarca milisaniye ya da daha fazlası oluyor. Bağlantı havuzu olmadan yazılmış uygulamalar ideal değil ama yaygın
Uygulama framework’leri de değişti; serverless mimariler PostgreSQL’in zorlanmaya başladığı on binlerce bağlantı üretebiliyor. Ben kişisel olarak birkaç yüzün üzerindeki bağlantıları tercih etmiyorum ama bugünlerde bu durum gayet gerçekçi
Java uyumluluğunu sağlama sürecinde birçok şirket eşzamanlılık işleme yöntemini ciddi biçimde değiştirmek zorunda kaldı. PostgreSQL ve SQLite da benzer dönemde tasarlandı, ancak bu threading tartışmaları ortaya çıkmadan önce bile yüksek yüklü sistemleri devreye almış sektörün deneyimli isimleri tarafından, eski donanım kullanıcılarını da destekleyecek şekilde geliştiriliyordu