Nastavitev programa Out-Of-Memory Killer v Linuxu za PostgreSQL

Nastavitev programa Out-Of-Memory Killer v Linuxu za PostgreSQL

Ko se strežnik baze podatkov nepričakovano zapre v Linuxu, morate najti razlog. Razlogov je lahko več. na primer SIGSEGV — napaka zaradi hrošča v zalednem strežniku. Ampak to je redko. Najpogosteje preprosto zmanjka prostora na disku ali pomnilnika. Če vam zmanjka prostora na disku, obstaja samo en izhod - sprostite prostor in znova zaženite bazo podatkov.

Ubijalec brez spomina

Ko strežniku ali procesu zmanjka pomnilnika, Linux ponuja 2 rešitvi: zruši celoten sistem ali prekine proces (aplikacijo), ki jede pomnilnik. Seveda je bolje, da prekinete postopek in rešite OS pred zrušitvijo. Na kratko, Out-Of-Memory Killer je postopek, ki ubije aplikacijo, da reši jedro pred zrušitvijo. Žrtvuje aplikacijo, da OS še naprej deluje. Najprej se pogovorimo o tem, kako deluje OOM in kako ga nadzorovati, nato pa poglejmo, kako se OOM Killer odloči, katero aplikacijo bo zaprl.

Ena od glavnih nalog Linuxa je dodeljevanje pomnilnika procesom, ko ga zahtevajo. Običajno proces ali aplikacija zahteva pomnilnik od OS, vendar ga ne uporablja v celoti. Če operacijski sistem da pomnilnik vsem, ki ga zahtevajo, a ga ne nameravajo uporabljati, bo pomnilnika zelo kmalu zmanjkalo in sistem bo odpovedal. Da bi se temu izognili, OS rezervira pomnilnik za proces, vendar ga dejansko ne sprosti. Pomnilnik se dodeli le, ko ga bo proces dejansko uporabil. Zgodi se, da OS nima prostega pomnilnika, ampak dodeli pomnilnik procesu in ko ga proces potrebuje, ga OS dodeli, če lahko. Slaba stran je, da včasih OS rezervira pomnilnik, vendar ob pravem času ni prostega pomnilnika in sistem se zruši. OOM igra pomembno vlogo v tem scenariju in prekine procese, da prepreči paniko v jedru. Ko se proces PostgreSQL prisilno prekine, se v dnevniku prikaže sporočilo:

Out of Memory: Killed process 12345 (postgres).

Če sistemu primanjkuje pomnilnika in ga ni mogoče sprostiti, se funkcija pokliče out_of_memory. Na tej stopnji ji preostane le še ena stvar - dokončati enega ali več procesov. Ali naj OOM-killer takoj prekine postopek ali lahko počaka? Očitno je, da se pri klicu out_of_memory pojavi čakanje na V/I operacijo ali ostranjevanje na disk. Zato mora OOM killer najprej opraviti preverjanja in se na podlagi njih odločiti, da je treba proces prekiniti. Če so vsa spodnja preverjanja pozitivna, bo OOM prekinil postopek.

Izbira procesa

Ko zmanjka pomnilnika, se funkcija pokliče out_of_memory(). Ima funkcijo select_bad_process(), ki prejme oceno funkcije badness(). Usmerjen bo "najslabši" proces. funkcija badness() izbere postopek po določenih pravilih.

  1. Jedro potrebuje nekaj minimalnega pomnilnika zase.
  2. Sprostiti morate veliko pomnilnika.
  3. Procesov, ki uporabljajo malo pomnilnika, ni treba prekiniti.
  4. Dokončati je treba minimalne procese.
  5. Kompleksni algoritmi, ki povečajo možnosti dokončanja za tiste procese, ki jih uporabnik sam želi dokončati.

Ko opravi vsa ta preverjanja, OOM pregleda rezultat (oom_score). OOM dodeli oom_score vsak proces in nato to vrednost pomnoži s količino pomnilnika. Procesi z večjimi vrednostmi bodo bolj verjetno žrtev OOM Killerja. Procesi, povezani s korenskim uporabnikom, imajo nižjo oceno in je manj verjetno, da bodo prisiljeni prekiniti.

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

ID procesa Postgres je 3813, tako da je v drugi lupini mogoče dobiti rezultat s tem parametrom jedra oom_score:

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

Če ne želite, da OOM-Killer sploh uniči proces, obstaja še ena možnost jedra: oom_score_adj. Dodajte veliko negativno vrednost, da zmanjšate možnosti za dokončanje procesa, ki ga cenite.

sudo echo -100 > /proc/3813/oom_score_adj

Za nastavitev vrednosti oom_score_adj, nastavite OOMScoreAdjust v servisnem bloku:

[Service]
OOMScoreAdjust=-1000

Ali uporabite oomprotect v ekipi rcctl.

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

Prisilna prekinitev procesa

Ko je eden ali več procesov že izbranih, OOM-Killer pokliče funkcijo oom_kill_task(). Ta funkcija pošlje procesu zaključni signal. V primeru pomanjkanja spomina oom_kill() Pokliče to funkcijo, da procesu pošlje signal SIGKILL. V dnevnik jedra se zapiše sporočilo.

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

Kako nadzirati OOM-Killer

V sistemu Linux lahko omogočite ali onemogočite OOM-Killer (čeprav slednje ni priporočljivo). Če želite omogočiti ali onemogočiti, uporabite parameter vm.oom-kill. Če želite omogočiti OOM-Killer med izvajanjem, zaženite ukaz sysctl.

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

Če želite onemogočiti OOM-Killer, podajte vrednost 0 v istem ukazu:

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

Rezultat tega ukaza ne bo shranjen za vedno, ampak le do prvega ponovnega zagona. Če potrebujete več vztrajnosti, dodajte to vrstico v datoteko /etc/sysctl.conf:

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

Drug način omogočanja in onemogočanja je pisanje spremenljivke panic_on_oom. Vrednost je vedno mogoče preveriti /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Če nastavite vrednost na 0, potem ko zmanjka pomnilnika, ne bo panike jedra.

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

Če nastavite vrednost na 1, se bo, ko zmanjka pomnilnika, pojavila panika jedra.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killerja ni mogoče samo vklopiti in izklopiti. Rekli smo že, da lahko Linux za procese rezervira več pomnilnika, kot je na voljo, ne da bi ga dejansko dodelil, to vedenje pa nadzoruje parameter jedra Linuxa. Za to je odgovorna spremenljivka vm.overcommit_memory.

Zanj lahko določite naslednje vrednosti:

0: Jedro se samo odloči, ali bo rezerviralo preveč pomnilnika. To je privzeto v večini različic Linuxa.
1: Jedro bo vedno rezerviralo dodatni pomnilnik. To je tvegano, saj lahko zmanjka pomnilnika, saj ga bodo najverjetneje nekoč procesi zahtevali.
2: jedro ne bo rezerviralo več pomnilnika, kot je navedeno v parametru overcommit_ratio.

S tem parametrom določite odstotek pomnilnika, ki je dovoljen za preveč rezerviran. Če zanj ni prostora, se pomnilnik ne dodeli in rezervacija bo zavrnjena. To je najvarnejša možnost, priporočena za PostgreSQL. Na OOM-Killer vpliva še en element - zmožnost zamenjave, ki jo nadzira spremenljivka cat /proc/sys/vm/swappiness. Te vrednosti povedo jedru, kako ravnati s strani. Višja kot je vrednost, manjša je verjetnost, da bo OOM prekinil proces, vendar zaradi V/I operacij negativno vpliva na bazo podatkov. In obratno – nižja kot je vrednost, večja je verjetnost posega OOM-Killer, vendar je tudi zmogljivost baze podatkov večja. Privzeta vrednost je 60, a če se celotna zbirka podatkov prilega pomnilniku, je bolje, da vrednost nastavite na 1.

Rezultati

Naj vas "morilec" v OOM-Killerju ne prestraši. V tem primeru bo morilec rešitelj vašega sistema. "Ubije" najhujše procese in reši sistem pred sesutjem. Da bi se izognili uporabi OOM-Killer za prekinitev PostgreSQL, nastavite na vm.overcommit_memory vrednost 2. To ne zagotavlja, da OOM-Killerju ne bo treba posredovati, vendar bo zmanjšalo verjetnost prisilne prekinitve procesa PostgreSQL.

Vir: www.habr.com

Dodaj komentar