راه‌اندازی قاتل خارج از حافظه در Linux برای PostgreSQL

راه‌اندازی قاتل خارج از حافظه در Linux برای PostgreSQL

زمانی که در Linux сервер базы данных непредвиденно завершает работу, нужно найти причину. Причин может быть несколько. Например, SIGSEGV - شکست به دلیل یک اشکال در سرور باطن. اما این نادر است. اغلب اوقات، فضای دیسک یا حافظه شما تمام می شود. اگر فضای دیسک شما تمام شد، تنها یک راه برای خروج وجود دارد - آزاد کردن فضا و راه اندازی مجدد پایگاه داده.

قاتل خارج از حافظه

وقتی تو سرور или процесса заканчивается память, Linux предлагает 2 пути решения: обрушить всю систему или завершить процесс (приложение), который съедает память. Лучше, конечно, завершить процесс и спасти ОС от аварийного завершения. В двух словах, Out-Of-Memory Killer — это процесс, который завершает приложение, чтобы спасти ядро от сбоя. Он жертвует приложением, чтобы сохранить работу ОС. Давайте сначала обсудим, как работает OOM и как его контролировать, а потом посмотрим, как OOM Killer решает, какое приложение завершить.

Одна из главных задач Linux — выделять память процессам, когда они ее просят. Обычно процесс или приложение запрашивают у ОС память, а сами используют ее не полностью. Если ОС будет выдавать память всем, кто ее просит, но не планирует использовать, очень скоро память закончится, и система откажет. Чтобы этого избежать, ОС резервирует память за процессом, но фактически не выдает ее. Память выделяется, только когда процесс действительно собирается ее использовать. Случается, что у ОС нет свободной памяти, но она закрепляет память за процессом, и когда процессу она нужна, ОС выделяет ее, если может. Минус в том, что иногда ОС резервирует память, но в нужный момент свободной памяти нет, и происходит сбой системы. OOM играет важную роль в этом сценарии и завершает процессы, чтобы уберечь ядро от паники. Когда принудительно завершается процесс PostgreSQL, в логе появляется сообщение:

Out of Memory: Killed process 12345 (postgres).

اگر حافظه سیستم کم است و نمی توان آن را آزاد کرد، تابع فراخوانی می شود out_of_memory. در این مرحله، او تنها یک کار برای انجام دارد - تکمیل یک یا چند فرآیند. آیا OOM-killer باید فوراً فرآیند را خاتمه دهد یا می تواند صبر کند؟ بدیهی است که وقتی out_of_memory فراخوانی می شود، به دلیل انتظار برای عملیات I/O یا صفحه بندی روی دیسک است. بنابراین، قاتل OOM ابتدا باید بررسی هایی را انجام دهد و بر اساس آنها تصمیم بگیرد که این فرآیند باید خاتمه یابد. اگر همه بررسی‌های زیر مثبت باشد، OOM فرآیند را خاتمه می‌دهد.

انتخاب فرآیند

هنگامی که حافظه تمام می شود، تابع فراخوانی می شود out_of_memory(). کارکردی دارد select_bad_process()، که یک ارزیابی از تابع دریافت می کند badness(). "بدترین" روند هدف قرار خواهد گرفت. تابع badness() فرآیندی را طبق قوانین خاصی انتخاب می کند.

  1. هسته برای خودش به حداقل حافظه نیاز دارد.
  2. شما باید حافظه زیادی را آزاد کنید.
  3. نیازی به پایان دادن به فرآیندهایی که از حافظه کمی استفاده می کنند وجود ندارد.
  4. حداقل فرآیندها باید تکمیل شوند.
  5. الگوریتم های پیچیده ای که شانس تکمیل را برای آن دسته از فرآیندهایی که خود کاربر می خواهد انجام دهد افزایش می دهد.

پس از تکمیل تمام این بررسی ها، OOM امتیاز را بررسی می کند (oom_score). OOM منصوب می کند oom_score هر فرآیند، و سپس این مقدار را در مقدار حافظه ضرب می کند. فرآیندهایی با مقادیر بزرگتر احتمال بیشتری دارد که قربانی OOM Killer شوند. فرآیندهای مرتبط با کاربر ریشه امتیاز کمتری دارند و احتمال اینکه مجبور به پایان شوند کمتر است.

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

شناسه فرآیند Postgres 3813 است، بنابراین در پوسته دیگری می توان با استفاده از این پارامتر هسته امتیاز را به دست آورد. oom_score:

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

اگر اصلاً نمی‌خواهید OOM-Killer این فرآیند را از بین ببرد، گزینه دیگری برای کرنل وجود دارد: oom_score_adj. یک مقدار منفی بزرگ اضافه کنید تا شانس تکمیل فرآیندی را که برای شما ارزش قائل هستید کاهش دهید.

sudo echo -100 > /proc/3813/oom_score_adj

برای تعیین یک مقدار oom_score_adj، OOMScoreAdjust را در بلوک سرویس تنظیم کنید:

[Service]
OOMScoreAdjust=-1000

یا استفاده کنید oomprotect در یک تیم rcctl.

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

خاتمه اجباری یک فرآیند

هنگامی که یک یا چند فرآیند از قبل انتخاب شده باشد، OOM-Killer تابع را فراخوانی می کند oom_kill_task(). این تابع یک سیگنال خاتمه به فرآیند ارسال می کند. در صورت کمبود حافظه oom_kill() این تابع را برای ارسال یک سیگنال SIGKILL به فرآیند فراخوانی می کند. یک پیام به گزارش هسته نوشته می شود.

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

نحوه کنترل OOM-Killer

В Linux можно включать и отключать OOM-Killer (хотя последнее не рекомендуется). Для включения и отключения используйте параметр vm.oom-kill. برای فعال کردن OOM-Killer در زمان اجرا، دستور را اجرا کنید sysctl.

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

برای غیرفعال کردن OOM-Killer، مقدار 0 را در همان دستور مشخص کنید:

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

نتیجه این دستور برای همیشه ذخیره نمی شود، بلکه فقط تا اولین راه اندازی مجدد. اگر به ماندگاری بیشتری نیاز دارید، این خط را به فایل اضافه کنید /etc/sysctl.conf:

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

راه دیگر برای فعال و غیرفعال کردن، نوشتن یک متغیر است panic_on_oom. همیشه می توان مقدار را بررسی کرد /proc.

$ cat /proc/sys/vm/panic_on_oom
0

اگر مقدار را روی 0 تنظیم کنید، پس از اتمام حافظه، هیچ وحشتی از هسته وجود نخواهد داشت.

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

اگر مقدار را روی 1 تنظیم کنید، پس از اتمام حافظه، یک وحشت هسته رخ می دهد.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer можно не только включать и выключать. Мы уже говорили, что Linux может зарезервировать для процессов больше памяти, чем есть, но не выделять ее по факту, и этим поведением управляет параметр ядра Linux. За это отвечает переменная vm.overcommit_memory.

می توانید مقادیر زیر را برای آن تعیین کنید:

0: ядро само решает, стоит ли резервировать слишком много памяти. Это значение по умолчанию в большинстве версий Linux.
1: هسته همیشه حافظه اضافی را ذخیره می کند. این خطرناک است، زیرا ممکن است حافظه تمام شود، زیرا، به احتمال زیاد، روزی فرآیندها به آن نیاز خواهند داشت.
2: هسته بیشتر از مقدار مشخص شده در پارامتر حافظه ذخیره نخواهد کرد overcommit_ratio.

با استفاده از این پارامتر، درصدی از حافظه مجاز برای رزرو بیش از حد را مشخص می کنید. اگر جایی برای آن وجود نداشته باشد، حافظه ای اختصاص داده نمی شود و رزرو رد می شود. این امن ترین گزینه توصیه شده برای PostgreSQL است. OOM-Killer تحت تأثیر عنصر دیگری قرار می گیرد - قابلیت تعویض که توسط متغیر کنترل می شود. cat /proc/sys/vm/swappiness. این مقادیر به هسته می گویند که چگونه صفحه بندی را مدیریت کند. هر چه مقدار بالاتر باشد، احتمال اینکه OOM فرآیند را خاتمه دهد کمتر است، اما به دلیل عملیات I/O تأثیر منفی بر پایگاه داده دارد. و برعکس - هر چه مقدار کمتر باشد، احتمال مداخله OOM-Killer بیشتر است، اما عملکرد پایگاه داده نیز بالاتر است. مقدار پیش فرض 60 است، اما اگر کل پایگاه داده در حافظه قرار می گیرد، بهتر است مقدار را 1 قرار دهید.

نمایش نتایج: از

اجازه ندهید "قاتل" در OOM-Killer شما را بترساند. در این صورت قاتل ناجی سیستم شما خواهد بود. این بدترین فرآیندها را "کشته" می کند و سیستم را از خرابی نجات می دهد. برای جلوگیری از نیاز به استفاده از OOM-Killer برای پایان دادن به PostgreSQL، روی را تنظیم کنید vm.overcommit_memory مقدار 2. این تضمین نمی کند که OOM-Killer مجبور به مداخله نخواهد بود، اما احتمال خاتمه دادن به فرآیند PostgreSQL را کاهش می دهد.

منبع: www.habr.com

خرید هاست قابل اعتماد برای سایت های دارای حفاظت DDoS، سرورهای VPS VDS 🔥 خرید هاستینگ معتبر با محافظت در برابر حملات DDoS، سرورهای VPS و VDS | ProHoster