max_map_count 是什么
vm.max_map_count 限制单个进程可以持有的内存映射区域(VMA)数量,默认 65530。每个 mmap 调用、共享库加载、文件映射都会占用一个映射区域。搜索引擎类程序依赖 mmap 打开大量索引文件,JVM 的堆与类元数据、部分游戏服务器与科学计算程序也会产生大量映射。达到上限后新的 mmap 会失败并返回 ENOMEM,应用日志里看到的是 Cannot allocate memory,但内存其实还有余量。
基本信息
| 参数 | vm.max_map_count |
|---|---|
| 默认值 | 65530(发行版可能调整过,以本机回读为准) |
| 作用对象 | 单进程的内存映射区域数量,不是内存容量 |
| 典型报错 | mmap 失败返回 ENOMEM,应用提示 Cannot allocate memory |
| 常用实践 | 运行 Elasticsearch 一类依赖 mmap 的组件时,其官方文档要求在宿主机上提高到 262144 |
| 核对方式 | 查看进程的映射数量与上限的差距 |
典型使用场景
- 部署搜索引擎:安装前按官方文档要求检查并提高宿主机上的该值
- 应用报内存分配失败但系统内存充足:先排除映射数量触顶再查内存
- 容器化部署:确认修改所在层级,容器内看到的限制可能与宿主不同
- 容量评估:按索引分片数量估算单个进程可能需要的映射数
- 故障复盘:把该值纳入交付检查项,避免同类问题在扩容后再次出现
查看与调整
查看与调整
sysctl vm.max_map_count # 读当前上限
wc -l /proc/$(pgrep -n java)/maps 2>/dev/null # 用映射行数近似当前映射数量
grep -c . /proc/1/maps # 示例:统计某进程的映射条目数
sysctl -w vm.max_map_count=262144 # 临时调大
# 容器内修改可能被宿主或运行时限制,以在目标命名空间内的回读值为准落盘与回读
落盘与回读
# /etc/sysctl.d/99-map-count.conf
vm.max_map_count = 262144 # 满足依赖 mmap 的组件对映射数量的要求
# 回读命令:sysctl vm.max_map_count报错与方向对照
| 现象 | 可能原因 | 验证方式 |
|---|---|---|
| Cannot allocate memory | 映射数量触顶 | 查看进程 maps 行数是否接近上限 |
| Cannot allocate memory | 物理内存与 swap 都不足 | 查看 free、Committed_AS 与 OOM 日志 |
| 启动阶段即失败 | 映射上限在初始化时已被用尽 | 核对该值是否被镜像或运行时限制在较小值 |
| 只有部分实例失败 | 单进程映射数量差异大 | 对比各实例的映射数量与配置差异 |
虚拟内存映射数量与物理内存用量是两件事:一个进程可以有数十万映射而实际占用内存不大。因此这个值调高通常不会带来内存压力,但真正需要关注的是映射数量为何如此多,是否存在设计上的浪费。
容器场景要确认生效层级:宿主机修改后需要保证容器能读到新值,不同运行时与安全策略下的行为不一致。最可靠的做法是在容器内部用 sysctl 回读确认,而不是只核对宿主节点。