2. 内存密集型业务特征识别

容量规划的第一步不是算内存,而是判断“这个业务到底算不算内存密集型”。判断错了,后面所有计算都会跑偏:把 CPU 密集型业务按内存密集型配,会浪费内存预算;把真正的内存密集型业务当成普通业务,则会在业务高峰出现换页、缓存命中率骤降、数据库 Buffer Pool 命中率跌破阈值等连锁问题。本节从内存访问模式、工作集大小和性能瓶颈三个维度,给出可操作的识别方法。

一、内存密集型业务的本质:瓶颈在“内存层级”而非“计算”

任何业务都要用内存,但“用内存”和“内存受限”是两回事。内存密集型业务的共同特征是:CPU 利用率长期不高(例如 30%~50%),但内存容量占用高、内存带宽压力大,或者对内存延迟极其敏感。当内存不足时,性能不是线性下降,而是断崖式下跌——因为系统开始换页(swap)或频繁触发缓存淘汰,磁盘 I/O 被拖入关键路径。

可以用一个简单的判据来初筛:在压测或生产高峰中,如果 CPU 利用率 < 60% 而内存占用率 > 80%,或者 内存带宽利用率 > 70%,或者 LLC(Last Level Cache)缺失率显著上升,就应优先按内存密集型业务对待。反之,如果 CPU 已经打满而内存仍有大量空闲,则更可能是计算密集型。

二、四类典型负载的内存访问模式

不同业务的内存访问模式差异很大,识别时要看“访问粒度、访问局部性、读写比例、延迟敏感度”四个属性。

  • 数据库(OLTP 为主):以随机小页访问为主,读写混合,对延迟极敏感。核心内存对象是 Buffer Pool / InnoDB Buffer Pool,工作集通常等于“热数据 + 索引”。访问局部性中等,但一旦 Buffer Pool 装不下热数据,物理读会急剧上升。
  • 内存缓存(Redis / Memcached):几乎全内存驻留,访问模式为随机 key 查找,读写比通常 8:2 或更高,对延迟要求亚毫秒级。工作集就是全部数据集(或全部热 key),内存不足会直接触发淘汰策略,命中率下降。
  • 实时分析(OLAP / 流处理):以顺序扫描和列式聚合为主,内存带宽压力大,常出现大块内存分配(如 Hash Join、排序缓冲区)。工作集可能是“当前查询涉及的列数据 + 中间结果”,峰值内存远高于平均。
  • 虚拟化(VM / 容器密度):内存被多个虚拟机或容器瓜分,访问模式取决于各 guest 的业务。关键指标是“内存超分比”和“气球驱动/交换”行为,瓶颈往往出现在内存回收和 NUMA 跨节点访问上。

下面这张图把四类负载在“访问模式—工作集—瓶颈点”上的差异放在同一张关系图中,便于横向对比识别。

四类典型负载的内存特征对比 访问模式 → 工作集 → 瓶颈点 负载类型 内存访问模式 工作集大小 主要瓶颈点 数据库 OLTP Buffer Pool 驻留 随机小页读写 随机访问 · 读写混合 延迟敏感(μs 级) 局部性中等 热数据 + 索引 通常为数据集 20%~40% 随业务增长而扩大 Buffer Pool 命中率 物理读 / 换页 内存延迟 内存缓存 Redis / Memcached 全内存驻留 随机 key 查找 读写比约 8:2 亚毫秒延迟要求 全部数据集或热 key 需预留 20%~30% 余量 含副本与持久化开销 缓存命中率 淘汰策略触发 内存碎片 实时分析 OLAP 列式扫描 / 聚合 Hash Join / 排序 顺序扫描为主 大块内存分配 带宽敏感 查询涉及列 + 中间结果 峰值远高于平均 并发查询叠加 内存带宽 峰值内存溢出 Spill to disk 虚拟化 / 容器 多租户共享 内存超分 取决于各 guest 业务 NUMA 跨节点访问 气球驱动回收 各 VM 工作集之和 超分比 1.2~1.5 常见 需留出回收余量 内存回收 / 交换 NUMA 远端延迟 密度与性能权衡

三、工作集大小的估算方法

工作集(Working Set)是识别内存密集型业务的核心量化指标。它不等于“数据总量”,而是“在稳定运行期间被频繁访问、必须常驻内存的那部分数据”。估算工作集有三种常用手段:

  1. 监控法:在业务高峰运行 1~2 周,采集 Buffer Pool 命中率、缓存命中率、page fault 次数。当命中率稳定在目标阈值以上(如数据库 Buffer Pool 命中率 > 99%,Redis 命中率 > 95%)时,当前内存占用可近似视为工作集下限。
  2. 采样法:对数据库做全量扫描统计,按访问频次排序,取累计访问量占比 80%~90% 的数据量作为工作集估计。例如某订单库总数据 2 TB,按主键访问频次排序后,前 15% 的数据贡献了 85% 的访问,则工作集约 300 GB。
  3. 公式法:工作集 ≈ 热数据量 × (1 + 索引膨胀系数) × (1 + 并发放大系数)。索引膨胀系数通常取 1.2~1.5,并发放大系数在 OLAP 场景可取 1.5~3.0。
示例(合理假设,非实测):某 MySQL 订单库总数据量 2 TB,索引 400 GB,监控显示 Buffer Pool 命中率长期 99.2%,物理读稳定。按采样法估算热数据约 300 GB,索引膨胀系数取 1.3,则工作集 ≈ 300 × 1.3 = 390 GB。若单机内存 512 GB,扣除 OS 与连接开销约 40 GB,Buffer Pool 可配 440 GB,余量约 50 GB,属于健康区间。

四、性能瓶颈的定位与判断

识别内存密集型业务,最终要落到“瓶颈是否在内存”上。建议按以下顺序排查:

  • 看 CPU 与内存的利用率剪刀差:CPU 低、内存高,是内存密集型的典型信号。
  • 看换页与缺页:vmstat 中 si/so 持续非零,或 pgmajfault 快速增长,说明内存不足已影响性能。
  • 看缓存命中率:数据库 Buffer Pool 命中率、Redis 命中率、LLC 命中率下降,是工作集超出内存的直接证据。
  • 看内存带宽:使用 pcm-memory 或 perf stat 观察内存带宽利用率,OLAP 场景常先于容量触顶。
  • 看 NUMA 分布:numastat 中远端访问比例高,说明内存分配不均,会放大延迟。
常见误判:把“数据量大”直接等同于“内存密集型”。如果业务以顺序扫描为主、缓存命中率低但延迟可接受,且 CPU 已接近饱和,则更可能是 I/O 或计算密集型。判断依据始终是“瓶颈位置”,而不是“数据规模”。

五、快速判断清单

在实际容量规划中,可以用下面这份清单快速给业务打标签。满足 3 条及以上,即可判定为内存密集型,进入内存容量详细测算流程。

判断项 内存密集型信号 非内存密集型信号
CPU 利用率 长期 < 60% 长期 > 80%
内存占用率 > 80% 且持续 < 60% 且波动小
缓存命中率 低于目标阈值并下降 稳定在高位
换页活动 si/so 持续非零 几乎为零
内存带宽 > 70% 利用率 < 40%
延迟敏感度 对内存延迟极敏感 对吞吐更敏感

完成本节识别后,你就得到了一个明确的输入:业务是否属于内存密集型、工作集大致多大、瓶颈在容量还是带宽。下一阶段才能据此选择 Xeon 平台的内存通道配置、容量配比和 NUMA 策略,避免“先买后算”的被动局面。