PostgreSQL için Linux'ta Bellek Yetersiz Killer'ı Kurma

PostgreSQL için Linux'ta Bellek Yetersiz Killer'ı Kurma

Linux'ta bir veritabanı sunucusu beklenmedik bir şekilde kapandığında, bunun sebebini bulmanız gerekir. Birkaç nedeni olabilir. Örneğin, SIGSEGV — arka uç sunucusundaki bir hatadan kaynaklanan arıza. Ancak bu nadirdir. Çoğu zaman, disk alanınız veya belleğiniz biter. Disk alanınız biterse tek çıkış yolu vardır; alanı boşaltmak ve veritabanını yeniden başlatmak.

Yetersiz Bellek Katili

Bir sunucunun veya işlemin belleği tükendiğinde, Linux 2 çözüm sunar: tüm sistemi çökertmek veya belleği tüketen işlemi (uygulamayı) sonlandırmak. Elbette süreci sonlandırmak ve işletim sistemini çökmekten kurtarmak daha iyidir. Özetle, Yetersiz Bellek Killer, çekirdeğin çökmesini önlemek için uygulamayı öldüren bir işlemdir. İşletim sistemini çalışır durumda tutmak için uygulamayı feda eder. Önce OOM'un nasıl çalıştığını ve nasıl kontrol edileceğini tartışalım, ardından OOM Killer'ın hangi uygulamayı sonlandıracağına nasıl karar verdiğini görelim.

Linux'un ana görevlerinden biri, işlemler istendiğinde bellek ayırmaktır. Genellikle bir işlem veya uygulama işletim sisteminden bellek ister ancak onu tam olarak kullanmaz. İşletim sistemi, isteyen ancak kullanmayı planlamayan herkese bellek verirse, çok geçmeden bellek tükenecek ve sistem çökecektir. Bunu önlemek için işletim sistemi işlem için bellek ayırır, ancak gerçekte onu serbest bırakmaz. Bellek yalnızca bir işlem onu ​​gerçekten kullanacaksa ayrılır. İşletim sisteminin boş belleği yoktur, ancak bir işleme bellek atar ve bir süreç buna ihtiyaç duyduğunda, işletim sistemi yapabiliyorsa onu tahsis eder. Dezavantajı ise bazen işletim sisteminin hafızayı ayırmasıdır, ancak doğru zamanda boş hafıza kalmaz ve sistem çöker. OOM bu senaryoda önemli bir rol oynar ve çekirdeğin paniğe kapılmasını önlemek için süreçleri sonlandırır. Bir PostgreSQL işlemi sonlandırılmaya zorlandığında günlükte bir mesaj görünür:

Out of Memory: Killed process 12345 (postgres).

Sistemin belleği azsa ve boşaltılamıyorsa işlev çağrılır. out_of_memory. Bu aşamada yapması gereken tek şey kaldı; bir veya daha fazla işlemi tamamlamak. OOM-killer süreci hemen sonlandırmalı mı yoksa bekleyebilir mi? Açıkçası, out_of_memory çağrıldığında bunun nedeni bir G/Ç işleminin veya diske sayfalamanın beklenmesidir. Bu nedenle, OOM katilinin öncelikle kontroller yapması ve bunlara dayanarak sürecin sonlandırılması gerektiğine karar vermesi gerekir. Aşağıdaki kontrollerin tümü olumluysa OOM süreci sonlandıracaktır.

Süreç seçimi

Bellek dolduğunda fonksiyon çağrılır out_of_memory(). Bir işlevi var select_bad_process()işlevden bir değerlendirme alan badness(). “En kötü” süreç hedeflenecek. İşlev badness() Belirli kurallara göre bir süreç seçer.

  1. Çekirdeğin kendisi için minimum belleğe ihtiyacı vardır.
  2. Çok fazla hafıza boşaltmanız gerekiyor.
  3. Az bellek kullanan işlemleri sonlandırmaya gerek yoktur.
  4. Minimum süreçlerin tamamlanması gerekiyor.
  5. Kullanıcının kendisinin tamamlamak istediği süreçlerin tamamlanma şansını artıran karmaşık algoritmalar.

Tüm bu kontrolleri tamamlayan OOM, puanı inceler (oom_score). OOM atar oom_score her işlem ve ardından bu değeri bellek miktarıyla çarpar. Daha büyük değerlere sahip süreçlerin OOM Killer'ın kurbanı olma olasılığı daha yüksektir. Kök kullanıcıyla ilişkili işlemlerin puanı daha düşüktür ve sonlandırılmaya zorlanma olasılıkları daha düşüktür.

postgres=# SELECT pg_backend_pid();
pg_backend_pid 
----------------
    3813
(1 row)

Postgres işlem kimliği 3813'tür, dolayısıyla başka bir kabukta bu çekirdek parametresini kullanarak puanı almak mümkündür oom_score:

vagrant@vagrant:~$ sudo cat /proc/3813/oom_score
2

OOM-Killer'ın süreci sonlandırmasını istemiyorsanız başka bir çekirdek seçeneği daha vardır: oom_score_adj. Değer verdiğiniz bir süreci tamamlama şansınızı azaltmak için büyük bir negatif değer ekleyin.

sudo echo -100 > /proc/3813/oom_score_adj

Bir değer ayarlamak için oom_score_adj, hizmet bloğunda OOMScoreAdjust'ı ayarlayın:

[Service]
OOMScoreAdjust=-1000

Ya da kullan oomprotect bir takımda rcctl.

rcctl set <i>servicename</i> oomprotect -1000

Bir işlemin zorla sonlandırılması

Bir veya daha fazla işlem zaten seçildiğinde, OOM-Killer işlevi çağırır oom_kill_task(). Bu fonksiyon sürece bir sonlandırma sinyali gönderir. Bellek yetersizliği durumunda oom_kill() Sürece bir SIGKILL sinyali göndermek için bu işlevi çağırır. Çekirdek günlüğüne bir mesaj yazılır.

Out of Memory: Killed process [pid] [name].

OOM-Killer nasıl kontrol edilir

Linux'ta OOM-Killer'ı etkinleştirebilir veya devre dışı bırakabilirsiniz (ancak ikincisi önerilmez). Etkinleştirmek veya devre dışı bırakmak için parametreyi kullanın vm.oom-kill. OOM-Killer'ı çalışma zamanında etkinleştirmek için şu komutu çalıştırın: sysctl.

sudo -s sysctl -w vm.oom-kill = 1

OOM-Killer'ı devre dışı bırakmak için aynı komutta 0 değerini belirtin:

sudo -s sysctl -w vm.oom-kill = 0

Bu komutun sonucu sonsuza kadar kaydedilmeyecek, yalnızca ilk yeniden başlatmaya kadar kaydedilecektir. Daha fazla ısrara ihtiyacınız varsa bu satırı dosyaya ekleyin /etc/sysctl.conf:

echo vm.oom-kill = 1 >>/etc/sysctl.conf

Etkinleştirmenin ve devre dışı bırakmanın başka bir yolu da bir değişken yazmaktır panic_on_oom. Değer her zaman kontrol edilebilir /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Değeri 0 olarak ayarlarsanız, bellek bittiğinde çekirdek paniği oluşmaz.

$ echo 0 > /proc/sys/vm/panic_on_oom

Değeri 1 olarak ayarlarsanız, bellek bittiğinde çekirdek paniği meydana gelir.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer yalnızca açılıp kapatılamaz. Linux'un işlemler için gerçekte tahsis etmeden mevcut olandan daha fazla bellek ayırabileceğini ve bu davranışın bir Linux çekirdek parametresi tarafından kontrol edildiğini zaten söylemiştik. Değişken bundan sorumludur vm.overcommit_memory.

Bunun için aşağıdaki değerleri belirleyebilirsiniz:

0: Çok fazla bellek ayrılıp ayrılmayacağına çekirdeğin kendisi karar verir. Bu, Linux'un çoğu sürümünde varsayılandır.
1: Çekirdek her zaman ekstra bellek ayıracaktır. Bu risklidir çünkü hafıza tükenebilir, çünkü büyük olasılıkla bir gün süreçler bunu gerektirecektir.
2: çekirdek parametrede belirtilenden daha fazla bellek ayırmayacaktır overcommit_ratio.

Bu parametreyle, aşırı rezerve edilmesine izin verilen belleğin yüzdesini belirtirsiniz. Yer yoksa, hafıza tahsis edilmez ve rezervasyon reddedilir. Bu PostgreSQL için önerilen en güvenli seçenektir. OOM-Killer başka bir unsurdan etkilenir; değişken tarafından kontrol edilen değiştirme yeteneği cat /proc/sys/vm/swappiness. Bu değerler çekirdeğe sayfalamanın nasıl işleneceğini anlatır. Değer ne kadar yüksek olursa, OOM'un süreci sonlandırma olasılığı da o kadar düşük olur, ancak G/Ç işlemleri nedeniyle veritabanı üzerinde olumsuz bir etkisi vardır. Ve bunun tersi de geçerlidir; değer ne kadar düşük olursa, OOM-Killer'ın müdahale olasılığı da o kadar yüksek olur, ancak veritabanı performansı da daha yüksek olur. Varsayılan değer 60'tır ancak veritabanının tamamı belleğe sığıyorsa değeri 1 olarak ayarlamak daha iyidir.

sonuçlar

OOM-Killer'daki "katil"in sizi korkutmasına izin vermeyin. Bu durumda katil sisteminizin kurtarıcısı olacaktır. En kötü süreçleri “öldürür” ve sistemi çökmekten kurtarır. PostgreSQL'i sonlandırmak için OOM-Killer'ı kullanmak zorunda kalmamak için, şu şekilde ayarlayın: vm.overcommit_memory değer 2. Bu, OOM-Killer'in müdahale etmek zorunda kalmayacağını garanti etmez ancak PostgreSQL sürecini sonlandırmaya zorlama olasılığını azaltır.

Kaynak: habr.com

Yorum ekle