多应用场景 NUMA 实践
双核 CPU 运行了 PostgreSQL 和 Redis,现在需要运行多个 Python 程序,内核是否有必要配置 kernel.numa_balancing = 0,如果配置了,是否有必要使用 numactl 启动 Python 程序?
这是一个非常好的、而且问到点子上的问题,因为它把 CPU 拓扑、NUMA、内核策略、应用启动方式 全部串在了一起。
先给结论,再解释为什么,最后给可执行建议。
双核 CPU + PostgreSQL + Redis + 多个 Python 程序:
-
是否需要关闭
kernel.numa_balancing?- 大概率:不需要
- 甚至可以说:关了反而更容易出问题
-
如果关了
kernel.numa_balancing,是否有必要用numactl启动 Python?- 一般没有必要
- 除非你在做 明确的 CPU / 内存强隔离
你说的是 双核 CPU,而不是 双路 CPU。
这是关键区别:
| 硬件 | NUMA 是否存在 |
|---|---|
| 双核(1 颗 CPU,2 core) | ❌ 基本不存在 |
| 双路(2 颗物理 CPU) | ✅ 明确 NUMA |
| 单路 + 多 chiplet(部分 AMD) | ⚠️ 可能存在 |
判断方法(一句话):
numactl --hardware
如果结果是:
available: 1 nodes (0)
👉 这台机器在内核层面几乎是 UMA(统一内存架构)
让“进程在哪个 CPU 跑”,和“它用的内存在哪个 NUMA node”尽量一致
它只在以下条件下才真正有意义:
- 多 NUMA node
- 进程频繁跨 node 访问内存
- 内存访问成本差异明显
| 项目 | 实际情况 |
|---|---|
| NUMA node 数 | 基本为 1 |
| 内存访问差异 | 几乎没有 |
| 自动平衡收益 | 接近 0 |
| 自动平衡成本 | 仍然存在(页迁移、扫描) |
所以:
开着没收益,关了也没收益
- PostgreSQL(长期常驻、缓存敏感)
- Redis(极度内存和 CPU 敏感)
- 多个 Python 程序(短生命周期 / GIL / 抖动)
如果你:
- ❌ 关闭
kernel.numa_balancing - ❌ 不做 CPU / 内存绑定
- ❌ 核数又少(2 核)
那么内核会:
- 允许调度器频繁迁移 Python 进程
- 导致 PostgreSQL / Redis 被抢占
- 出现 缓存抖动 + 上下文切换放大
👉 这和 NUMA 无关,是“CPU 争抢问题”
几乎没用
- 只有 1 个 NUMA node
numactl --cpunodebind=0和不写,效果一样numactl --membind=0也是一样
numactl 的前提是:你有得选
双核 CPU 上的“资源争抢与优先级失控”
如果你真的要“硬隔离”:
taskset -c 0 postgres
taskset -c 1 redis-server
⚠️ 双核非常紧张,不建议过度绑定。
- 避免同时跑多个 CPU-bound Python
- 使用队列 / 批次 / 限流
你已经在用:
vm.swappiness = 0
建议再配合:
- systemd
MemoryMax= - 或容器 cgroup(如果有)
- 设置
OOMScoreAdjust=-900 - Python 程序设置更高 OOM 分值
这是实话:
双核 CPU + 数据库 + Redis + 多 Python,本身就已经在透支稳定性
# 保持默认即可
kernel.numa_balancing = 1
或者:
# 关不关都行,但没收益
kernel.numa_balancing = 0
不作为关键调优点
- 不要为了“看起来专业”上 numactl
- 不要在没有 NUMA 的机器上做 NUMA 调优
- 不要指望 NUMA 参数解决 CPU 争抢问题
在“双核 + 单 NUMA 节点”的机器上:
kernel.numa_balancing不是关键变量numactl几乎没有意义- 真正决定稳定性的,是 CPU 争抢、内存边界、OOM 优先级