内存刷脏机制触发的系统故障案例一则

2024-02-05 21:52

本文主要是介绍内存刷脏机制触发的系统故障案例一则,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  关键词

  • linux、centos
  • cpu load、cpu iowait、sar监控、大页内存
  • vm.dirty_background_ratio、vm.dirty_ratio、vm.min_free_kbytes

     There are many things that can not be broken!

     如果觉得本文对你有帮助,欢迎点赞、收藏、评论!

一、问题现象

某数据库主机接连在几天里出现莫名hang死现象,造成业务中断,故障时间段,出现数据库连接数升高,cpu有陡增,cpu iowait time陡增,从监控曲线看cpu load负载过高,并伴随有大量的IO操作、事务等待会话、tps以及慢SQL,由于负载升高导致数据库自动主从切换失败,造成业务一定的中断影响。

二、问题分析

1、在集中复盘这几次故障中,发现故障主机几次故障之前出现过剩余内存严重不足情况,主机内存:377G,几乎耗尽,将故障原因怀疑的方向定位在是zone内存剩余达到min水位线导致直接内存回收,用户申请内存被阻塞,只有内核态可以正常申请剩余内存。

这种情况下,系统中剩余的内存极少,少到可能连回收内存操作本身需要的内存都不够,当 free 内存降到了 min 水线以下,此时如果操作系统忽然需要通过伙伴系统为用户进程分配一大块内存,或者需要创建一个很大的缓冲区,而当时系统中的内存没有办法提供足够多的物理内存以满足这种内存请求,这时候,操作系统就必须尽快进行页面回收操作,以便释放出一些内存空间从而满足上述的内存请求,这种页面回收方式也被称作"直接页面回收",这个过程会阻塞申请内存的进程,被阻塞进程的内存分配延迟就会提高,从而感受到卡顿。

随后检查操作系统内存回收上的参数配置情况,发现此时的脏页vm.dirty_ratio过小,在此过程中很多应用进程可能会因为系统转而处理文件IO而阻塞。

2、同时发现主机pagetables达到70G以上,建议数据库配置大页。使用大页(huge page)能够缩小page tables,减少cpu在内存管理上的的系统开销,提高性能。 

三、处理过程

1、调整刷脏配置
vm.dirty_background_ratio = 50 
vm.dirty_ratio = 80
vm.min_free_kbytes 为4G


2、配置大页,降低pagetables占用内存。

四、知识拓展

1、sysctl中的那些参数控制页高速缓存的参数

  • vm.vfs_cache_pressure (默认值 = 100)
    • 默认值vfs_cache_pressure=100,在回收页高速缓存(page cache)和交换缓存(swap cache)时,内核会以"相对公平"的比例回收dentries和inodes。
    • 调整内核更趋向于回收内存中保存的目录项缓存(dentry)和索引节点对象 (inode objects)。
    • 减少vfs_cache_pressure值,会使内核更倾向于保留目录项对象(dentry)以及索引节点缓存(inode caches); 增加vfs_cache_pressure 超过100 会使内核更倾向于释放目录项对象(dentry)以及索引节点缓存(inode caches)。
    • 可以通过增加vfs_cache_pressure的值,来使内核更倾向于释放上述缓存,从而限制页高速缓存(page cache)的大小。
  • vm.dirty_background_ratio (默认值 = 10)
    • 此参数的值代表脏页占总内存的百分比, 当系统中脏页数量达到此值时,内核线程pdflush开始把脏页数据写入存储。
    • 可以通过减少此值,来使pdflush进程更早把脏页写入存储,从而限制页高速缓存的大小。
  • vm.dirty_ratio (默认值 = 20)
    • 这个参数则指定了当文件系统缓存脏页数量达到系统内存百分之多少时(默认值20%),系统不得不开始处理缓存脏页(因为此时脏页数量已经比较多,为了避免数据丢失需要将一定脏页刷入外部存储);在此过程中很多应用进程可能会因为系统转而处理文件IO而阻塞。
    • 减少此值可使 系统更早来处理内存中的脏页,从而限制页高速缓存的大小。
  • vm.dirty_writeback_centisecs (Red Hat Enterprise Linux 4 & 5: 默认值 = 499, Red Hat Enterprise Linux 6 and 7: 默认值 = 500)
    • pdflush进程会定时被唤醒,把脏页中的数据写入硬盘。单位是 1/100 秒。缺省数值是500,也就是pdflush进程5秒钟会被唤醒一次。
    • 减少此值可以更频繁的唤醒pdflush进程来处理脏页, 从而限制页高速缓存的大小。
  • vm.dirty_expire_centisecs (Red Hat Enterprise Linux 4 and 5: 默认值= 2999, Red Hat Enterprise Linux 6 and 7: 默认值 = 3000)
    • 这个参数声明Linux内核写缓冲区里面的数据多“旧”了之后,被唤醒的pdflush进程就开始考虑写到磁盘中去。单位是 1/100秒。缺省是 30000,也就是 30 秒的数据就算旧了,pdflush进程被唤醒后,将会把“旧”的数据写入磁盘。
    • 减少此值意味着脏页会更快变“旧”,并被pdflush进程写入磁盘,从而限制页高速缓存的大小。
  • vm.swappiness (RHEL 5 and 6:默认值 = 60, RHEL 7:默认值 = 30)
    • 此参数控制内核是否更趋向于交换非活动内存页页至交换分区(此值越高,代表非活动内存页越可能被交换至交换分区)。
    • 减少此值使内核更倾向于保持非活动内存页在物理内存中,从而释放页高速缓存中的页, 从而限制页高速缓存的大小。

2、如何查看你的脏页刷脏情况

使用sar命令,重点关注pgscank指标,格式

sar  -B  1 5        

pgpgin/s:表示每秒从磁盘或SWAP置换到内存的字节数(KB)
pgpgout/s:表示每秒从内存置换到磁盘或SWAP的字节数(KB)
fault/s:每秒钟系统产生的缺页数,即主缺页与次缺页之和(major + minor)
majflt/s:每秒钟产生的主缺页数 pgfree/s:每秒被放入空闲队列中的页个数
pgscank/s:每秒被 kswapd 扫描的页个数
pgscand/s:每秒直接被扫描的页个数
pgsteal/s:每秒钟从 cache 中被清除来满足内存需要的页个数
%vmeff:每秒清除的页(pgsteal)占总扫描页(pgscank + pgscand)的百分比

这篇关于内存刷脏机制触发的系统故障案例一则的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/682277

相关文章

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

SpringRetry重试机制之@Retryable注解与重试策略详解

《SpringRetry重试机制之@Retryable注解与重试策略详解》本文将详细介绍SpringRetry的重试机制,特别是@Retryable注解的使用及各种重试策略的配置,帮助开发者构建更加健... 目录引言一、SpringRetry基础知识二、启用SpringRetry三、@Retryable注解

Python中使用正则表达式精准匹配IP地址的案例

《Python中使用正则表达式精准匹配IP地址的案例》Python的正则表达式(re模块)是完成这个任务的利器,但你知道怎么写才能准确匹配各种合法的IP地址吗,今天我们就来详细探讨这个问题,感兴趣的朋... 目录为什么需要IP正则表达式?IP地址的基本结构基础正则表达式写法精确匹配0-255的数字验证IP地

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

SpringKafka错误处理(重试机制与死信队列)

《SpringKafka错误处理(重试机制与死信队列)》SpringKafka提供了全面的错误处理机制,通过灵活的重试策略和死信队列处理,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、Spring Kafka错误处理基础二、配置重试机制三、死信队列实现四、特定异常的处理策略五

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

java中反射(Reflection)机制举例详解

《java中反射(Reflection)机制举例详解》Java中的反射机制是指Java程序在运行期间可以获取到一个对象的全部信息,:本文主要介绍java中反射(Reflection)机制的相关资料... 目录一、什么是反射?二、反射的用途三、获取Class对象四、Class类型的对象使用场景1五、Class