Mengkonfigurasi Pembunuh Kehabisan Memori di Linux untuk PostgreSQL


Ketika server database dimatikan secara tak terduga di Linux, Anda perlu menemukan alasannya. Mungkin ada beberapa alasan. Misalnya, SIGSEGV - macet karena bug di server backend. Tapi ini jarang terjadi. Lebih sering daripada tidak, ruang disk atau memori habis. Jika ruang disk habis, salah satu jalan keluar adalah membebaskan ruang dan memulai kembali basis data.


Pembunuh kehabisan memori


Ketika server atau proses kehabisan memori, Linux menawarkan 2 solusi: untuk crash seluruh sistem atau menghentikan proses (aplikasi) yang memakan memori. Lebih baik, tentu saja, untuk menyelesaikan proses dan menyimpan OS dari penghentian abnormal. Singkatnya, Pembunuh Kehabisan Memori adalah proses yang menghentikan aplikasi untuk menyimpan kernel dari kerusakan. Dia mengorbankan aplikasi untuk menjaga OS tetap berjalan. Pertama mari kita bahas bagaimana OOM bekerja dan bagaimana mengendalikannya, dan kemudian lihat bagaimana OOM Killer memutuskan aplikasi mana yang akan berakhir.


Salah satu tugas utama Linux adalah mengalokasikan memori ke proses ketika mereka memintanya. Biasanya suatu proses atau aplikasi meminta memori dari OS, tetapi mereka sendiri tidak sepenuhnya menggunakannya. Jika OS akan mengeluarkan memori untuk semua orang yang memintanya, tetapi tidak berencana untuk menggunakannya, segera memori akan berakhir, dan sistem akan gagal. Untuk menghindarinya, OS mencadangkan memori untuk proses, tetapi tidak benar-benar mengeluarkannya. Memori hanya dialokasikan ketika proses benar-benar akan menggunakannya. Itu terjadi bahwa OS tidak memiliki memori bebas, tetapi itu menetapkan memori untuk proses, dan ketika proses membutuhkannya, OS mengalokasikannya jika bisa. Kelemahannya adalah kadang-kadang OS menyimpan memori, tetapi pada saat yang tepat tidak ada memori bebas, dan sistem macet. OOM memainkan peran penting dalam skenario ini dan menghentikan proses untuk mencegah kernel dari panik. Ketika proses PostgreSQL dihentikan secara paksa, sebuah pesan muncul di log:


Out of Memory: Killed process 12345 (postgres). 

Jika ada sedikit memori dalam sistem dan tidak mungkin untuk membebaskannya, fungsi out_of_memory . Pada tahap ini, ia hanya memiliki satu hal yang tersisa - untuk menyelesaikan satu atau lebih proses. Haruskah OOM-killer menghentikan proses dengan segera atau bisakah saya menunggu? Jelas, ketika out_of_memory dipanggil, ini karena menunggu operasi I / O atau pertukaran halaman ke disk. Oleh karena itu, pembunuh-OOM pertama-tama harus melakukan pemeriksaan dan berdasarkan pada mereka memutuskan bahwa proses tersebut harus diselesaikan. Jika semua cek di bawah memberikan hasil positif, OOM akan menghentikan proses.


Seleksi proses


Ketika memori habis, fungsi out_of_memory() . Ini memiliki fungsi select_bad_process() , yang menerima estimasi dari fungsi select_bad_process() . Distribusi proses yang paling "buruk". Fungsi badness() memilih proses sesuai dengan aturan tertentu.


  1. Kernel membutuhkan beberapa memori minimum untuk dirinya sendiri.
  2. Anda perlu mengosongkan banyak memori.
  3. Tidak perlu mengakhiri proses yang menggunakan sedikit memori.
  4. Anda harus menyelesaikan proses minimum.
  5. Algoritma kompleks yang meningkatkan kemungkinan penyelesaian untuk proses yang ingin diselesaikan sendiri oleh pengguna.

Setelah menyelesaikan semua pemeriksaan ini, OOM memeriksa kelasnya ( oom_score ). OOM menetapkan oom_score setiap proses, dan kemudian mengalikan nilai ini dengan jumlah memori. Proses dengan nilai yang lebih tinggi lebih mungkin menjadi korban Pembunuh OOM. Proses yang terkait dengan pengguna yang memiliki hak istimewa memiliki peringkat yang lebih rendah dan cenderung memaksakan penghentian.


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

Pengidentifikasi proses Postgres adalah 3813, jadi di shell lain Anda bisa mendapatkan perkiraan menggunakan oom_score kernel oom_score ini:


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

Jika Anda tidak ingin OOM-Killer menyelesaikan proses sama sekali, ada parameter kernel lain: oom_score_adj . Tambahkan nilai negatif besar untuk mengurangi kemungkinan menyelesaikan proses yang Anda sukai.


 sudo echo -100 > /proc/3813/oom_score_adj 

Untuk mengatur nilai oom_score_adj , setel OOMScoreAdjust di blok layanan:


 [Service] OOMScoreAdjust=-1000 

Atau gunakan oomprotect dalam rcctl .


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

Pengakhiran proses secara paksa


Ketika satu atau lebih proses sudah dipilih, OOM-Killer memanggil fungsi oom_kill_task() . Fungsi ini mengirimkan sinyal terminasi ke proses. Jika tidak ada cukup memori, oom_kill() memanggil fungsi ini untuk mengirim sinyal SIGKILL ke proses. Pesan ditulis ke log kernel.


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

Cara mengontrol OOM-Killer


Di Linux, Anda dapat mengaktifkan atau menonaktifkan OOM-Killer (meskipun yang terakhir tidak disarankan). Untuk mengaktifkan dan menonaktifkan, gunakan opsi vm.oom-kill . Untuk mengaktifkan OOM-Killer saat runtime, jalankan perintah sysctl .


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

Untuk menonaktifkan OOM-Killer, tentukan nilai 0 dalam perintah yang sama:


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

Hasil dari perintah ini tidak akan disimpan selamanya, tetapi hanya sampai reboot pertama. Jika Anda membutuhkan lebih banyak ketekunan, tambahkan baris ini ke file /etc/sysctl.conf :


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

Cara lain untuk mengaktifkan dan menonaktifkan adalah dengan menulis variabel panic_on_oom . Nilai selalu dapat diperiksa di /proc .


 $ cat /proc/sys/vm/panic_on_oom 0 

Jika Anda menetapkan nilai ke 0, maka ketika memori habis, panik kernel tidak akan.


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

Jika Anda menetapkan nilai ke 1, maka ketika memori habis, kernel panik akan terjadi.


 echo 1 > /proc/sys/vm/panic_on_oom 

OOM-Killer tidak hanya bisa dihidupkan dan dimatikan. Kami telah mengatakan bahwa Linux dapat menyimpan lebih banyak memori untuk proses daripada yang ada, tetapi sebenarnya tidak mengalokasikannya, dan perilaku ini dikendalikan oleh parameter kernel Linux. Variabel vm.overcommit_memory bertanggung jawab untuk ini.


Anda dapat menentukan nilai-nilai berikut untuk itu:


0: Kernel itu sendiri memutuskan apakah akan mencadangkan terlalu banyak memori. Ini adalah nilai default pada sebagian besar versi Linux.
1: kernel akan selalu menyimpan memori ekstra. Ini berisiko, karena ingatan bisa berakhir, karena, kemungkinan besar, suatu hari proses akan menuntut apa yang seharusnya.
2: kernel tidak akan menyimpan lebih banyak memori daripada yang ditentukan dalam parameter overcommit_ratio .


Dalam parameter ini Anda menentukan persentase memori yang redundansi diizinkan. Jika tidak ada ruang untuk itu, memori tidak dialokasikan, reservasi akan ditolak. Ini adalah opsi teraman yang direkomendasikan untuk PostgreSQL. OOM-Killer dipengaruhi oleh elemen lain - fitur swap, yang dikendalikan oleh variabel cat /proc/sys/vm/swappiness . Nilai-nilai ini memberi tahu kernel cara menangani paging. Semakin besar nilainya, semakin kecil kemungkinan OOM akan menghentikan proses, tetapi karena I / O, ini berdampak negatif pada database. Dan sebaliknya - semakin kecil nilainya, semakin tinggi kemungkinan intervensi OOM-Killer, tetapi kinerja basis data juga lebih tinggi. Nilai default adalah 60, tetapi jika seluruh database sesuai dengan memori, yang terbaik adalah mengatur nilai ke 1.


Ringkasan


Jangan takut dengan si pembunuh di OOM-Killer. Dalam hal ini, si pembunuh akan menjadi penyelamat sistem Anda. Ini "membunuh" proses terburuk dan menyelamatkan sistem dari penghentian abnormal. Untuk menghindari keharusan menggunakan OOM-Killer untuk menyelesaikan PostgreSQL, atur vm.overcommit_memory ke 2. Ini tidak menjamin bahwa OOM-Killer tidak harus campur tangan, tetapi akan mengurangi kemungkinan proses PostgreSQL dipaksa untuk diakhiri.

Source: https://habr.com/ru/post/id464245/


All Articles