如何让 Ollama 模型常驻内存不被卸载
Ollama 默认空闲 5 分钟后卸载模型,下一次请求会等待重新加载。通过 systemd override 设置 keep_alive,使配置重启后仍有效,再预加载模型。
为什么 Ollama 会在几分钟后卸载模型?
Ollama 会在最后一次请求后将模型保留在内存中 5 分钟,然后释放模型。下一次请求必须再次将权重加载到 RAM 或 VRAM 中,因此在返回第一个 token 前会停顿。这就是聊天 UI 或编码代理开始运行很快,静默一段时间后,下一条消息又变慢的原因。系统没有故障。空闲计时器已到期。
该计时器称为 keep_alive。它按模型单独计算,并在每次请求完成时重新计时。正在处理请求的模型不会被卸载,因为服务器只会让没有活动请求的模型过期。截至 2026 年 10 月,默认值为 5 分钟,适用于此服务器加载的每个模型。
有两个位置可以设置 keep_alive:单个请求,或服务器默认值。systemd drop-in 可使服务器默认值在重启后保持有效。本指南假设 Ollama 已作为服务运行。如果尚未运行,请先参阅 在 VPS 上安装 Ollama,然后返回本指南。
当前有哪些模型驻留,以及何时过期?
ollama psNAME ID SIZE PROCESSOR CONTEXT UNTIL
qwen3:8b 500a1f067a9f 6.6 GB 100% GPU 4096 4 minutes from now输出为空表示当前没有加载任何模型,因此下一个请求必须先加载模型。PROCESSOR 告诉你权重存放在哪里。100% GPU 和 100% CPU 表示模型完整驻留在相应设备上。像 25%/75% CPU/GPU 这样的拆分表示模型只有一部分位于 VRAM 中,其余部分在处理器上运行,因此生成速度较慢。通常这是因为模型无法完全装入显存,但限制 GPU 加载层数的 num_gpu 设置也会产生相同类型的拆分。
UNTIL 表示倒计时,输出类似 4 minutes from now 的相对时间。如果模型加载时使用了负数的 keep_alive,则输出 Forever。服务器正在卸载模型的短暂期间,则输出 Stopping...。
不同版本的字段集合可能不同,因此应读取表头,不要在脚本中通过统计字段数量来解析。Ollama v0.40.2 是在 2026-10-10 检查时的当前版本,它还会在 CONTEXT 和 UNTIL 之间输出 RUNNER 列,用于标识为模型提供服务的运行器,因此你的表头可能比上面的示例多一列。对于任何自动化处理,请调用 API:
curl -s http://localhost:11434/api/ps每个条目都包含 expires_at、类似 2026-08-09T14:38:31.83753Z 的绝对时间戳,以及 size_vram,表示该模型位于 GPU 内存中的部分。size_vram 为 0 表示模型在 CPU 上运行。
实际重新加载的成本
不要凭猜测判断。Ollama 会在每个响应中报告加载时间,字段为 load_duration,单位是纳秒。
sudo apt install -y jq
ollama stop qwen3:8b
curl -s http://localhost:11434/api/generate -d '{"model": "qwen3:8b", "prompt": "hi", "stream": false}' | jq '{load_duration, total_duration}'
curl -s http://localhost:11434/api/generate -d '{"model": "qwen3:8b", "prompt": "hi", "stream": false}' | jq '{load_duration, total_duration}'第一次调用会加载模型,因此其 load_duration 数值较大。将它除以 1000000000,即可换算为秒。第二次调用在模型驻留内存期间运行,报告的数值会小得多。这两个数值之间的差值,就是计时器到期后每位用户都要承担的等待时间,也是修改 keep_alive 的根本原因。卸载模型后,内核的页缓存通常仍会保留模型文件。因此,在有剩余 RAM 的机器上,重新加载可能比系统启动后的首次加载更快。缓存被回收后,模型权重需要从磁盘读取。如果您已将模型目录移到第二个卷,该卷的速度就决定了每次冷加载的最低耗时。至于暂停前后两侧的生成速度,请参阅如何在自己的机器上测量每秒生成的 token 数。
在一次请求中将 Ollama 模型保持加载状态
在请求中发送 keep_alive。从请求完成时起,该设置将应用于此模型。
curl -s http://localhost:11434/api/chat -d '{
"model": "qwen3:8b",
"messages": [{"role": "user", "content": "hello"}],
"keep_alive": "30m"
}'支持以下 4 种值形式:
- 时长字符串:
"30m"、"24h"、"90s" - 普通数字,按秒读取:
3600 - 负值
-1或"-1m",表示完全不设置空闲超时 0,表示请求完成后立即卸载
请求中的值会覆盖服务器默认值,双向覆盖均适用。这一点非常重要:客户端发送的 keep_alive 会优先于服务器上的任何配置。
您也可以在不生成任何内容的情况下加载模型。只发送模型名称即可。服务器会加载该模型,并返回包含 "done": true 的空响应。
curl -s http://localhost:11434/api/generate -d '{"model": "qwen3:8b", "keep_alive": "30m"}'重启后或拉取新模型后运行此命令。这样,首个实际用户请求就无需等待模型加载。CLI 使用一个 flag 执行相同操作:
ollama run --keepalive 30m qwen3:8b "hello"使用 OLLAMA_KEEP_ALIVE 默认保持模型加载
服务器启动时读取 OLLAMA_KEEP_ALIVE,并将其用于所有未单独设置该值的模型。它支持与请求字段相同的格式,因此 30m、3600 和 -1 均可使用。
关键在于该环境变量必须设置在哪个环境中。在 SSH 会话中运行 export OLLAMA_KEEP_ALIVE=30m 不会产生任何效果,因为通过软件包安装的服务会以独立用户身份作为 systemd 服务运行,并使用自己的环境变量。您的登录 shell 与该服务互不相通。这是该设置看似未生效的最常见原因。
通过 systemd drop-in 让设置在重启后保留
sudo systemctl edit ollama.service编辑器打开后会显示两个注释标记。在这两个标记之间输入内容:systemd 会丢弃第二个标记下方的所有内容。
[Service]
Environment="OLLAMA_KEEP_ALIVE=30m"保存后会写入 /etc/systemd/system/ollama.service.d/override.conf。这是 drop-in,而不是修改已发布的单元文件,因此 Ollama 软件包升级并替换 ollama.service 时,不会覆盖你的设置。如果你不熟悉 drop-in 和单元文件,请参阅systemd 服务和计时器指南,了解相关机制。
sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environment最后一条命令会输出服务实际运行时使用的环境。如果该行中缺少 OLLAMA_KEEP_ALIVE=30m,说明 drop-in 未生效。原因通常是缺少 [Service] 标头,或将内容输入到了标记下方。重启会卸载所有已加载的模型,因此下一个请求需要重新冷加载。使用上面的预加载调用完成预热。drop-in 会在系统重启后保留该设置,但不会保留模型:服务启动时 ollama serve 不会加载任何模型,因此每次启动后都要运行相同的预加载调用。
让模型常驻的成本
ollama ps 中的 SIZE 列表示整个空闲窗口期间占用的内存,而不只是处理请求时占用的内存。采用 4-bit 量化的 8B 模型通常占用约 5 到 6 GB。27B 模型则完全是另一种情况。在决定让模型常驻之前,值得先了解仅使用 CPU 的 VPS 运行模型所需的内存计算。将 keep_alive 设置为 -1 后,就意味着只要服务器运行,模型就会持续占用这部分内存,除非其他模型的请求迫使它被卸载。对于小型 VPS,这会直接挤占数据库、Web 应用和构建任务的资源。
请查看实际数值,不要只相信估算值。模型加载后运行一次,执行 ollama stop 后再运行一次:
free -havailable 列表示内核仍可分配给新进程的内存。在 NVIDIA GPU 服务器上,nvidia-smi 会显示相同的情况,只不过对象是 VRAM。如果服务器耗尽内存,内核会终止某个进程以回收资源:
sudo dmesg -T | grep -i "out of memory"如果某一行列出 ollama,说明模型服务器成了被终止的进程。如果列出的是数据库,说明模型保住了,而你关心的其他服务被终止了。这两种结果都源于同一个决定:在没有余量的服务器上设置过长的保持活动窗口。
这里有两项容易忽略的成本。更长的上下文长度会预留更大的 KV cache(key value cache,即模型生成内容时为每个 token 保留的注意力状态),该缓存也属于常驻内存。其大小取决于 num_ctx,因此增大上下文窗口会增加常驻模型在整个空闲期间持有的内存,而不只是在模型响应时增加。将 OLLAMA_NUM_PARALLEL 设置为大于 1 的值后,每个并行槽位都会分别预留一份缓存。如果计划让一个模型为多名用户提供服务,应按槽位而不是仅按模型权重来规划内存。
一个合理的默认设置是:在有足够余量的服务器上运行一个模型时,可以使用 -1。共享服务器应使用能够覆盖请求间隔的窗口,例如 30m,这样停止工作后,内存就会释放。
立即卸载模型
ollama stop qwen3:8b该命令不输出任何内容,并且模型会从 ollama ps 中消失。对于已拉取但当前未加载的模型,该命令同样不输出任何内容。该命令不会检查当前驻留的模型:它只发送卸载请求,无论内存中是否有该模型,服务器都会返回成功。仅当服务器上未安装该名称的模型时,才会出现 couldn't find model "qwen3:8b" to stop 错误。这通常表示模型名称或标签拼写错误。因此,静默返回的 ollama stop 不能证明已释放任何内存。只有 ollama ps 才能证明这一点。API 形式是不带提示词的请求,并将 keep_alive 设置为 0:
curl -s http://localhost:11434/api/chat -d '{"model": "qwen3:8b", "messages": [], "keep_alive": 0}'响应中包含 "done_reason": "unload"。请使用此方法,而不要重启服务。systemctl restart ollama 也会释放内存,但它会卸载所有其他已加载的模型,并终止正在运行的请求。
在一台服务器上运行多个模型
OLLAMA_MAX_LOADED_MODELS限制同时保持加载状态的模型数量。截至 2026 年 10 月,默认值为每个 GPU 3 个模型;仅使用 CPU 的服务器默认也是 3 个。该限制统计的是模型数量,但真正的限制是内存。因此,第二个大型模型可能在达到 3 个模型之前就因内存不足而无法加载。
请求加载新模型时,如果可用内存不足,或已达到模型数量上限,调度器会卸载一个已驻留的模型以释放空间。调度器优先选择没有活动请求的模型。即使某个模型的计时器尚未到期,调度器也可能将其驱逐,包括使用 -1 加载的模型,但会优先处理剩余时间较短的模型。因此,负数 keep_alive 表示不设置空闲超时。它不会锁定模型权重以阻止其他模型使用相应资源。
这些决策会记录在服务日志中,但达到模型数量上限的情况只会以 debug 级别记录。在同一个 drop-in 文件中再添加一行 Environment="OLLAMA_DEBUG=1",然后重启服务并监控日志:
sudo journalctl -u ollama -f查看触发卸载的请求旁边记录的原因。max runners achieved, unloading one to make room 表示已达到 OLLAMA_MAX_LOADED_MODELS 上限。即使两个模型的内存需求合计不超过可用内存,也可能出现这种情况;如果 free -h 显示仍有余量,请提高该上限。若日志显示预测加载新模型会超出可用内存,随后又发生模型驱逐,则说明这两个模型无法在此服务器上同时运行。解决方法是减少此服务器上的模型数量,或为必须快速响应的模型设置较长的窗口,并为很少调用的模型使用 0。
可持续到下一版本的指导
Ollama 经常发布新版本,默认值也会变化。因此,应检查当前使用的构建版本,而不要死记数值:
ollama --version
ollama serve --helpollama serve --help 会列出该构建实际读取的环境变量,其中包括 OLLAMA_KEEP_ALIVE。有两条规则在各版本中都成立,可以放心据此配置。请求中的值优先于服务器默认值。无论配置文件声明应加载什么,ollama ps 才是实际加载内容的依据。
如果编辑器或代理驱动您的服务器,请先检查客户端发送的内容,再判断是否是服务器的问题。将编码代理指向您自己的 Ollama 服务器介绍了这些请求设置的位置。
FAQ
为什么 Ollama 会在 5 分钟后卸载模型?
5 分钟是默认的 keep_alive,即 Ollama 在请求完成后启动的空闲计时器。计时器到期后,服务器会释放模型权重,因此下一个请求必须重新加载模型,而重新加载就是您感受到的暂停。对于单个请求,可在 JSON 请求体中发送 "keep_alive": "30m" 来延长该时间;对于整个服务器,可使用 OLLAMA_KEEP_ALIVE 环境变量。
如何让 Ollama 模型永久保留在内存中?
使用负值:在请求中设置 "keep_alive": -1,或为服务器设置 OLLAMA_KEEP_ALIVE=-1。此时,ollama ps 会在 UNTIL 列中显示 Forever。这只会移除空闲计时器,不会改变其他行为。如果请求另一个模型时内存不足,调度器仍会卸载当前模型以释放空间。重启服务或重启系统也会清除该状态,因此之后需要再次预加载模型。
为什么 OLLAMA_KEEP_ALIVE 没有生效?
检查变量的设置位置。运行 systemctl show ollama --property=Environment。如果输出中没有该变量,说明服务器从未获取到它,因为在 shell 中导出的变量不会传递给 systemd 服务。使用 sudo systemctl edit ollama.service 设置变量,然后运行 sudo systemctl daemon-reload 和 sudo systemctl restart ollama。另一种原因是客户端在请求中发送了自己的 keep_alive,从而覆盖服务器默认值。
如何在不重启 Ollama 的情况下释放内存?
ollama stop qwen3:8b 会立即卸载指定模型,同时保持服务器和其他已加载模型继续运行。通过 API 发送不包含提示词且带有 "keep_alive": 0 的请求,响应会返回 "done_reason": "unload"。使用 ollama ps 确认,输出中不应再列出该模型。