很多团队的运维是"救火式"的:平时不看数据,出事了才登上去排查。结果容量规划全靠拍脑袋,扩容总是慢半拍,故障总是在业务最忙的时候爆发。更麻烦的是,同样是"CPU 80%",判断它是不是危险,必须知道这个值相对于历史是常态还是异常——没有基线,任何数字都是孤立的。
长期性能趋势分析要解决的,就是把"单点快照"升级为"时间序列 + 基线 + 预警"。它的目标不是出问题时帮你定位,而是在问题还没发生时,从趋势里提前看到它:磁盘使用率的斜率是不是在加速、内存是不是在缓慢泄漏、连接数是不是每个月都创新高、P99 延迟是不是在悄悄爬坡。
这篇文章讲一套可落地的做法:怎么采集数据、怎么建立基线、怎么计算容量余量和预警阈值、以及怎么把结论转成扩容决策。适合运维工程师、SRE、中小企业 IT 负责人。前提是你要有(或准备搭)一套指标采集系统,最轻量的方案是 sar 的历史数据,标准方案是 Prometheus 加可视化。
一、从"看当下"到"看趋势"的转变
单点监控和趋势分析的区别,用一个例子说清楚。
假设某台服务器现在 CPU 使用率 70%。单点看:还好,没满。趋势看:过去一个月每周涨 5%,照这个速度两三周后就会长期贴着 100%。前者让你觉得安全,后者让你提前安排扩容。
再比如磁盘:df -h 显示 /data 用了 75%。单点看:没事。趋势看:过去 30 天从 55% 涨到 75%,平均每天涨 0.67%,按这个速率二十多天就满,而日志清理策略只覆盖 7 天,说明增长不是日志造成的,是业务数据在长——需要从业务侧解决,而不是单纯清理。
趋势分析要回答三个问题:
- 基线是多少:正常状态下各项指标在什么范围波动?
- 偏离了吗:当前值和基线比,是正常波动还是异常变化?
- 会出什么事:按当前趋势推演,哪个资源、在什么时间点会触顶?
二、要采集哪些指标
不是所有指标都值得长期跟踪。抓核心的几类,覆盖 CPU、内存、磁盘、网络、以及业务侧的关键指标。
| 类别 | 核心指标 | 采集方式 | 关注点 |
|---|---|---|---|
| CPU | 使用率(us/sy/wa)、负载、上下文切换 | sar、node_exporter |
趋势涨幅、wa 占比 |
| 内存 | 使用率、available、swap 使用、OOM 次数 | sar -r、node_exporter |
缓慢泄漏、swap 增长 |
| 磁盘容量 | 各分区使用率、inode 使用率 | df -h、df -i |
线性增长斜率 |
| 磁盘性能 | IOPS、吞吐、await、%util、aqu-sz | sar -b/-d、iostat |
延迟趋势 |
| 网络 | 带宽、包速率、错误包、重传 | sar -n、node_exporter |
峰值、错误率 |
| 应用 | QPS、P99/P999 延迟、错误率 | 应用埋点、APM | 延迟爬坡 |
| 依赖 | 数据库连接数、慢查询、缓存命中率 | 数据库状态、中间件 | 连接增长、命中率下降 |
指标不是越多越好。指标太多会淹没信号、增加存储成本。经验做法:每台机器长期保留十几到几十个核心时序,其余按需临时查询。
强烈推荐的采集路径:
# 方案一:sysstat 的 sa 数据(轻量、几乎所有发行版自带能力)
# 检查是否开启历史采集
cat /etc/sysconfig/sysstat | grep ENABLED # RHEL/CentOS/Rocky
grep ENABLED /etc/default/sysstat # Debian/Ubuntu
# 安装并开启
# RHEL/CentOS/Rocky
dnf install -y sysstat
systemctl enable --now sysstat
# Debian/Ubuntu
apt install -y sysstat
sed -i 's/ENABLED="false"/ENABLED="true"/' /etc/default/sysstat
systemctl restart sysstat
# 默认数据在 /var/log/sa/ 下,按天保存,默认保留约一个月(可在配置里调 HISTORY)
ls -lh /var/log/sa/
# 查询历史某天的数据(saDD 文件是二进制,sar 能读)
sar -f /var/log/sa/sa12 -u # 12 号的 CPU 历史
sar -f /var/log/sa/sa12 -r # 内存历史
sar -f /var/log/sa/sa12 -d # 磁盘 IO 历史
sar -f /var/log/sa/sa12 -n DEV # 网络历史
# 查时间范围内的数据,用于对比周与周
LC_ALL=C sar -f /var/log/sa/sa12 -u -s 09:00:00 -e 18:00:00
# 方案二:Prometheus + node_exporter(标准方案,适合规模化)
# 在每台机器上部署 node_exporter,Prometheus 拉取指标并长期存储
# 常用查询示例(PromQL):
# CPU 使用率:100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# 内存使用率:1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes
# 磁盘使用率:1 - node_filesystem_avail_bytes / node_filesystem_size_bytes
三、怎么建立基线
基线是趋势分析的锚点。没有基线,你就无法判断"70% 的 CPU"是好是坏。
按周期性建立基线。 业务的流量有周期:工作日和周末不同、白天和夜里不同、月初和月末可能不同。基线要按这些周期分别统计,而不是一个平均值了事。比如"工作日 9 点到 21 点的 CPU 基线是 45% 到 65%"比"平均 50%"有用得多。
用中位数和分位数,而不是平均值。 平均值容易被峰值拉高,掩盖正常范围。通常取 P50(中位数)作为典型值,取 P95/P99 作为峰值参考。
至少积累两到四周才能形成可靠基线。 一两天的数据说明不了什么,一两个月的同比数据(本月和上月同期)才能识别出真正的趋势。
基线要动态更新。 业务在增长,基线本身也会缓慢上移。一个常见做法是滚动取最近四周的数据计算基线,同时保留"上个季度同期"作为对照。
建立基线的实操步骤:
# 示例:用 sa 数据粗算一周内 CPU 的日间基线(09:00-18:00)
for d in 08 09 10 11 12; do
echo "=== day $d ==="
LC_ALL=C sar -f /var/log/sa/sa$d -u -s 09:00:00 -e 18:00:00 \
| awk '/Average/ {print}'
done
# 把一周同一时段的数据横向对比,观察波动范围和趋势
# 用 sar 看长时间段的负载趋势,抓异常日
LC_ALL=C sar -q -f /var/log/sa/sa12
# ldavg-1 / ldavg-5 / ldavg-15 三列结合看,识别负载爬升
# 看内存趋势,重点抓 available 的下降斜率
LC_ALL=C sar -r -f /var/log/sa/sa12 | awk '{print $1, $2, $4, $5}'
# 也可以关注 kbmemfree、kbmemused、%memused、kbdirty
四、容量余量与到达时间的计算
趋势分析最有价值的产品,是"预测什么时候会触顶"。这比"现在用了多少"有用得多。
线性外推是最简单也最常用的方法,适合容量类指标(磁盘、内存占用、连接数):
预计可用天数 = (警戒阈值 - 当前值) / 日均增长量
举例:/data 分区当前使用率 75%,警戒线设为 85%,过去 30 天从 55% 涨到 75%,日均增长约 0.67%。那么:(85 - 75) / 0.67 ≈ 15 天,也就是大约半个月内需要处理。如果清理策略不改变增长斜率,单纯扩盘只是延后问题。
要提醒的是,线性外推只在增长近似线性的阶段可靠。很多增长是加速的(业务爬坡期、用户自然增长),这时用增长加速度来推演更准,或者干脆用"最近一个周期的增量"保守估算。经验做法:至少用三种口径(线性、近期加速、同比)各算一遍,取最保守的那个作为预警依据。
| 资源 | 常用警戒线(经验值) | 说明 |
|---|---|---|
| CPU 使用率 | 长期 70%-80% | 留突发余量,短时冲高可接受 |
| 内存使用率 | 80%-85% | 留缓存和突发余量,避免触发 OOM |
| 磁盘容量 | 80%-85% | 留日志突发余量,SSD 建议更早 |
| inode 使用率 | 80% | 小文件多的场景容易先耗尽 |
| 磁盘 IO 延迟 await | 明显高于基线 | 相对基线判断,无绝对标准 |
| 数据库连接数 | 70% of max | 留并发和突发余量 |
| 网络带宽 | 70%-80% | 留突发余量 |
这些是通用经验值,具体要结合业务容忍度调整。比如对延迟极敏感的业务,CPU 到 60% 就该关注了。
五、从趋势到预警与扩容决策
趋势分析的最终目的是驱动动作。建议按"信号—判断—动作"三段式设计。
信号层:设定静态阈值预警(超过警戒线告警)和动态趋势预警(斜率异常、同比异常)。
判断层:看到预警后,先判断是新增长还是异常(比如某天突然多出一批日志、某个任务失控刷数据)。
动作层:分为缓解(清理、限流、调参)和扩容(加盘、加内存、加机器、分库分表)。缓解是争取时间,扩容才解决根本,但扩容要根据增长速率和业务规划来定,避免过度投入。
# 用脚本做简单的容量趋势检查,可以接到定时任务里
# 检查各分区剩余可用天数(粗略线性外推)
# 注意:这只是示意,真实实现要接入较长的历史数据
df -h --output=target,pcent | tail -n +2 | while read mnt pct; do
used=${pct%\%}
[ "$used" -gt 80 ] && echo "[WARN] $mnt 使用率 ${used}%"
done
# inode 检查同样重要
df -i --output=target,ipcent | tail -n +2 | while read mnt ipct; do
iused=${ipct%\%}
[ "$iused" -gt 80 ] && echo "[WARN] $mnt inode ${iused}%"
done
# Prometheus 预警规则示例(容量类)
groups:
- name: capacity
rules:
- alert: DiskWillFillIn4Days
# 用 6 小时的增长速率外推 4 天
expr: predict_linear(node_filesystem_avail_bytes{mountpoint="/data"}[6h], 4*86400) < 0
for: 1h
labels:
severity: warning
annotations:
summary: "磁盘 {{ $labels.mountpoint }} 预计 4 天内写满"
- alert: MemoryLeakSuspect
# 内存 available 在 1 天内持续下降
expr: deriv(node_memory_MemAvailable_bytes[1d]) < 0
for: 2h
labels:
severity: info
predict_linear 是 Prometheus 里做线性外推的现成函数,非常适合容量预警,可以直接用。
六、长期数据的存储与保留策略
长期趋势分析的前提是数据不丢、能追溯。建议:
- 原始数据保留 15 天到 30 天,用于精细化排查。
- 降采样后的数据保留 1 年以上,用于同比和容量规划。比如 15 秒采样降采样到 5 分钟、1 小时各一份。
- 关键指标加标签:机器、业务、环境、机房,方便按维度聚合。
- 剔除噪声:把重启、发布、已知压测等窗口标记出来,分析基线时排除,避免它们拉偏数据。
# sysstat 的保留天数与采样间隔配置
# RHEL/CentOS/Rocky: /etc/sysconfig/sysstat
# Debian/Ubuntu: /etc/default/sysstat
# 关键项:HISTORY=30(保留天数)、COMPRESSAFTER=10(多少天后压缩)
风险提示:调整 sysstat 保留天数、数据清理策略属于会影响历史数据可用性的操作。缩短保留期前先确认这些数据是否还被依赖(比如季度容量报告)。回滚就是改回原配置并重启服务,但已经删掉的历史数据无法恢复。
常见问题
Q:没有监控系统,能做起趋势分析吗?
可以起步。开启 sysstat 的历史采集(sar),默认就能保留一个月的数据,足够做基础的趋势观察和容量预警。规模大了再上 Prometheus。
Q:单一阈值告警和趋势告警,哪个更重要?
都要,作用不同。阈值告警抓"已经越线",趋势告警抓"即将越线"。对容量类问题,趋势告警更有价值,因为它给你留出处理时间。
Q:P99 延迟慢慢上升但没到告警线,要不要管?
要。延迟的持续爬坡通常意味着资源在逼近瓶颈或某条慢查询在恶化,是最值得提前处理的信号之一。设一条"延迟斜率"告警会比单纯看阈值更早发现问题。
Q:怎么区分内存缓慢上涨是泄漏还是正常缓存?
看 MemAvailable 而不是 MemUsed。如果 available 稳定、cache 在增长,通常是正常的页缓存;如果 available 持续下降且 swap 开始增长,就要怀疑泄漏。
Q:容量预测准吗?
线性外推对近似线性的增长比较准,对加速或阶跃式增长会偏差较大。所以预测要给出区间、定期刷新,并结合业务侧的规划(比如已知下月要上活动)一起判断,不要把它当精确预言。
总结
长期趋势分析的核心是把单点快照升级为"时间序列 + 基线 + 预测",在问题发生前看到它,而不是出事后才救火。
要采集的核心是 CPU、内存、磁盘容量与性能、网络、以及业务侧的 QPS/延迟/错误率;起步用 sysstat 的历史数据即可,规模化后用 Prometheus + node_exporter。
基线要按周期(工作日/周末、白天/夜里)分别建立,用中位数和分位数而不是平均值,至少积累两到四周数据,并动态更新。
容量预警的关键是预测触顶时间:预计可用天数 = (阈值 - 当前值) / 日均增长,并用线性、近期加速、同比三种口径取最保守值;Prometheus 的 predict_linear 可直接用于此类预警。
把趋势结论落到动作上:先判断是新增长还是异常,缓解措施争取时间,扩容按增长速率和业务规划决策;同时规划好数据的降采样与保留策略,保证一年以上的同比能力。
企业QQ咨询




