available还有141G为什么就开始用swap了
free cache swap关系梳理
free -h
total used free shared buff/cache available
Mem: 503Gi 341Gi 10Gi 2.6Gi 150Gi 141Gi
Swap: 63Gi 9.9Gi 54Gi
available还有141G为什么就开始用swap了
核心原因是Linux 内核的 swap 调度机制并非只在物理内存耗尽时才使用swap,而是由vm.swappiness参数控制内存交换的倾向,即使available有大量空闲,内核也可能会主动将部分内存页换入swap,再结合系统内存的页类型特性,就会出现你看到的现象。
结合你503Gi内存、141Gi available但已用9.9Gi swap的场景,拆解具体原因和验证/优化方法如下:
一、最核心因素:vm.swappiness 配置并非0(大数据/集群环境的关键问题)
vm.swappiness是Linux内核的核心参数,取值0~100,代表内核将匿名内存页(进程的堆/栈等,无法被释放的内存) 换入swap的倾向程度:
0:内核尽可能不使用swap,仅在物理内存完全耗尽(OOM前)才会触发交换(大数据/Hadoop/Spark/Doris等集群节点必须配置0);1~10:极低的交换倾向,仅在系统内存压力极大时轻微使用;- 默认值通常为60:这是通用服务器的配置,内核会主动且频繁地将闲置的匿名内存页换入swap,为物理内存腾出更多空间作为
buff/cache,提升磁盘IO性能——但这个逻辑对大数据集群(纯内存计算、对swap延迟极度敏感) 完全不适用,也是你这个场景的主要问题。
立即验证当前swappiness配置:
cat /proc/sys/vm/swappiness
大概率结果是60,这就是为什么内存充足还会用swap的根本原因。
二、次要因素:内存页的类型特性(available≠可直接回收的内存)
free -h中的available是系统预估可分配给新进程的内存,包含3部分:
- 真正的空闲内存(free);
- 可回收的buff/cache(页缓存、目录项等,内核可随时释放);
- 可交换的匿名内存页(需换入swap才能释放)。
但内核对不同内存页的处理逻辑不同:
buff/cache:属于文件页,可以无成本直接释放,内核不会主动将其换入swap;- 匿名内存页:属于进程的私有内存(如Spark Executor、Doris BE的堆内存),无法直接释放,内核会根据
vm.swappiness的配置,将暂时闲置的匿名内存页换入swap——这部分交换和available大小无关,只和内核的交换倾向有关。
简单说:你的141Gi available中,大概率包含大量可回收的buff/cache(你这里buff/cache有150Gi),但内核优先选择将闲置的匿名页换入swap,而非释放buff/cache,最终就出现了swap被使用的情况。
三、针对大数据集群的解决方案(一步到位,彻底解决)
你的环境是大数据平台(503Gi大内存、Doris/Spark/Hadoop类组件),必须让内核彻底放弃swap,按以下步骤操作(永久生效,适配集群场景):
步骤1:临时生效(立即停止swap交换,无需重启)
# 1. 临时将swappiness设为0,内核立即停止主动交换
sudo sysctl vm.swappiness=0
# 2. 将已用的swap换回到物理内存(关键:把9.9Gi swap的内容切回内存)
sudo swapon -a && sudo swapoff -a
步骤2:永久生效(重启后不还原,集群生产环境必做)
# 编辑sysctl配置文件
sudo vim /etc/sysctl.conf
# 添加/修改以下两行(确保无重复,重复则删去原有行)
vm.swappiness=0
vm.zone_reclaim_mode=0 # 多核NUMA架构服务器必加,防止节点内内存局部回收触发swap
# 生效配置
sudo sysctl -p
步骤3:配合之前的永久关闭swap操作(彻底杜绝swap使用)
确保已按之前的方法注释/etc/fstab中的swap配置,并执行sudo swapoff -a,彻底关闭swap分区,从根本上避免内核访问swap。
四、验证优化效果
操作完成后,依次执行以下命令,确认swap不再被使用:
- 检查swappiness:
cat /proc/sys/vm/swappiness→ 结果为0; - 检查swap使用:
free -h→ Swap的used逐步变为0(swapoff后立即生效); - 长期监控:
vmstat 1→ 观察si(swap入)、so(swap出)列,持续为0即表示无swap交换。
五、补充说明(大数据集群的内存优化关键)
- 为什么大数据集群必须禁用swap?
swap是磁盘级别的存储,读写速度比物理内存慢数万倍,而Spark/Doris/Flink等组件是纯内存计算,一旦进程访问到被换入swap的内存页,会出现严重的性能卡顿、任务超时、节点假死,即使只有少量swap使用,也会对集群性能造成不可逆的影响。 - zone_reclaim_mode=0的作用?
你的503Gi大内存服务器大概率是NUMA架构(多CPU节点),默认zone_reclaim_mode=1会让内核在单个NUMA节点内存不足时,优先回收该节点的内存(甚至触发swap),而非使用其他NUMA节点的空闲内存,配置为0后,内核会跨NUMA节点分配内存,避免局部内存压力触发swap。 - available充足的情况下,关闭swap无任何风险
你的服务器used341Gi、available141Gi,内存压力极低,关闭swap并将swappiness设为0后,内核会完全使用物理内存,不会出现OOM,反而会提升大数据组件的运行效率。
最终总结
你这个场景的问题是通用服务器的swap配置不适用于大数据集群:默认vm.swappiness=60让内核主动使用swap,和available内存大小无关。只需将swappiness设为0+永久关闭swap分区,就能彻底解决内存充足但使用swap的问题,这也是大数据平台(Hadoop/Doris/Spark/Iceberg)节点的标准优化配置。
swap和内存的换入换出能有多少性能损耗
swap与物理内存的换入换出(si/so)带来的性能损耗是数量级级别的,核心根源是磁盘IO和物理内存的读写速度差距达数万倍,再叠加大数据组件(Spark/Doris/Flink)的纯内存计算、高并发、低延迟特性,哪怕是少量的swap交换,也会引发严重的性能衰减、任务超时甚至节点假死,而非简单的“性能变慢”。
结合你的大数据集群场景(503Gi大内存、Doris/Spark等组件),从量化性能差距、不同交换程度的损耗表现、大数据组件的敏感点三个维度讲清损耗,结论先抛:对大数据节点,swap交换的性能损耗≈「可用性能直接腰斩/报废」,无任何容忍度。
一、核心量化:磁盘/swap vs 物理内存的速度差距
先看硬件层面的基础读写速度,这是损耗的根本,单位均为MB/s,差距直接拉满:
| 存储类型 | 随机读写速度(大数据核心场景) | 顺序读写速度 | 访问延迟 |
|---|---|---|---|
| 物理内存(RAM) | 100,000+ MB/s | 200,000+ MB/s | 纳秒级(ns) |
| 机械硬盘(HDD) | 10~20 MB/s | 100~200 MB/s | 毫秒级(ms) |
| 固态硬盘(SSD) | 1,000~3,000 MB/s | 5,000~10,000 MB/s | 微秒级(μs) |
| NVMe SSD | 10,000~30,000 MB/s | 50,000+ MB/s | 百纳秒级 |
关键换算:1毫秒(ms)=1000微秒(μs)=1000000纳秒(ns),内存延迟比HDD低100万倍,比SSD低1000倍。
而swap的本质是将磁盘空间模拟为内存,无论用HDD/SSD/NVMe,随机读写性能是核心瓶颈(大数据组件的内存访问几乎都是随机的,而非顺序)。
二、分场景:swap换入换出的实际性能损耗(最贴合你的集群)
swap的损耗不是“线性比例”,而是触发即陡降,且换入(si)的损耗远大于换出(so)(换入是进程需要访问的内存页被放到swap,必须从磁盘读回内存,进程会阻塞等待;换出是内核将闲置页写到swap,后台异步执行,对进程影响小)。
结合交换量和存储介质,分3种常见场景,对应你的大数据节点:
场景1:少量swap交换(如你当前的9.9Gi已用,偶发si/so>0)
- 表现:
vmstat 1中si/so列偶尔出现非0值(如几KB/MB),无持续交换; - 损耗:**单任务性能衰减30%80%**,集群整体吞吐量下降20%50%;
- 原因:大数据组件(如Doris BE的查询引擎、Spark Executor的计算任务)是多线程高并发,只要有一个线程访问到swap中的内存页,就会触发线程阻塞,进而导致整个查询/任务的执行链路变慢,并发越高,阻塞的连锁反应越明显。
- 你的风险:即使只有少量si,Doris的高QPS查询、Spark的大任务也会出现偶尔的超时、慢查询,排查时很难定位(因为内存/CPU/磁盘IO看似都正常)。
场景2:持续轻度swap交换(si/so持续为几MB/s)
- 表现:swap已用逐步增加,
si列持续有数值,物理内存buff/cache无明显释放; - 损耗:单任务性能衰减90%以上,集群出现大量任务超时、重试;
- 原因:内核持续将活跃的匿名内存页换入swap,进程频繁触发磁盘IO等待,CPU出现高空闲率但负载高(CPU等磁盘数据,空转),也就是常说的IO阻塞型负载。
- 典型现象:Doris FE报查询超时、Spark Task失败重试、Flink作业背压飙升。
场景3:重度swap交换(si/so达几十/上百MB/s,swap使用率快速上升)
- 表现:物理内存看似有available,但内核疯狂交换,
si列数值拉满; - 损耗:性能直接报废,节点近乎假死,损耗率99%+;
- 原因:此时内核的swap调度已经抢占了大量磁盘IO资源,进程的内存访问几乎都要走磁盘,整个节点的计算、存储、网络全部被阻塞,最终会引发OOM Killer杀进程或组件服务崩溃(如Doris BE宕机、Spark Executor退出)。
补充:不同存储介质的损耗差异
- HDD做swap:场景1就会出现严重卡顿,是大数据集群的绝对禁忌;
- SSD做swap:可缓解少量交换的损耗,但场景2仍会出现明显超时,性价比极低(SSD的IOPS被swap占用后,业务的磁盘读写也会受影响);
- NVMe SSD做swap:少量交换的损耗相对最小,但仍比物理内存慢10~100倍,且NVMe的寿命会因swap的频繁读写大幅降低,完全没必要(大内存服务器的NVMe应留给业务数据)。
三、大数据组件的“致命敏感点”:为什么swap对集群的损耗远大于通用服务器
通用服务器(如Web服务、数据库)对swap有一定容忍度,但Hadoop/Spark/Doris/Flink/Iceberg等大数据组件完全无法容忍,核心原因是组件的设计逻辑和内存使用特性:
- 纯内存计算:核心逻辑是将数据加载到物理内存中完成计算,全程依赖内存的高速访问,一旦触达swap,计算模型的效率就会完全失效;
- 大内存页/堆内存:组件通常使用大页内存(HugePages)、JVM堆内存,这些都是匿名内存页,无法被释放,内核优先将其换入swap,而这些页正是组件的核心计算页;
- 高并发/低延迟要求:Doris要求毫秒级查询、Spark要求秒级任务、Flink要求低延迟流处理,而swap的毫秒级延迟直接突破了组件的性能阈值;
- 分布式调度:集群的资源调度器(Yarn/K8s)会根据物理内存使用量调度任务,若内核将内存换入swap,调度器会误判“内存有空闲”,继续下发任务,最终导致节点内存过载,交换加剧,形成恶性循环。
四、直观结论:对大数据节点,swap的性能损耗“无阈值”
哪怕是极少量的swap换入(si>0),也会带来不可接受的性能损耗,总结成两句话:
- 换出(so):后台异步执行,损耗可忽略,但so持续非0说明内核在主动交换,是危险信号;
- 换入(si):只要非0,就有损耗,si的数值越大、持续时间越长,损耗呈指数级上升。
你当前的场景(9.9Gi swap已用,偶发si),已经对集群性能造成了隐性的、持续的损耗,只是尚未出现明显的任务失败,但这是大数据集群的潜在故障点(业务量上涨/任务变复杂时,会立即爆发超时、宕机问题)。
五、延伸:为什么通用服务器能容忍swap,而大数据集群不能
通用服务器(如Nginx、MySQL)的内存访问特性是低并发、多空闲、顺序/半随机访问:
- Nginx的内存主要是缓存,可释放,即使触达swap,对请求的延迟影响仅几毫秒,用户无感知;
- MySQL的内存主要是InnoDB缓冲池,磁盘IO本身就是瓶颈,swap的损耗会被磁盘IO掩盖;
而大数据集群的高并发、纯内存、随机访问特性,让swap的损耗被无限放大,成为性能的“致命短板”。
最终核心建议
结合你的环境,彻底禁用swap是唯一选择,没有任何折中方案:
- 按之前的方法将
vm.swappiness=0+vm.zone_reclaim_mode=0,永久关闭swap分区; - 执行
swapoff -a将已用的9.9Gi swap换回到物理内存,立即消除swap带来的隐性损耗; - 开启HugePages(大页内存),进一步提升大数据组件的内存访问效率,减少内核的内存调度开销(大数据集群的标准优化)。
被迫将匿名页换出到Swap的通俗解释
简单说:内核不是主动想把内存页放到Swap,而是进程突然申请内存时,内核手边既没有空闲物理内存、又来不及快速回收buff/cache,为了满足进程的内存请求,只能“被逼无奈”把一部分进程的私有内存(匿名页)临时挪到Swap磁盘上,腾出物理内存给新申请的进程用。
这个行为是vm.swappiness=0时唯一会触发的Swap操作(禁止了主动交换,只保留了这种“应急被动交换”),和你理解的“内核优先用Swap”完全相反,是内核的最后应急手段,核心关键词是「内存申请紧急」+「回收cache来不及」。
结合你的大数据场景,拆成通俗概念+触发过程+你的实际场景三部分,一看就懂:
一、先搞懂2个核心概念(无专业术语)
1. 匿名页
就是进程的“私有内存”,比如Spark Executor的JVM堆内存、Doris BE的查询计算内存、程序运行时的变量/对象内存。
- 特点:不能被内核直接释放(释放了进程就崩溃了),只能两种处理方式:要么留在物理内存,要么临时挪到Swap磁盘;
- 对应你场景:这部分内存是大数据组件的核心计算内存,挪到Swap就会触发后续的
si(换入),导致性能暴跌。
2. 被迫换出(被动交换)
和swappiness>0时的主动换出是完全相反的行为:
| 类型 | 触发时机 | 内核目的 | swappiness要求 |
|---|---|---|---|
| 主动换出 | 系统空闲时(后台异步) | 腾出物理内存当buff/cache | swappiness>0 |
| 被迫换出 | 进程紧急申请内存时 | 满足内存申请,避免进程OOM | swappiness=0/任意 |
简单说:主动换出是“没事找事”,被迫换出是“被逼无奈”。
二、“被迫换出”的完整触发过程(还原你服务器的场景)
结合你的服务器状态:503Gi内存、used341Gi、free10Gi、buff/cache150Gi、available141Gi,且swappiness=0,这个过程就像公司的办公位分配,一步一步看:
- 初始状态:物理内存是“公司办公区”,
free是空办公位(10Gi),buff/cache是临时闲置办公位(150Gi,员工暂时离开,可清理后重新分配),匿名页是员工正在使用的办公位(341Gi),Swap是公司楼下的临时仓库。 - 突发请求:Spark/Doris突然启动一个大任务,瞬间申请大量内存(比如一次性要8Gi),相当于“突然来了一大批新员工,要立刻分配办公位”。
- 内核第一反应:先看空办公位(free10Gi),看似够,但Linux内核会保留
vm.min_free_kbytes的保底空办公位(比如保底5Gi),实际可分配的只有5Gi,不够新进程的8Gi请求。 - 内核第二反应:回收临时闲置办公位(buff/cache),相当于“让保洁快速清理闲置工位”,但保洁清理速度赶不上新员工的入职速度(内存申请速度>kswapd进程的cache回收速度)。
- 被迫应急:内核没有时间等cache回收,为了不让新进程因内存不足崩溃(OOM),只能临时把部分老员工的办公位(不活跃的匿名页)挪到楼下仓库(Swap),腾出3Gi物理内存,凑够8Gi分给新进程——这就是被迫将匿名页换出到Swap。
- 后续副作用:被挪到仓库的老员工(匿名页),后续工作时需要回到办公区(进程访问该内存页),只能从仓库跑上来(
si换入),导致工作效率暴跌(性能卡顿)。
核心关键:这个过程中,不是内核不想用buff/cache,而是内存申请的“突发性”和“高速性”,让内核来不及回收cache,只能用Swap应急。
三、你的场景中,为什么会触发这种“被迫换出”?
结合你是大数据集群(Spark/Doris)+503Gi NUMA架构大内存,两个最核心的触发点:
1. NUMA架构导致的「局部内存不足」(最主要原因)
你的服务器是NUMA架构(多CPU节点,每个节点有独立的本地内存),默认vm.zone_reclaim_mode=1,相当于公司被分成多个独立的小办公区,每个小办公区的工位只能内部分配,不能跨区借用:
- 全局看:整个服务器free10Gi、buff/cache150Gi,内存充足;
- 局部看:某个NUMA节点的本地内存被Spark/Doris占满,free接近0,且该节点的cache回收速度跟不上,其他节点的空闲内存又不能跨区使用;
- 结果:这个节点只能单独触发“被迫换出”,把自己节点内的匿名页挪到Swap,哪怕全局内存充足——这是大内存大数据服务器触发被动交换的第一元凶。
2. 大数据组件的「内存突发申请特性」(源头)
Spark/Doris/Flink这类大数据组件,本身就有瞬间申请大内存的特点:
- Spark:启动Executor、执行shuffle/join操作时,会一次性申请数Gi甚至数十Gi的内存;
- Doris:高QPS下的复杂查询、大表扫描,会突发申请大量计算内存;
这种瞬间的、大粒度的内存申请,会让内核的cache回收进程(kswapd)完全跟不上节奏,哪怕有大量可回收的buff/cache,也来不及释放,最终触发被动交换。
四、一句话总结
“被迫将匿名页换出到Swap”就是:大数据组件突发大内存申请,内核因NUMA局部内存限制+cache回收不及时,没有足够的物理内存满足请求,为了避免进程OOM,只能紧急把进程的私有内存挪到Swap磁盘,是内核的最后应急手段。
而我们之前说的所有优化操作(vm.zone_reclaim_mode=0、主动释放cache、调低min_free_kbytes),核心目的就是让内核有足够的时间/能力回收cache,且能跨NUMA节点使用内存,从根本上避免这种“应急情况”的发生。
我可以帮你把被动交换的触发条件+对应排查命令整理成一个速查清单,后续服务器再出现Swap使用时,能快速定位是否是被动交换,需要吗?
更多推荐

所有评论(0)