การตั้งค่า Out-Of-Memory Killer ใน Linux สำหรับ PostgreSQL

การตั้งค่า Out-Of-Memory Killer ใน Linux สำหรับ PostgreSQL

เมื่อเซิร์ฟเวอร์ฐานข้อมูลปิดการทำงานโดยไม่คาดคิดใน Linux คุณต้องค้นหาสาเหตุ อาจมีสาเหตุหลายประการ ตัวอย่างเช่น, ซิกเซกวี — ความล้มเหลวเนื่องจากข้อผิดพลาดในเซิร์ฟเวอร์แบ็กเอนด์ แต่นี่หายาก บ่อยครั้งที่พื้นที่ดิสก์หรือหน่วยความจำของคุณหมด หากพื้นที่ดิสก์ของคุณหมด มีทางเดียวเท่านั้นที่จะออก - เพิ่มพื้นที่ว่างและรีสตาร์ทฐานข้อมูล

นักฆ่าหน่วยความจำไม่เพียงพอ

เมื่อเซิร์ฟเวอร์หรือกระบวนการหน่วยความจำไม่เพียงพอ 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 killer ต้องทำการตรวจสอบก่อน และตัดสินใจว่ากระบวนการจำเป็นต้องถูกยกเลิก หากการตรวจสอบด้านล่างทั้งหมดเป็นบวก 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 ยุติลง

ที่มา: will.com

เพิ่มความคิดเห็น