看 free -h 别只盯 free 那列:available 才是真

服务器一查内存:

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           14Gi        10Gi       146Mi       0.0Ki       4.2Gi       4.1Gi
Swap:            0B          0B          0B

看到 free: 146Mi 就觉得”内存要爆了”——不对,Linux 从来不闲着,它会把空闲内存拿去做各种缓存

各列到底是什么

含义
total总内存
used已被进程占用
free完全空闲,谁都没在用(少不代表不好)
sharedtmpfs / shared memory 占用
buff/cache内核用作 page cache / dentry 缓存
available实际还能分配给程序的内存(这个才是真)

关键buff/cache弹性的——一旦有程序需要内存,内核会立刻回收 cache 让出来。所以真正衡量”还剩多少”的指标是 available,不是 free

上面例子里 available = 4.1Gi,说明还能舒服再开 4G 内存的程序,没问题。

buff/cache 具体缓存什么

  • Page cache:读过的文件内容缓存在内存里,下次读同一文件秒回
  • Dentry cache:目录项缓存,让 ls / find 之类操作更快
  • Inode cache:文件元数据(大小、时间戳)缓存
  • Buffers:块设备 IO 缓冲

这些都是性能加速——把内存”用起来”总比闲着好。

手动清 cache

极少用得上,但知道一下:

sync              # 先把脏页刷盘
echo 3 > /proc/sys/vm/drop_caches   # 清所有 cache
  • 1 = 清 page cache
  • 2 = 清 dentry + inode
  • 3 = 全清

清完 free -hfree 会瞬间变大——但系统 IO 性能会立刻下降,因为所有文件读要重新从磁盘拉。生产上除非做基准测试,不然不要清。

Swap = 0 的风险

上面的例子 Swap: 0B。开 swap 有一个好处:内存暂时不够时,把不活跃页面换到磁盘,避免 OOM Killer 杀进程

没 swap 的情况,某个进程突然吃到 15G 内存,系统会直接触发 OOM Killer

Killed process 12345 (python)
Killed process 23456 (mysqld)

杀谁看 oom_score(内核给每个进程算一个”该杀分数”),基本是”占内存多、优先级低”的先中招。

加个 swap(4G)

sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

验证:

free -h
# Swap: 4.0Gi ...

开机自动挂载:

echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab

Swap 大小经验:

  • 内存 < 2G:swap 是内存的 2 倍
  • 内存 2-8G:swap 等于内存
  • 内存 > 8G:swap 2-4G 或者干脆不开(数据库服务器)

找谁在吃内存

RSS 排序(真实占用物理内存):

ps aux --sort=-rss | head -20

或者 top 里按 M 排。列 RES才是实际占用,VIRT(虚拟内存)意义不大。

看某个进程详情:

cat /proc/<PID>/status | grep -E 'VmRSS|VmSize'

看具体是哪部分:

pmap -x <PID> | tail -1

MySQL / Redis / Java 类”吃内存大户”

这些程序的内存占用大多是配置定的

  • MySQLinnodb_buffer_pool_size,默认可能占 70% 内存
  • Redismaxmemory,不配就吃到爆
  • Java-Xmx 设堆大小,不设 JVM 会按机器算

上生产前把这些参数对着物理内存卡好,不然多进程叠加轻松超总内存。

Linux OOM 前的预警

看 dmesg 有没有:

sudo dmesg -T | grep -i "oom\|killed"
Out of memory: Killed process 12345 (python) total-vm:15234567kB

看到这个说明已经杀过了。生产上应该主动监控——node_exporter + Prometheus 采 node_memory_MemAvailable_bytes,跌破阈值发告警。

一句话总结

free -h 看的是 available,不是 free;buff/cache 是好东西不是问题。没 swap 的服务器建议加 4G 兜底,主要吃内存的程序(MySQL / Redis / Java)参数要卡死。