【linux】关于内存相关指标、内存回收、内存泄漏、内存调优等一些内存优化问题~

 最近在复习总结linux内存优化相关知识,撰写此文,本文分别从以下几个部分展开,内存瓶颈有什么特征?如何去优化?以及怎么去衡量一个系统的内存情况,有什么指标和工具?内存泄漏怎么发现,内存回收相关知识,另外,还给出了一些常见的内存调优方法和内核调整参数。

另外,此文是我总结的思维导图导出后调整格式发布的,由于思维导图太大了,放图片的话会模糊,关于思维导图,如需要的话可私聊。

目录

内存瓶颈

特征

原因

性能优化措施

内存指标

物理内存和逻辑内存

进程内存

系统内存

内存调优常用工具

内存泄露

原因

影响

如何定位

生产环境

为什么剩余内存很多的情况下,也会发生 Swap

内存回收

匿名页(动态分配的堆内存)

文件页

如何解决回收内存会产生磁盘IO这种影响?

如何调整内存回收时回收的是哪种类型内存呢?

内核里有一个线程kswapd0会定期扫描,进行内存回收

内核内存参数优化

/proc/sys/vm/swappiness

/proc/sys/vm/panic_on_oom

/proc/sys/vm/nr_pdflush_threads

/proc/sys/vm/min_free_kbytes

关于脏数据处理方法的一些内核参数


  1. 内存瓶颈

    1. 特征

      1. 可用内存(available)持续减少,系统进程中kswapd进程频繁出现,同时Swap交换空间占用率持续增高

    2. 原因

      1. 一种是应用程序bug导致内存资源耗尽;另一种是确实内存资源不足
        1. 解决方法:针对第一种情况,需要从应用程序角度来排查问题。如果出现第二种情况,就要考虑增加内存资源了
    3. 性能优化措施

      1. 关掉操作系统上用不到的服务
      2. 增加内存
        1. 需要注意的是在内存充足的情况下,如果再增加内存的话,内存瓶颈就会转为CPU瓶颈,因为CPU的运行速度也就是每秒内执行的机器指令数量是有限的
      3. 通过cgroups等措施限制进程内存使用
      4. 非必要不使用swap,如果必须用swap,调整Swapiness,降低内存回收时使用swap的机率
        1. 临时调整
          1. sysctl vm.swapiness=10   临时设置swapiness为10
        2. 永久调整
          1. vim /etc.sysctl.conf   vm.swapiness=1
      5. 减少内存的动态分配
        1.  使用bigpages、hugetlb和共享内存调优。
      6. 优化操作系统虚拟内存参数(如/proc/sys/vm)。
      7. 尽量使用缓存和缓冲区来访问数据
        1. 使用堆栈时,明确声明其内存空间来存储需要缓存的数据
        2. 用redis这类的外部缓存组件,来优化数据访问
      8. 保护核心应用不被OOM杀死
        1. 通过/proc/pid/oom_abj调整oom_score
        2. 保证内存紧张时,核心应用也不会被OOM KILL
  2. 内存指标

    1. 物理内存和逻辑内存

      1.  物理内存就是系统硬件提供的内存大小,是真正的内存。
      2. 逻辑内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存区域,用作逻辑内存的磁盘空间被称为交换空间(Swap Space)
    2. 进程内存

      1. 虚拟内存VSS
        1. 已经申请,但是并未分配物理内存,也称作虚拟内存
        2. 包括了进程代码段、数据段、共享内存、已经申请的堆内存和已经换出的内存
      2. 共享内存
        1. 包括与其他进程共同使用的真实的共享内存
        2. 包括了加载的动态链接库以及程序的代码段等
      3. 常驻内存RSS
        1. 是进程实际使用的物理内存,不包括共享内存和swap
        2. 系统内存使用率是常驻内存占整个系统的总内存百分比
      4. 独占内存USS
        1. USS(Unique Set Size):进程独自占用的内存,它只计算了进程独自占用的内存大小,不包含任何共享的部分。默认是USS
      5.  按比例分配共享内存后的物理内存PSS(Proportional Set Size)
        1. 所有进程的PSS之和就是系统的内存使用量
        2. 它将共享内存的大小进行平均后,再分摊到各进程上去
      6. swap内存
        1. swap是linux中时间换空间的一种操作,当swap空间占用多,频繁换入换出,会导致系统很卡顿
        2. swap是指通过 Swap 换出到磁盘的内存
    3. 系统内存

      1. 已用内存
      2. 剩余内存
      3. 共享内存
        1. 是通过 tmpfs 实现
        2. 大小也就是 tmpfs 使用的内存大小
      4. 可用内存
        1. 包括剩余内存和可回收缓存
      5. 缓存
        1. 磁盘读取文件的页缓存
        2.  Slab 分配器中的可回收内存
      6. 缓冲区
        1. 缓存了将要写入磁盘的数据
        2. 内核就可以把分散的写集中起来,统一优化磁盘写入
      7. 缺页异常
        1. 次缺页异常
          1. 直接从系统物理内存分配
        2. 主缺页异常
          1.  从swap等需要磁盘IO介入的部分 分配
      8. sawp使用情况
        1. 换入速度
          1. 每秒换入的内存大小
        2. 换出速度
        3. 每秒换出的内存大小
        4. 已用空间
        5. 剩余空间
  3. 内存调优常用工具

    1. free
    2. smem
      1. 可以查看每个进程的物理内存使用情况
    3. vmstat
      1. 可以观察内存的变化情况
    4. pmap
      1. 查看进程的内存分布
    5. sar
    6. cachetop
    7. pmap
    8. cachestat
  4. 内存泄露

    1. 原因

      1. 使用完内存空间后忘记释放了
          1. 当我们不知道使用的数据大小时,会使用malloc()在程序中动态分配内存
          2.  系统就会从内存空间的堆中分配内存
          3.  使用后忘记释放会出现内存泄漏风险
          1. 分配的局部变量
          2. 由系统进行内存管理,不会出现内存泄漏问题
        1. 其他内存段
          1. 只读段
            1. 包括程序的代码和常量,只读的不会分配新内存,所以不会产生内存泄漏
          2. 数据段
            1. 包括全局变量和静态变量
            2. 在定义时候已经定好了大小,也不会产生memoryleak
          3. 内存映射段
            1. 包括动态链接库和共享内存
            2. 共享内存由程序动态分配和管理,因此在程序使用后忘记回收,就会导致和堆内存类似的泄露问题
    2. 影响

      1. 泄露的内存不断累积,造成内存浪费,系统无法为新进程分配内存,swap交换分区如打开的话会进行回收,并且剩余内存不多的话系统会开启内存回收,这将进一步导致IO问题
    3. 如何定位

      1. vmstat查看内存变化趋势
      2. memleak查看内存分配,从而定位是哪个程序内存异常
      3. 进入程序内部,查看代码,是否没有释放内存
      4. 生产环境

        1. 生产环境中除了一些程序错误导致内存迅速发生异常(这类用工具可以很容易发现),还可能会出现一些慢性积累过程,比如说一些缓慢的内存增长,用vmstat几乎看不到变化趋势,但是长此以往,对内存的消耗很大,这种情况下可以上监控,监控可以看到内存指标增长的趋势
  5. 为什么剩余内存很多的情况下,也会发生 Swap

    1. 处理器架构NUMA导致的
      1. NUMA  is(Non-Uniform Memory
        Access)
      2. 在 NUMA 架构下,多个处理器被划分到不同 Node 上,且每个 Node 都拥有自己的本地内存空间。
        1. 一个node内部的内存空间可分为不同的内存域(Zone)
          1. 直接内存访问区(DMA)
          2.  普通内存区(NORMAL)
          3.  伪内存区(MOVABLE)
          4.   ....
        2. numactl --hardware可以查看处理器在不同node上的分布情况
        3. 当某一个node内存不足时,可以从其他node回收内存
          1. /proc/sys/vm/zone_reclaim_mode 可以调节回收方式
          2.  默认是0,可以从其他node找空闲内存或从本地回收内存
          3. 1表示内存回收只会发生在本地节点内
          4. 2表示可以回写Cache中脏数据到磁盘来回收内存
          5. 4表示可以使用swap回收内存
  6. 内存回收

    1. 匿名页(动态分配的堆内存)

      1. 不可直接回收
        1. swap将匿名页先写到磁盘,然后再回收内存
        2. 当需要访问这部分匿名页时,再从swap中读取即可
    2. 文件页

      1. 可直接回收
        1. 文件页(包括缓存和缓冲区)
      2. 不可直接回收
        1. 脏页
          1. 需要先写入磁盘再进行回收
            1. 通过系统调用fsnc同步写入
            2. 系统的内核线程pdflush刷新脏页
    3. 如何解决回收内存会产生磁盘IO这种影响?

      1. 调整swapiness
        1. 回收匿名页(swapiness较大)一定会发生换入换出行为,产生磁盘IO,因此可以尝试降低 swappiness 的值,减少内存回收时 Swap 的使用倾向
        2. 回收文件页(swapiness较小)在回收干净页时不会发生磁盘写入行为,也就没有磁盘IO
      2. 尽早触发系统内存回收
        1. kswapd是后台内存回收机制,它是异步的,不会阻塞进程。
      3. 除非有必要使用swap,禁用swap
      4. 响应延迟敏感的应用,如果它们可能在开启 Swap 的服务器中运行,你还可以用库函数mlock() 或者 mlockall() 锁定内存,阻止它们的内存换出
    4. 如何调整内存回收时回收的是哪种类型内存呢?

      1. /proc/sys/vm/swappiness
        1. swappiness越小,越倾向于回收文件页
        2. swapiness越大,越倾向于回收匿名页
        3. 范围是0-100,表示的是一种倾向,当为0时也不是表示回收内存完全不用匿名页,当空心内存加上文件页仍小于pages_low,还是会用Swap
    5. 内核里有一个线程kswapd0会定期扫描,进行内存回收

      1. 一旦剩余内存小于pages_min即页低阈值,就会触发内存的回收
      2. 页低阈值可以通过/proc/sys/vm/min_free_kbytes来设置
  7. 内核内存参数优化

    1. /proc/sys/vm/swappiness

      1. 表示使用Swap分区的概率
      2. 默认60,这是一个相对中和的配置,所以系统会根据实际运行情况,选择合适的回收类型
      3. 在一些数据库服务器上,如Redis、HBase机器上,应该设置0~10之间,表示最大限度使用物理内存。
      4. swappiness=100时表示积极使用Swap分区,并且把内存上的数据及时搬运到Swap空间里面
      5. swappiness=0时表示最大限度使用物理内存,然后才是Swap空间
    2. /proc/sys/vm/panic_on_oom

      1. 表示内存不够时内核是否直接panic
      2. 默认值为0,表示当内存耗尽时,内核会触发OOM killer杀掉最耗内存的进程。
        1. 根据 oom_score来杀死,在/proc/${pid}/oom_score   越高的分数意味着越可能被kill,这个数值是根据oom_adj运算后的结果,是oom_killer的主要参考。
        2. /proc/[pid]/oom_adj 取值-17~15  越高的权重,意味着更可能被oom killer选中,-17表示禁止被kill掉。
      3. 设置为1表示在OOM时系统会panic(恐慌)
        1. 为了不让系统自动kill掉进程,需要设置此值为1。
    3. /proc/sys/vm/nr_pdflush_threads

      1. 表示当前正在运行的pdflush进程数量,在I/O负载高的情况下,内核会自动增加更多的pdflush进程。
    4. /proc/sys/vm/min_free_kbytes

      1. 表示强制Linux VM最低保留多少空闲内存
      2. 默认值为90112(88M物理内存,CentOS7版本),保持默认即可。
      3. pages_low = pages_min*5/4
        pages_high = pages_min*3/2
    5. 关于脏数据处理方法的一些内核参数

      1. /proc/sys/vm/dirty_writeback_centisecs
        1. 控制内核的脏数据刷新进程pdflush的运行间隔
        2. 单位是(1/100)s。默认值是500,也就是5s
        3. 如果系统是持续地写入动作,那么建议降低这个数值,这样可以把尖峰的写操作削平成多次写操作;
        4. 如果系统是短期地尖峰式的写操作,并且写入数据不大且内存又比较富裕,那么应该增大此数值。
      2. /proc/sys/vm/dirty_ratio
        1. 参数指定了当文件系统缓存脏数据数量达到系统内存百分之多少时,系统不得不开始处理缓存脏页
        2. 如果触发了这个设置,那么新的I/O请求将会被阻挡,直到脏数据被写进磁盘。这是造成I/O卡顿的重要原因,但这也是保证内存中不会存在过量脏数据的保护机制
        3. 在磁盘写入不是很频繁的场景,适当增大此值
        4. 如果是持续、恒定的写入场合,应该降低其数值。

你可能感兴趣的:(运维,笔记,linux,服务器,运维)