راه اندازی Out-Of-Memory Killer در لینوکس برای PostgreSQL

راه اندازی Out-Of-Memory Killer در لینوکس برای PostgreSQL

وقتی سرور پایگاه داده به طور غیرمنتظره ای در لینوکس خاموش می شود، باید دلیل آن را پیدا کنید. ممکن است دلایل مختلفی وجود داشته باشد. مثلا، SIGSEGV - شکست به دلیل یک اشکال در سرور باطن. اما این نادر است. اغلب اوقات، فضای دیسک یا حافظه شما تمام می شود. اگر فضای دیسک شما تمام شد، تنها یک راه برای خروج وجود دارد - آزاد کردن فضا و راه اندازی مجدد پایگاه داده.

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

هنگامی که حافظه سرور یا فرآیندی تمام می شود، لینوکس 2 راه حل ارائه می دهد: خرابی کل سیستم یا خاتمه فرآیند (برنامه) که در حال مصرف حافظه است. البته بهتر است فرآیند را خاتمه دهید و سیستم عامل را از خراب شدن نجات دهید. به طور خلاصه، Out-Of-Memory Killer فرآیندی است که یک برنامه کاربردی را می کشد تا هسته را از خراب شدن نجات دهد. این برنامه را قربانی نگه داشتن سیستم عامل می کند. بیایید ابتدا درباره نحوه کار OOM و نحوه کنترل آن بحث کنیم و سپس ببینیم که چگونه OOM Killer تصمیم می گیرد کدام برنامه را خاتمه دهد.

یکی از وظایف اصلی لینوکس، تخصیص حافظه به پردازش‌ها در زمانی است که آنها درخواست می‌کنند. به طور معمول، یک فرآیند یا برنامه از سیستم عامل درخواست حافظه می کند، اما به طور کامل از آن استفاده نمی کند. اگر سیستم عامل به همه کسانی که آن را درخواست می کنند اما برنامه ای برای استفاده از آن ندارند، حافظه بدهد، خیلی زود حافظه تمام می شود و سیستم از کار می افتد. برای جلوگیری از این امر، سیستم عامل حافظه را برای فرآیند ذخیره می کند، اما در واقع آن را آزاد نمی کند. حافظه تنها زمانی تخصیص می یابد که یک فرآیند واقعاً از آن استفاده کند. این اتفاق می افتد که سیستم عامل حافظه آزاد ندارد، اما حافظه را به یک پردازش اختصاص می دهد و زمانی که یک فرآیند به آن نیاز دارد، سیستم عامل اگر بتواند آن را اختصاص می دهد. نقطه ضعف این است که گاهی اوقات سیستم عامل حافظه را ذخیره می کند، اما در زمان مناسب حافظه آزاد وجود ندارد و سیستم از کار می افتد. 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

در لینوکس، می‌توانید 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 نه تنها می تواند روشن و خاموش شود. قبلاً گفته‌ایم که لینوکس می‌تواند حافظه بیشتری نسبت به آنچه در دسترس است بدون تخصیص واقعی آن برای فرآیندها ذخیره کند و این رفتار توسط یک پارامتر هسته لینوکس کنترل می‌شود. متغیر مسئول این است vm.overcommit_memory.

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

0: کرنل خودش تصمیم می گیرد که حافظه زیادی را ذخیره کند یا خیر. این پیش فرض در اکثر نسخه های لینوکس است.
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

اضافه کردن نظر