Postavljanje programa Out-Of-Memory Killer u Linuxu za PostgreSQL

Postavljanje programa Out-Of-Memory Killer u Linuxu za PostgreSQL

Kada se poslužitelj baze podataka neočekivano zatvori u Linuxu, morate pronaći razlog. Može postojati nekoliko razloga. Na primjer, SIGSEGV — kvar zbog greške u pozadinskom poslužitelju. Ali ovo je rijetkost. Najčešće jednostavno ostanete bez prostora na disku ili memorije. Ako vam ponestane prostora na disku, postoji samo jedan izlaz - oslobodite prostor i ponovno pokrenite bazu podataka.

Ubojica bez pamćenja

Kada poslužitelju ili procesu ponestane memorije, Linux nudi 2 rješenja: srušiti cijeli sustav ili prekinuti proces (aplikaciju) koji troši memoriju. Bolje je, naravno, prekinuti proces i spasiti OS od pada. Ukratko, Out-Of-Memory Killer je proces koji ubija aplikaciju kako bi spasio kernel od pada. Žrtvuje aplikaciju kako bi operativni sustav nastavio raditi. Prvo raspravimo kako OOM radi i kako ga kontrolirati, a zatim vidimo kako OOM Killer odlučuje koju će aplikaciju zatvoriti.

Jedan od glavnih zadataka Linuxa je dodjeljivanje memorije procesima kada oni to zatraže. Tipično, proces ili aplikacija zahtijeva memoriju od OS-a, ali je ne koristi u potpunosti. Ako OS daje memoriju svima koji je traže, ali je ne planiraju koristiti, vrlo brzo će memorije ponestati i sustav će pasti. Da bi se to izbjeglo, OS rezervira memoriju za proces, ali je zapravo ne oslobađa. Memorija se dodjeljuje samo kada će je proces stvarno koristiti. Dešava se da OS nema slobodne memorije, ali dodijeli memoriju procesu, a kada je procesu treba, OS je dodijeli ako može. Loša strana je što OS ponekad rezervira memoriju, ali u pravom trenutku nema slobodne memorije i sustav se ruši. OOM igra važnu ulogu u ovom scenariju i prekida procese kako bi spriječio paniku kernela. Kada se PostgreSQL proces prisilno prekine, u zapisniku se pojavljuje poruka:

Out of Memory: Killed process 12345 (postgres).

Ako sustavu nedostaje memorije i ne može se osloboditi, poziva se funkcija out_of_memory. U ovoj fazi joj preostaje samo jedno - završiti jedan ili više procesa. Treba li OOM-killer odmah prekinuti proces ili može pričekati? Očito, kada se pozove out_of_memory, to je zbog čekanja I/O operacije ili straničenja na disk. Stoga OOM ubojica prvo mora izvršiti provjere i na temelju njih odlučiti da je proces potrebno prekinuti. Ako su sve provjere u nastavku pozitivne, OOM će prekinuti proces.

Izbor procesa

Kada ponestane memorije, poziva se funkcija out_of_memory(). Ima funkciju select_bad_process(), koji dobiva ocjenu od funkcije badness(). Ciljat će se "najgori" proces. Funkcija badness() odabire proces prema određenim pravilima.

  1. Kernel treba minimalnu memoriju za sebe.
  2. Morate osloboditi puno memorije.
  3. Nema potrebe prekidati procese koji koriste malo memorije.
  4. Potrebno je dovršiti minimalne procese.
  5. Složeni algoritmi koji povećavaju šanse za dovršetak za one procese koje sam korisnik želi dovršiti.

Nakon završetka svih ovih provjera, OOM ispituje rezultat (oom_score). OOM imenuje oom_score svaki proces, a zatim množi ovu vrijednost s količinom memorije. Veća je vjerojatnost da će procesi s većim vrijednostima postati žrtve OOM Killera. Procesi povezani s root korisnikom imaju niži rezultat i manja je vjerojatnost da će biti prisiljeni prekinuti.

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

ID Postgres procesa je 3813, tako da je u drugoj ljusci moguće dobiti rezultat pomoću ovog parametra jezgre oom_score:

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

Ako ne želite da OOM-Killer uopće prekine proces, postoji još jedna opcija kernela: oom_score_adj. Dodajte veliku negativnu vrijednost kako biste smanjili šanse za dovršetak procesa koji cijenite.

sudo echo -100 > /proc/3813/oom_score_adj

Za postavljanje vrijednosti oom_score_adj, postavite OOMScoreAdjust u servisnom bloku:

[Service]
OOMScoreAdjust=-1000

Ili koristiti oomprotect u timu rcctl.

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

Prisilno prekidanje procesa

Kada je jedan ili više procesa već odabrano, OOM-Killer poziva funkciju oom_kill_task(). Ova funkcija šalje procesu prekidni signal. U slučaju nedostatka memorije oom_kill() Poziva ovu funkciju da pošalje SIGKILL signal procesu. Poruka se upisuje u dnevnik kernela.

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

Kako kontrolirati OOM-Killer

Na Linuxu možete omogućiti ili onemogućiti OOM-Killer (iako se ovo drugo ne preporučuje). Da biste omogućili ili onemogućili koristite parametar vm.oom-kill. Da biste omogućili OOM-Killer tijekom izvođenja, pokrenite naredbu sysctl.

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

Da biste onemogućili OOM-Killer, navedite vrijednost 0 u istoj naredbi:

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

Rezultat ove naredbe neće biti spremljen zauvijek, već samo do prvog ponovnog pokretanja. Ako trebate više upornosti, dodajte ovaj redak u datoteku /etc/sysctl.conf:

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

Drugi način omogućavanja i onemogućavanja je pisanje varijable panic_on_oom. Vrijednost se uvijek može provjeriti /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Ako postavite vrijednost na 0, tada kada ponestane memorije, neće biti panike u kernelu.

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

Ako postavite vrijednost na 1, kada ponestane memorije, pojavit će se panika kernela.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer se ne može samo uključiti i isključiti. Već smo rekli da Linux može rezervirati više memorije za procese nego što je dostupno bez stvarne dodjele, a ovo ponašanje kontrolira parametar jezgre Linuxa. Za to je odgovorna varijabla vm.overcommit_memory.

Za njega možete odrediti sljedeće vrijednosti:

0: Kernel sam odlučuje hoće li rezervirati previše memorije. Ovo je zadana postavka na većini verzija Linuxa.
1: Kernel će uvijek rezervirati dodatnu memoriju. To je riskantno, jer memorija može ponestati, jer, najvjerojatnije, jednog dana će to procesi zahtijevati.
2: kernel neće rezervirati više memorije nego što je navedeno u parametru overcommit_ratio.

Pomoću ovog parametra određujete postotak memorije koji je dopušteno prerezervirati. Ako za to nema mjesta, memorija se ne dodjeljuje i rezervacija će biti odbijena. Ovo je najsigurnija opcija preporučena za PostgreSQL. Na OOM-Killer utječe još jedan element - mogućnost zamjene, koja je kontrolirana varijablom cat /proc/sys/vm/swappiness. Ove vrijednosti govore kernelu kako da rukuje straničenjem. Što je viša vrijednost, manja je vjerojatnost da će OOM prekinuti proces, ali zbog I/O operacija to ima negativan utjecaj na bazu podataka. I obrnuto - što je niža vrijednost, veća je vjerojatnost intervencije OOM-Killera, ali je i izvedba baze podataka veća. Zadana vrijednost je 60, ali ako cijela baza podataka stane u memoriju, bolje je postaviti vrijednost na 1.

Rezultati

Ne dopustite da vas "ubojica" u OOM-Killeru prestraši. U ovom slučaju, ubojica će biti spasitelj vašeg sustava. “Ubija” najgore procese i spašava sustav od pada. Kako biste izbjegli korištenje OOM-Killer-a za prekid PostgreSQL-a, postavite na vm.overcommit_memory vrijednost 2. Ovo ne jamči da OOM-Killer neće morati intervenirati, ali će smanjiti vjerojatnost prisilnog prekida PostgreSQL procesa.

Izvor: www.habr.com

Dodajte komentar