Menyiapkan Pembunuh Kehabisan Memori di Linux untuk PostgreSQL

Menyiapkan Pembunuh Kehabisan Memori di Linux untuk PostgreSQL

Ketika server database tiba-tiba berhenti di Linux, Anda perlu menemukan alasannya. Mungkin ada beberapa alasan. Misalnya, SIGSEGV — kegagalan karena bug di server backend. Tapi ini jarang terjadi. Paling sering, Anda kehabisan ruang disk atau memori. Jika Anda kehabisan ruang disk, hanya ada satu jalan keluar - kosongkan ruang dan mulai ulang database.

Pembunuh Kehabisan Memori

Ketika server atau proses kehabisan memori, Linux menawarkan 2 solusi: membuat seluruh sistem crash atau menghentikan proses (aplikasi) yang menghabiskan memori. Tentu saja lebih baik menghentikan proses dan menyelamatkan OS dari kerusakan. Singkatnya, Out-Of-Memory Killer adalah proses yang mematikan aplikasi untuk menyelamatkan kernel agar tidak mogok. Itu mengorbankan aplikasi untuk menjaga OS tetap berjalan. Mari kita bahas dulu cara kerja OOM dan cara mengendalikannya, lalu lihat bagaimana OOM Killer memutuskan aplikasi mana yang akan dihentikan.

Salah satu tugas utama Linux adalah mengalokasikan memori ke proses ketika mereka memintanya. Biasanya, suatu proses atau aplikasi meminta memori dari OS, tetapi tidak menggunakannya sepenuhnya. Jika OS memberikan memori kepada semua orang yang memintanya tetapi tidak berencana menggunakannya, memori akan segera habis dan sistem akan gagal. Untuk menghindari hal ini, OS mencadangkan memori untuk proses tersebut, namun tidak benar-benar melepaskannya. Memori dialokasikan hanya ketika suatu proses benar-benar akan menggunakannya. Kebetulan OS tidak memiliki memori bebas, tetapi ia menetapkan memori untuk suatu proses, dan ketika suatu proses membutuhkannya, OS mengalokasikannya jika bisa. Kelemahannya adalah terkadang OS mencadangkan memori, tetapi pada saat yang tepat tidak ada memori bebas, dan sistem mogok. OOM memainkan peran penting dalam skenario ini dan menghentikan proses untuk mencegah kernel panik. Ketika proses PostgreSQL terpaksa dihentikan, sebuah pesan muncul di log:

Out of Memory: Killed process 12345 (postgres).

Jika sistem kekurangan memori dan tidak dapat dikosongkan, fungsi tersebut dipanggil out_of_memory. Pada tahap ini, dia hanya memiliki satu hal yang harus dilakukan - menyelesaikan satu atau lebih proses. Haruskah OOM-killer segera menghentikan prosesnya atau dapatkah menunggu? Jelasnya, ketika out_of_memory dipanggil, hal ini disebabkan menunggu operasi I/O atau paging ke disk. Oleh karena itu, pembunuh OOM harus terlebih dahulu melakukan pemeriksaan dan, berdasarkan pemeriksaan tersebut, memutuskan bahwa proses tersebut perlu dihentikan. Jika semua pemeriksaan di bawah ini positif, OOM akan menghentikan proses.

Seleksi proses

Ketika memori habis, fungsi tersebut dipanggil out_of_memory(). Ini memiliki fungsi select_bad_process(), yang menerima evaluasi dari fungsi tersebut badness(). Proses “terburuk” akan menjadi sasaran. Fungsi badness() memilih proses menurut aturan tertentu.

  1. Kernel memerlukan sejumlah memori minimum untuk dirinya sendiri.
  2. Anda perlu mengosongkan banyak memori.
  3. Tidak perlu menghentikan proses yang menggunakan sedikit memori.
  4. Proses minimum harus diselesaikan.
  5. Algoritme kompleks yang meningkatkan peluang penyelesaian proses yang ingin diselesaikan oleh pengguna sendiri.

Setelah menyelesaikan semua pemeriksaan ini, OOM memeriksa skornya (oom_score). OOM menugaskan oom_score setiap proses, lalu mengalikan nilai ini dengan jumlah memori. Proses dengan nilai yang lebih besar lebih mungkin menjadi korban OOM Killer. Proses yang terkait dengan pengguna root memiliki skor lebih rendah dan kecil kemungkinannya untuk dihentikan secara paksa.

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

ID proses Postgres adalah 3813, jadi di shell lain dimungkinkan untuk mendapatkan skor menggunakan parameter kernel ini oom_score:

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

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

sudo echo -100 > /proc/3813/oom_score_adj

Untuk menetapkan nilai oom_score_adj, atur OOMScoreAdjust di blok layanan:

[Service]
OOMScoreAdjust=-1000

Atau gunakan oomprotect dalam tim rcctl.

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

Memaksa penghentian suatu proses

Ketika satu atau lebih proses telah dipilih, OOM-Killer memanggil fungsi tersebut oom_kill_task(). Fungsi ini mengirimkan sinyal penghentian ke proses. Jika terjadi kekurangan memori oom_kill() Memanggil fungsi ini untuk mengirimkan sinyal SIGKILL ke proses. Sebuah pesan ditulis ke log kernel.

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

Bagaimana cara mengontrol OOM-Killer

Di Linux, Anda dapat mengaktifkan atau menonaktifkan OOM-Killer (walaupun cara terakhir tidak disarankan). Untuk mengaktifkan atau menonaktifkan gunakan parameter 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 pada 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. Nilainya selalu dapat diperiksa /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Jika Anda menyetel nilainya ke 0, maka ketika memori habis, tidak akan terjadi kepanikan kernel.

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

Jika Anda menyetel nilainya ke 1, maka ketika memori habis, akan terjadi kepanikan kernel.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer tidak hanya bisa dinyalakan dan dimatikan saja. Kami telah mengatakan bahwa Linux dapat mencadangkan lebih banyak memori untuk proses daripada yang tersedia tanpa benar-benar mengalokasikannya, dan perilaku ini dikendalikan oleh parameter kernel Linux. Variabel bertanggung jawab untuk ini vm.overcommit_memory.

Anda dapat menentukan nilai berikut untuknya:

0: Kernel sendiri yang memutuskan apakah akan mencadangkan terlalu banyak memori. Ini adalah default pada sebagian besar versi Linux.
1: Kernel akan selalu mencadangkan memori tambahan. Ini berisiko, karena memori bisa habis, karena kemungkinan besar suatu saat proses akan membutuhkannya.
2: kernel tidak akan mencadangkan memori lebih dari yang ditentukan dalam parameter overcommit_ratio.

Dengan parameter ini, Anda menentukan persentase memori yang diperbolehkan untuk dicadangkan secara berlebihan. Jika tidak ada ruang untuk itu, tidak ada memori yang dialokasikan, dan reservasi akan ditolak. Ini adalah opsi teraman yang direkomendasikan untuk PostgreSQL. OOM-Killer dipengaruhi oleh elemen lain - kemampuan swapping, yang dikendalikan oleh variabel cat /proc/sys/vm/swappiness. Nilai-nilai ini memberi tahu kernel cara menangani paging. Semakin tinggi nilainya, semakin kecil kemungkinan OOM akan menghentikan proses, namun karena operasi I/O, hal ini berdampak negatif pada database. Dan sebaliknya - semakin rendah nilainya, semakin tinggi kemungkinan intervensi OOM-Killer, namun performa database juga lebih tinggi. Nilai defaultnya adalah 60, tetapi jika seluruh database muat di memori, lebih baik setel nilainya ke 1.

Hasil

Jangan biarkan "pembunuh" di OOM-Killer membuat Anda takut. Dalam hal ini, pembunuhnya akan menjadi penyelamat sistem Anda. Ini “mematikan” proses terburuk dan menyelamatkan sistem dari kerusakan. Untuk menghindari penggunaan OOM-Killer untuk menghentikan PostgreSQL, setel ke vm.overcommit_memory nilai 2. Hal ini tidak menjamin bahwa OOM-Killer tidak perlu melakukan intervensi, namun akan mengurangi kemungkinan memaksa proses PostgreSQL untuk dihentikan.

Sumber: www.habr.com

Tambah komentar