RHCA08内存管理
内存调优、溢出与泄露及相关架构笔记
一、内存调优
(一)内存过量分配
- 物理内存与虚拟内存概念
- 虚拟地址空间特性:每个进程拥有独立线性连续地址空间,地址范围因架构而异,x86架构和x86_64架构(RHEL8系统)支持不同的最大地址空间。
- 物理地址空间特性:借助MMU(内存管理单元)完成地址转换,物理页可非连续分布,内存页来源包括RAM和swap空间。
- 虚拟内存与物理内存关系
- 虚拟内存本质:是应用程序申请的内存空间(如Firefox浏览器占用的内存),呈现为连续的线性地址空间。32位架构和64位架构支持不同范围的地址空间,且虚拟内存必须映射到物理内存,swap空间也属于物理内存的一部分。
- 内存页大小与分配
- 页大小标准:x86架构默认4096字节(4KB),ARM架构默认65536字节(64KB)。
- 分配特性:内存管理的最小单位是页(类似文件系统的block size),应用程序至少占用一个页的空间,可通过命令
getconf -a | grep -i pagesize
查看系统页大小。
- 应用程序内存占用示例:以Firefox进程ID 5141为例,其虚拟内存和物理内存占用有相应数值,且所有内存分配均为页大小的整数倍(如4KB的倍数),可通过
pmap
命令查看进程内存映射详情,内存地址编号显示为连续的虚拟地址空间。 - 基本概念与配置参数
- 基本概念:又称overcommit或内存复用,允许分配的内存超过实际物理内存,在虚拟化中称为内存共享(如华为实现150%超分配)。
- 配置参数:
vm.overcommit_memory
有三种模式,0为试探性过量分配(heuristic overcommit),1为总是允许过量分配(always overcommit),2为基于交换空间加内存百分比(commit all swap plus RAM percentage);vm.overcommit_ratio
控制过量分配比例。 - 应用场景:主要用于虚拟化环境提高资源利用率,需特别注意实际内存使用监控,实验演示中部分功能效果未完全展示。
- 内存过量分配机制
- 测试工具:课程专门开发的bigmem程序,用于模拟大内存分配场景,且必须使用红帽8系统中的bigmem版本,因其新增了试探策略。
- 过量分配策略类型
- 策略0(默认):试探性过量分配,系统根据当前资源情况谨慎分配,实际分配量不超过物理内存+swap,测试中分配3.5GB(1.5G内存+2G swap)后无法继续分配更大内存。
- 策略1:无条件过量分配,允许应用程序申请任意大小的虚拟内存,可能导致系统崩溃,测试中可成功分配20GB虚拟内存(实际物理内存不足)。
- 策略2:基于公式的分配,允许分配量= swap总量 + (物理内存×overcommit_ratio%),默认比例50%(可通过
vm.overcommit_ratio
调整)。
- 关键参数说明:
vm.overcommit_memory
是策略选择开关(0/1/2),vm.overcommit_ratio
仅策略2有效,设置物理内存的过量分配百分比。测试验证,当ratio=50%时,最大可分配3GB(2G swap + 1.5G×50%);调整ratio=150%后,可分配4GB(2G swap + 1.5G×150%)。 - 应用场景对比:策略0适用于常规服务器环境,保证系统稳定性;策略1适用于虚拟化环境,确保虚拟机能够启动(不保证性能);策略2适用于需要精确控制内存分配的企业级应用。操作建议,虚拟化环境中可适当提高overcommit_ratio(如150%)。
- 实验操作记录:策略1下分配超大内存可能导致进程被OOM killer终止,生产环境修改前需评估业务需求和服务承载能力。
(二)通过缓存提升读性能
- 缓存机制:系统会将读取的文件内容保留在内存中,形成读缓存。
- 性能提升原理:当再次读取相同文件时,直接从内存读取而非磁盘,显著提高读取速度。
- 操作示例:清空缓存命令为
sysctl -w vm.drop_caches=3
;首次复制耗时real 0m0.640s
,缓存命中后复制耗时real 0m0.098s
(速度提升约6.5倍)。 - 缓存类型:读缓存专门用于提升读性能,与写缓存机制不同。
(三)利用脏页提升写性能
- 脏页机制:系统将写入操作先在内存中缓存(形成脏页),延迟写入磁盘。
- 性能提升原理:将随机IO在内存中整合为顺序IO,减少磁盘寻道时间,提高写入效率。
- 监控方法:查看脏页大小可使用命令
cat /proc/meminfo | grep Dirty
,实时监控命令为watch -n .5 cat /proc/meminfo | grep Dirty
。 - 内存状态指标:Dirty值表示待写入磁盘的数据量(示例中为8kB),其他相关指标包括Writeback(正在回写的数据量)、Buffers、Cached等。
(四)内存调优参数设置
- 脏页比例设置:系统整体脏页比例上限为30%(
vm.dirty_ratio=30
),单个进程脏页比例上限为10%(vm.dirty_background_ratio=10
),脏页回收时间设置为3000厘秒(vm.dirty_expire_centisecs=3000
),脏页回写间隔为500厘秒(vm.dirty_writeback_centisecs=500
)。 - 内存交换策略:通过swappiness参数控制内存交换倾向,取值范围0-100,默认值60。低值(接近0)优先保留内存缓存,减少交换;高值(接近100)更积极使用交换空间。在内存紧张时需要权衡缓存释放与交换使用。
(五)内存溢出OOM解决方案
- 内存溢出Killer
- 定义:当系统所有内存(包括swap)都被占用时触发的保护机制,通过终止进程防止系统崩溃。
- 触发条件:物理内存和交换空间全部耗尽,系统处于"all memory active"状态。
- 工作机制:具有自救机制,优先杀死特定进程而非导致系统死机;在
/var/log/messages
中记录"Out of memory: Kill process"事件;基于oom_score值决定终止进程的优先级。 - 关键文件:
/proc/[pid]/oom_adj
用于调整进程被杀优先级(-17到15),/proc/[pid]/oom_score
是计算得出的被杀概率值,/proc/sysrq-trigger
可手动触发内存管理操作。 - 参数调整:取值范围为-17(最不可能被杀)到15(最可能被杀),值越小进程存活概率越高。oom_score由系统根据内存占用和oom_adj值动态计算,用户不可直接修改。
- 系统请求功能:触发方式为
echo f > /proc/sysrq-trigger
,作用是模拟内存紧张场景,主动调用OOM killer,会生成"Manual OOM execution"系统日志。
- 例题:vsftpd内存调整
- 操作步骤:查找进程ID使用
pidof vsftpd
,进入进程目录执行cd /proc/[pid]
,然后调整保护级别。 - 验证方法:通过
tail -f /var/log/messages
观察kill事件,测试不同oom_adj值对应的oom_score变化规律。 - 注意事项:新版系统推荐使用
oom_score_adj
替代oom_adj
;关键服务应设置为负值(如-17),非关键服务可设为正值;无法设置为超出-17~15范围的值,尝试设置-18会报错。
- 操作步骤:查找进程ID使用
二、内存溢出
(一)内存溢出解决方案
- OOM Killer机制:当系统内存耗尽时,内核会扫描所有进程,根据oom_score值决定杀死哪个进程。
- 评分标准:进程的oom_score值范围是0-1000,值越高越容易被杀死。例如vsftpd进程被杀死是因为其score值为999。
- 处理流程:系统会优先杀死分数最高的进程,如果问题未解决则继续杀死其他进程。
(二)out of memory killer
- 参数调整:通过
/proc/pid/oom_adj
文件可以调整进程的OOM优先级。 - 优先级规则:取值范围-17到15,值越小优先级越高(越不容易被杀死)。
- 持久化设置:在服务启动脚本中通过
echo -17 > /proc/[pid]/oom_adj
实现永久生效。 - 死机相关
- 死机触发命令:模拟命令
echo c > /proc/sysrq-trigger
可模拟系统崩溃;强制重启命令echo b > /proc/sysrq-trigger
会立即重启系统且不保存数据。 - 死机场景模拟:执行上述命令后系统完全无响应,必须强制重启,且非正常关机可能导致日志无法完整写入磁盘。
- 死机触发命令:模拟命令
(三)开机生效问题
- 服务脚本:在
/etc/systemd/system/[service].service.d/
目录下创建conf文件。 - 执行时机:使用ExecStartPost参数确保服务启动后执行设置命令。
- 优势:相比rc.local更可靠,服务重启后设置依然有效。
(四)应用案例
- 例题:内存优化设置
- 关键步骤:确定服务进程ID,修改oom_adj值为-17,通过systemd服务配置实现持久化。
- 验证方法:查看
/proc/[pid]/oom_score
确认优先级,模拟内存压力测试观察进程是否被杀死。
三、内存泄露
(一)内存泄露概念
- 定义:应用程序未能正确释放已分配的内存。
- 典型表现:程序运行时占用内存持续增长,重启后恢复正常。
- 危害:长期运行会导致系统性能下降甚至崩溃。
(二)检测工具
- valgrind:Linux系统自带的内存调试工具,检测原理是跟踪程序内存分配和释放操作,典型场景是开发人员用于检测代码中的内存管理问题。
- 其他内存检查工具
- 工具安装:使用光盘自带的y-tools=memory check工具包进行安装。
- 基本检测:执行命令
ls
可查看内存使用汇总,正常情况下应显示"没有内存泄露";通过运行big memory 512M
程序模拟内存泄露场景,该程序会产生进程ID(如3438)。 - 内存泄露分析:工具会显示"可能的丢失"提示,如检测到139KB内存泄露;字节数除以1024可转换为KB单位(如139KB);正常程序运行后应显示"没有内存线路",与异常程序形成对比。
- 高级诊断参数:添加
--track-origins=yes
参数可精确定位到源代码问题行(如309行);注意程序文件可能带有特殊权限(如sui ds gid),需使用chmod
修改权限才能执行;编译后的程序可通过/usr/share/doc/big_memory/src
路径查找对应源代码。 - 运维注意事项:运维人员只能检测内存泄露,修复需开发人员修改代码(如309行的vg_reply函数);内存泄露会导致程序反复异常,仅靠kill命令无法彻底解决问题;应针对持续占用资源异常的特定进程进行检查,而非全系统扫描。
四、应用案例
(一)共享内存与内存优化
- 共享内存基础概念
- 定义:共享内存是多个应用程序可以共享同一段内存的机制,在数据库中使用特别频繁(如Oracle、MySQL等)。
- 实现方式:通过内核参数设置,主要参数包括
kernel.shmmax
、kernel.shmall
等。 - 数据库应用:Oracle数据库通过共享内存实现SGA(System Global Area)系统全局区域,一个SGA对应一个共享内存段。
- 共享内存关键参数
shmmax
:单个共享内存段的最大大小(单位:字节)。shmall
:系统中总共可分配的共享内存页数(单位:页)。shmmni
:系统支持的最大共享内存段数量(默认4096个)。- 参数关系:类比"土地管理"概念 - 有多少块地(shmmni)、每块地多大(shmmax)、总共能分配多少资源(shmall)。
- 实际调优案例
- 问题现象:DB2数据库内存持续增长,系统运行523天后内存使用26GB/32GB,swap使用18GB/32GB。
- 诊断过程:使用
top
命令发现db2cc进程占用40GB虚拟内存,pmap
命令分析内存使用情况,发现shm(共享内存)占用过高,检查发现shmall参数被设置为16777216页(约64GB)。 - 解决方案:调整共享内存参数,降低shmall值,使系统能及时释放不常用的缓存数据。
- 内存与磁盘互换技术
- swap交换空间:原理是当内存紧张时,将硬盘空间临时充当内存使用,本质不提升性能,仅防止内存溢出;监控命令
top
、ps
、sar
等可查看进程内存和CPU占用。 - tmpfs内存文件系统:原理是将内存当作磁盘使用来提升写入性能(特别是随机小IO场景),内存速度是硬盘的10倍,适合缓存服务器等场景。
- 应用案例:Squid代理服务器缓存目录挂载到tmpfs,Spark内存计算框架的过程数据存储。
- 配置方法:默认大小为内存一半,重启后数据丢失,可通过
/etc/fstab
永久配置。
- swap交换空间:原理是当内存紧张时,将硬盘空间临时充当内存使用,本质不提升性能,仅防止内存溢出;监控命令
- 性能对比实验
- 硬盘写入测试:速度约5.1MB/s(200MB数据耗时约40秒)。
- 内存写入测试:速度约649MB/s(200MB数据耗时约0.3秒)。
- 监控方法:通过
free
命令观察共享内存变化(写入后shmem从16MB增至216MB)。
五、非一致性内存访问
(一)一致性内存访问
- 定义:传统架构中CPU通过前端总线(FSB)与内存通信,所有CPU访问内存的延迟相同。
- 特点:数据必须调入CPU才能处理(如计算1加到100=5050);内存作为非持久化存储设备,在硬盘和CPU间起缓冲作用;遵循冯·诺依曼架构设计。
- 瓶颈:当CPU核心数增加(如28核56线程)时,前端总线成为性能瓶颈。
(二)非一致性内存访问的发展
- 解决方案:NUMA架构将CPU和内存分组为多个node,每个node包含若干CPU和本地内存(如4个node,每个含48个处理器),程序优先使用本地node资源。
- 城市分区类比:类似武汉分武昌区、洪山区等行政区,办身份证只需去所在区政务中心,无需全市集中办理。
- 优势:减少总线通信压力,遵循就近访问原则(内存访问距离:本地node=10,远程node=21)。
(三)numa命令
- 查看命令:
numactl --hardware
,可显示各node的CPU数量、内存使用情况以及输出距离矩阵(如node0到node0=10,node0到node1=21)。 - 拓扑特点:全互联架构(任意node间可直接通信),远程访问距离相等(所有跨node访问均为21)。
- 资源调度:系统监控各node剩余内存,本地资源不足时自动选择空闲最多的远程node。
(四)虚拟化内存复用
- 华为FusionComputer实现:创建集群时可开启"内存复用"开关,关闭时虚拟机总内存≤物理内存(如256G),开启时允许超额分配内存。
- "虚拟机NUMA结构自动调整"功能:开启后尽量将虚拟机的CPU和内存分配在同一node,未指定时自动均衡分布在各node。
- 应用场景选择:需要低延迟时集中分配在单个node,需要高吞吐时均衡分布在多个node。