PostgreSQL के लिए लिनक्स में आउट-ऑफ-मेमोरी किलर की स्थापना

PostgreSQL के लिए लिनक्स में आउट-ऑफ-मेमोरी किलर की स्थापना

जब कोई डेटाबेस सर्वर लिनक्स में अप्रत्याशित रूप से बंद हो जाता है, तो आपको इसका कारण ढूंढना होगा। इसके कई कारण हो सकते हैं. उदाहरण के लिए, SIGSEGV - बैकएंड सर्वर में बग के कारण विफलता। लेकिन ऐसा दुर्लभ है. अक्सर, आपकी डिस्क स्थान या मेमोरी ख़त्म हो जाती है। यदि आपकी डिस्क स्थान समाप्त हो गया है, तो केवल एक ही रास्ता है - स्थान खाली करें और डेटाबेस को पुनरारंभ करें।

आउट-ऑफ़-मेमोरी किलर

जब किसी सर्वर या प्रक्रिया की मेमोरी खत्म हो जाती है, तो लिनक्स 2 समाधान प्रदान करता है: पूरे सिस्टम को क्रैश कर देना या उस प्रक्रिया (एप्लिकेशन) को समाप्त करना जो मेमोरी खा रही है। बेशक, प्रक्रिया को समाप्त करना और ओएस को क्रैश होने से बचाना बेहतर है। संक्षेप में, आउट-ऑफ-मेमोरी किलर एक ऐसी प्रक्रिया है जो कर्नेल को क्रैश होने से बचाने के लिए किसी एप्लिकेशन को मार देती है। यह OS को चालू रखने के लिए एप्लिकेशन का त्याग कर देता है। आइए पहले चर्चा करें कि OOM कैसे काम करता है और इसे कैसे नियंत्रित किया जाए, और फिर देखें कि OOM किलर कैसे तय करता है कि किस एप्लिकेशन को समाप्त करना है।

लिनक्स का एक मुख्य कार्य प्रक्रियाओं को मेमोरी आवंटित करना है जब वे इसके लिए कहते हैं। आमतौर पर, एक प्रक्रिया या एप्लिकेशन ओएस से मेमोरी का अनुरोध करता है, लेकिन इसका पूरी तरह से उपयोग नहीं करता है। यदि ओएस उन सभी को मेमोरी देता है जो इसकी मांग करता है लेकिन उसके पास इसका उपयोग करने की कोई योजना नहीं है, तो बहुत जल्द मेमोरी खत्म हो जाएगी और सिस्टम विफल हो जाएगा। इससे बचने के लिए, ओएस प्रक्रिया के लिए मेमोरी आरक्षित रखता है, लेकिन वास्तव में इसे जारी नहीं करता है। मेमोरी तभी आवंटित की जाती है जब कोई प्रक्रिया वास्तव में इसका उपयोग करने जा रही हो। ऐसा होता है कि ओएस में मुफ्त मेमोरी नहीं होती है, लेकिन यह एक प्रक्रिया को मेमोरी आवंटित करता है, और जब किसी प्रक्रिया को इसकी आवश्यकता होती है, तो ओएस इसे आवंटित कर सकता है। नकारात्मक पक्ष यह है कि कभी-कभी ओएस मेमोरी आरक्षित रखता है, लेकिन सही समय पर कोई खाली मेमोरी नहीं होती है, और सिस्टम क्रैश हो जाता है। OOM इस परिदृश्य में एक महत्वपूर्ण भूमिका निभाता है और कर्नेल को घबराने से रोकने के लिए प्रक्रियाओं को समाप्त करता है। जब PostgreSQL प्रक्रिया को समाप्त करने के लिए मजबूर किया जाता है, तो लॉग में एक संदेश दिखाई देता है:

Out of Memory: Killed process 12345 (postgres).

यदि सिस्टम में मेमोरी कम है और इसे मुक्त नहीं किया जा सकता है, तो फ़ंक्शन को कॉल किया जाता है out_of_memory. इस स्तर पर, उसके पास करने के लिए केवल एक ही काम बचा है - एक या अधिक प्रक्रियाओं को पूरा करना। क्या OOM-किलर को प्रक्रिया तुरंत समाप्त कर देनी चाहिए या प्रतीक्षा करनी चाहिए? जाहिर है, जब 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 किलर का शिकार होने की अधिक संभावना है। रूट उपयोगकर्ता से जुड़ी प्रक्रियाओं का स्कोर कम होता है और उन्हें समाप्त करने के लिए बाध्य होने की संभावना कम होती है।

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

पोस्टग्रेज प्रक्रिया आईडी 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-किलर फ़ंक्शन को कॉल करता है oom_kill_task(). यह फ़ंक्शन प्रक्रिया को समाप्ति संकेत भेजता है। मेमोरी की कमी होने पर oom_kill() प्रक्रिया में SIGKILL सिग्नल भेजने के लिए इस फ़ंक्शन को कॉल करता है। कर्नेल लॉग पर एक संदेश लिखा जाता है.

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

OOM-किलर को कैसे नियंत्रित करें

लिनक्स पर, आप OOM-किलर को सक्षम या अक्षम कर सकते हैं (हालाँकि बाद वाला अनुशंसित नहीं है)। सक्षम या अक्षम करने के लिए पैरामीटर का उपयोग करें vm.oom-kill. रनटाइम पर OOM-किलर को सक्षम करने के लिए, कमांड चलाएँ sysctl.

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

OOM-किलर को अक्षम करने के लिए, उसी कमांड में मान 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-किलर को न केवल चालू और बंद किया जा सकता है। हमने पहले ही कहा है कि लिनक्स वास्तव में इसे आवंटित किए बिना प्रक्रियाओं के लिए उपलब्ध मेमोरी से अधिक मेमोरी आरक्षित कर सकता है, और यह व्यवहार लिनक्स कर्नेल पैरामीटर द्वारा नियंत्रित किया जाता है। इसके लिए वेरिएबल जिम्मेदार है vm.overcommit_memory.

आप इसके लिए निम्नलिखित मान निर्दिष्ट कर सकते हैं:

0: कर्नेल स्वयं निर्णय लेता है कि बहुत अधिक मेमोरी आरक्षित करनी है या नहीं। लिनक्स के अधिकांश संस्करणों पर यह डिफ़ॉल्ट है।
1: कर्नेल हमेशा अतिरिक्त मेमोरी आरक्षित रखेगा. यह जोखिम भरा है, क्योंकि मेमोरी ख़त्म हो सकती है, क्योंकि, सबसे अधिक संभावना है, एक दिन प्रक्रियाओं को इसकी आवश्यकता होगी।
2: कर्नेल पैरामीटर में निर्दिष्ट से अधिक मेमोरी आरक्षित नहीं करेगा overcommit_ratio.

इस पैरामीटर के साथ, आप मेमोरी का वह प्रतिशत निर्दिष्ट करते हैं जिसे अधिक-आरक्षित करने की अनुमति है। यदि इसके लिए कोई जगह नहीं है, तो कोई मेमोरी आवंटित नहीं की जाएगी और आरक्षण से इनकार कर दिया जाएगा। यह PostgreSQL के लिए अनुशंसित सबसे सुरक्षित विकल्प है। ओओएम-किलर एक अन्य तत्व से प्रभावित होता है - स्वैपिंग क्षमता, जिसे वेरिएबल द्वारा नियंत्रित किया जाता है cat /proc/sys/vm/swappiness. ये मान कर्नेल को बताते हैं कि पेजिंग को कैसे संभालना है। मूल्य जितना अधिक होगा, उतनी ही कम संभावना होगी कि OOM प्रक्रिया को समाप्त कर देगा, लेकिन I/O संचालन के कारण डेटाबेस पर इसका नकारात्मक प्रभाव पड़ता है। और इसके विपरीत - मूल्य जितना कम होगा, ओओएम-किलर हस्तक्षेप की संभावना उतनी ही अधिक होगी, लेकिन डेटाबेस का प्रदर्शन भी अधिक होगा। डिफ़ॉल्ट मान 60 है, लेकिन यदि संपूर्ण डेटाबेस मेमोरी में फिट बैठता है, तो मान को 1 पर सेट करना बेहतर है।

परिणाम

OOM-किलर में "हत्यारे" को आपको डराने न दें। इस मामले में, हत्यारा आपके सिस्टम का रक्षक होगा। यह सबसे खराब प्रक्रियाओं को "मार देता है" और सिस्टम को क्रैश होने से बचाता है। PostgreSQL को समाप्त करने के लिए OOM-Killer का उपयोग करने से बचने के लिए, पर सेट करें vm.overcommit_memory मान 2. यह गारंटी नहीं देता है कि OOM-किलर को हस्तक्षेप नहीं करना पड़ेगा, लेकिन इससे PostgreSQL प्रक्रिया को समाप्त करने के लिए मजबूर करने की संभावना कम हो जाएगी।

स्रोत: www.habr.com

एक टिप्पणी जोड़ें