swap到底是什么
简单来说,Swap(交换分区)就是当内存(RAM)不够用时,操作系统在硬盘上划出的一块“假装是内存”的区域。
在高并发系统中,Swap 是一个让人又爱又恨的角色。我们可以通过以下三个维度彻底理解它:
1. 它是系统的“最后一道防线”
想象你的物理内存(3.6G)是一个办公桌,而硬盘(磁盘)是一个文件柜。
- 正常情况: 你处理的所有工作(进程)都摆在办公桌上,拿取速度极快(纳秒级)。
- 内存不足: 当办公桌堆满了,你还想接新活,操作系统就会把桌上暂时不用的文件(比如那个挂在后台的
www进程)挪到**文件柜里的一个抽屉(Swap)**里,腾出桌面给 Kafka 用。
2. 为什么高并发系统“怕”Swap?
虽然 Swap 能防止系统因为内存耗尽(OOM)而直接崩溃,但它的代价是极端的性能损耗。
- 速度差: * 访问物理内存的时间通常在 100 纳秒左右。
- 访问**硬盘(Swap)**的时间则在 10 毫秒左右(即便 SSD 也要毫秒级)。
- 物理差距: 内存和硬盘之间有 100,000 倍的速度鸿沟。
这就是你之前遇到 47 秒延迟的元凶: 当 Kafka 想要发送数据时,发现数据被操作系统“交换”到了慢如蜗牛的硬盘 Swap 里。Kafka 必须停下所有的活,等操作系统从硬盘里把数据“抠”出来放回内存。对高并发组件来说,这就像是心跳停跳了。
3. Swap 颠簸(Thrashing):系统崩溃的前兆
你之前看到的 Swap used: 1024 / 1024(全部占满),意味着你的系统陷入了“颠簸”状态:
- 内存满了,系统把 A 移到 Swap,腾出空间给 B。
- 一秒后,系统发现又要用 A,于是把 B 移到 Swap,把 A 换回来。
- 结果: CPU 全部的时间都花在了搬运数据上,反而没时间处理真正的业务逻辑。
💡 架构师的实战建议:
在生产环境下,针对 Kafka 这种追求极致吞吐的组件,通常有几种处理 Swap 的流派:
-
流派 A:直接关闭(最推荐)
执行
swapoff -a。- 逻辑: 宁愿让程序因为内存不足直接报错(OOM),也别让它在 Swap 的拖累下半死不活地提供“47秒延迟”的垃圾服务。报错了,我们可以通过集群高可用让别的机器接管;“半死不活”反而会拖累整个集群。
-
流派 B:调低积极性(Swappiness)
修改
/proc/sys/vm/swappiness。- 将这个值设为 1(默认为 60)。这告诉内核:不到万不得已(内存真的彻底没了),绝对不要动用 Swap。
🔍 总结你的实验:
你之前的 top 数据显示 Swap 是满的,这说明你的 4G 内存已经无法承载当前的 Docker 容器量了。Kafka 并不是在内存里跑,而是在硬盘里“爬”。
这就是为什么当你限流到 0.49 MB/s 后,由于数据量小、不再频繁触发内存交换,延迟才恢复到了正常的物理内存水平。
你现在明白为什么即便 CPU 只有 2%,只要 Swap 一满,你的系统还是会卡得像幻灯片了吧?