• 如何调整PostgreSQL的 Out-Of-Memory Killer设置


    当服务器/进程内存不足时,Linux有两种方法来处理,第一种是OS(Linux)崩溃,整个系统宕机;第二种是终止使系统耗尽内存的进程(应用程序)。第二种方法的最佳选择是终止进程,防止OS崩溃。简而言之,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时,有时是由于等待IO或等待页面在磁盘上交换。 因此,必须执行一些检查,OOM-killer将根据以下检查决定终止进程。如果下面指定的所有检查都为真,那么OOM将加入并终止进程。

    进程的选择

    每当发生内存外故障时,将调用out_of_memory()函数。在其中使用select_bad_process()函数,该函数从badness()函数获得一个分数。最“糟糕”的进程就是被牺牲的进程。badness()函数在选择过程时遵循一些规则。

    1.首先内核自身需要获得少量的内存

    2.尝试回收大量的内存

    3.不会kill使用少量内存的进程

    4.尝试kill少量的进程

    5.一些细致的算法提高了用户想要杀死的进程的牺牲优先级

     

    在所有这些检查列表之后,OOM killer会检查分数(oom_score)。将“oom_score”设置到每个进程,然后将该值与内存使用量相乘。具有更大值的进程将有很高的概率被OOM killer终止。与特权用户关联的进程分数值较低,被OOM杀死的机会也较少。

    postgres=# select pg_backend_pid();
     pg_backend_pid 
    ----------------
               4845
    (1 row)
    
    postgres=# 
    

    postgresql的进程id是4845,在另外shell中可以看到它的oom_score

    # cat /proc/4845/oom_score
    0
    

    如果你想你的进程不被oom killer杀掉,可以配置另外一个参数oom_score_adj。设置一个较大的负值,可以减少被kill的机会。

    # echo -100 > /proc/4845/oom_score_adj
    

      

    可以在启动服务中设置:

    #vi /usr/lib/systemd/system/postgresql-10.service
    # Disable OOM kill on the postmaster
    [Service]
    OOMScoreAdjust=-1000
    

      

    杀死一个进程
    当选择一个或多个进程时,OOM-Killer调用oom_kill_task()函数。这个函数负责向进程发送终止/kill信号。在内存不足的情况下,调用这个函数,它可以向进程发送SIGKILL信号。生成一条内核日志消息。

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

    如何控制OOM-Killer
    linux提供了如何启动和关闭oom-killer,但是不推荐关闭。内核参数vm.oom-kill被用来开启和关闭oom-killer。
    开启

    sysctl -w vm.oom-kill=1
    


    关闭

    sysctl -w vm.oom-kill=0
    

      

    要想永久生效:

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

      

    要开启或关闭的另一种方法是写变量panic_on_oom变量。

    $ cat /proc/sys/vm/panic_on_oom
    0
    

    设置为0表示,内核遇到内存溢出时候不会恐慌

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

      

    除了启用和禁用外,还有更多的设置。
    正如我们已经提到的那样,Linux可以通过分配内存而超额分配内存给进程,这种行为可以由Linux内核设置控制。
    vm.overcommit_memory是用来控制这种行为的变量。
    ·0:内核决定是否可以overcommit,这是默认设置
    ·1:内核总是使用overcommit功能。这是一个冒险的设置
    ·2:内核支持overcommit功能,但是不能超过overcommit_ratio(所有物理内存和交换空间总和的内存)。

    # vi /etc/sysctl.conf
    vm.overcommit_memory = 2
    vm.overcommit_ratio = 90 # overcommit_memory= 2 时生效
    

      

    影响“oom-killer”的第二个因素是交换分区。这个行为可以通过变量/proc/sys/vm/swappiness来控制。这值指定用于处理页面交换的内核设置。
    这个值越大,终止进程的可能性就越小,但是由于I/O,它会影响数据库的效率。
    控制swappiness的变量的值越小,意味着oom杀手出现的可能性越大,但它也会提高数据库性能。
    默认值是60,但是如果整个数据库内存适合,那么建议将该值设置为1。

    要想避免postgresql发生oom,建议设置vm.overcommit_memory=2。这样不能百分百避免发生,但是会减少杀死postgresql进程的机会。

  • 相关阅读:
    构建之法阅读笔记05
    构建之法阅读笔记04
    构建之法阅读笔记03
    构建之法阅读笔记02
    构建之法阅读笔记01
    管理系统的简单解析---web
    Java中的异常处理
    多态
    重写与重载
    抽象类与接口
  • 原文地址:https://www.cnblogs.com/abclife/p/14581795.html
Copyright © 2020-2023  润新知