当前位置: 首页 > news >正文

【左扬精讲】SRE 别慌!我用 服务器监控指标 讲 KNN 分类算法,从相似度计算到异常识别,都是咱运维人能懂的话(含代码)

【左扬精讲】SRE 别慌!我用 "服务器监控指标" 讲 KNN 分类算法,从相似度计算到异常识别,都是咱运维人能懂的话(含代码)

一、从 SRE 日常工作理解 KNN 的核心逻辑

        作为 SRE,你是否经常遇到这样的场景:​

        某天监控告警响起,某台服务器 CPU 突然飙升到 90%,你打开监控面板一看 —— 这台机器的内存使用率、网络流量、进程数变化趋势,和上周那台“因进程泄漏导致 CPU 异常”的服务器几乎一模一样。于是你判断:这台机器大概率也是进程泄漏问题,先重启目标进程试试,果然告警解除。​

        这个“靠历史经验匹配相似问题”的思路,其实就是KNN(K-近邻)算法的运维版逻辑:未知问题的“特征”(CPU、内存等指标)和哪些已知问题的特征最像,就按最像的那类问题来处理。​

        今天我们就从零基础出发,用 SRE 最熟悉的 "服务器异常检测"、"日志分类" 场景,拆解 KNN 算法的原理,再通过 "计算服务器指标相似度" 学会余弦相似度,最后用 Python 实现一个能落地的运维异常检测工具。

​二、什么是 KNN 分类算法(讲给 SRE 听)

KNN 的全称是 K-Nearest Neighbors(K 近邻),用运维语言翻译过来就是:

对于一个未知状态的对象(比如一台异常的服务器、一条看不懂的日志),找到和它 "最像" 的 K 个已知状态对象(比如历史上标记过 "正常 / 异常" 的服务器、已归类的"错误 / 正常"日志),看这 K 个对象里多数属于什么状态,就把未知对象归为这个状态

KNN 的 3 个核心概念(按SRE 视角拆解)

2.1、"样本"= 运维中的监控对象 / 日志

​比如 "一台服务器的 5 分钟指标数据"、"一条 Nginx 访问日志",都是一个 "样本"。

2.2、"K"= 参考历史案例的数量​

比如 "找最像的 3 个历史服务器异常案例",这里 K=3;K 太小容易误判(比如只参考 1 个案例,刚好是个特殊情况),K 太大容易模糊边界(比如参考 100 个案例,混进了不相关的情况),SRE 场景通常先从 K=3 或 K=5 开始试。​

2.3、"距离"= 运维指标 / 日志的相似度​

比如 "两台服务器的 CPU、内存、网络指标差异"、"两条日志的关键词重合度",差异越小、重合度越高,"距离" 越近,相似度越高。而 "余弦相似度" 就是计算这种 "指标相似度" 的常用工具。​
另外要注意:KNN 是 "懒惰学习" 算法 —— 它不需要像 "训练模型" 那样提前计算复杂参数,而是直接用历史数据(比如过去 3 个月的服务器异常案例)当 "参考库",有新问题时直接匹配,特别适合 SRE 这种 "需要快速响应、不需要复杂建模" 的场景。

​二、什么是 KNN 分类算法(讲给 SRE 听)

我们先定一个明确的 SRE 任务:​

通过服务器的 "CPU 使用率、内存使用率、网络入流量、进程数" 4 个指标,判断一台服务器当前是 "正常状态" 还是"异常状态"(比如进程泄漏、网络攻击导致的异常)。

任务背景与数据准备

首先我们需要 "历史标注数据—— 也就是过去记录的服务器指标,并且已经明确这些数据对应的服务器状态( "正常” 记为 0, "异常"记为 1),示例数据如下(共 100 条,80 条当 "训练数据",20 条当 "测试数据"):​

样本ID CPU使用率(%) 内存使用率(%) 网络入流量(MB/s) 进程数 状态(标签)
1 10 30 3 5 100
2 20 40 4 40 200
3 30 60 6 100 300
…… …… …… …… …… ……

我们的目标:给一台新服务器的 4 个指标(比如 CPU=90%、内存 = 78%、流量 = 18MB/s、进程数 = 220),用 KNN 判断它是正常(0)还是异常(1)。 

三、KNN 算法的 4 步运维落地流程(以异常检测为例)​

KNN 的流程非常直观,就像 SRE 排查问题的思路,我们一步一步拆解:

3.1、步骤 1:准备 “带标注的历史参考数据”(训练集)

从监控系统(比如 Prometheus)导出过去 3 个月的服务器指标,筛选出有明确状态的 100 条数据:

      • 训练集(80 条):包含 "正常" 和 "异常" 的指标数据,作为 "历史参考案例";​
      • 测试集(20 条):同样有明确状态,但暂时不用,用来验证算法判断的准不准。

3.2、步骤 2:选择 K 值(参考历史案例的数量)

SRE 场景推荐先选 K=5(参考最像的 5 个历史案例),原因:

      • 运维中 "5 个相似案例" 既能覆盖多数情况,又不会混入太多无关案例;​
      • 后续可以通过 "测试集验证" 调整 K 值 —— 比如 K=5 时准确率 92%,K=3 时准确率 88%,就确定用 K=5。

3.3、步骤 3:计算 “未知服务器” 与所有 “历史服务器” 的相似度(核心:余弦相似度)

假设现在有一台 “未知状态服务器”,指标如下:

新服务器指标(样本 A):[CPU=90, 内存 = 78, 流量 = 18, 进程数 = 220]​

我们需要计算它和训练集中 80 条 "历史服务器指标" 的相似度,这里就用到 "余弦相似度" —— 它能帮我们量化 "两个服务器指标向量的相似程度"。​

先搞懂:为什么用余弦相似度?(SRE 场景必要性)​

服务器的 4 个指标,就像一个 "4 维向量"(比如样本 A 的向量是 [90,78,18,220])。两个服务器的 "运行状态越像",它们的指标向量在 "4 维空间" 中的 "方向" 就越接近,余弦相似度的值就越接近 1;反之越接近 0。

比如:

      • 历史上 "进程泄漏异常" 的服务器向量是 [88,75,20,230],和样本 A 的向量方向很像,余弦相似度接近 1;​
      • 历史上 "正常服务器" 的向量是 [25,30,5,80],和样本 A 的向量方向差异大,余弦相似度接近 0。

余弦相似度怎么算?

对于两个指标向量 X(新服务器)和 Y(历史服务器),余弦相似度的公式是:

cosθ = (X·Y) / (|X| × |Y|)

公式里的 3 个部分,我来用数据举例拆解,讲给 sre 听:

举例:计算样本 A 与 "历史异常服务器" 的余弦相似度​
假设历史异常服务器(样本 B)的指标向量是:[88,75,20,230]​
样本 A 向量 X:[90,78,18,220]​
样本 B 向量 Y:[88,75,20,230]

3.3.1、计算 "点积 X・Y",对应指标相乘后求和

X·Y = (90×88) + (78×75) + (18×20) + (220×230)​
= 7920 + 5850 + 360 + 50600​
= 59730

3.3.2、计算 "向量 X 的模长 | X|" ,各指标平方后求和,再开平方

|X| = √(90² + 78² + 18² + 220²)​
= √(8100 + 6084 + 324 + 48400)​
= √62908 ≈ 250.8

3.3.3、计算 "向量 Y 的模长 | Y|",同上

|Y| = √(88² + 75² + 20² + 230²)​
= √(7744 + 5625 + 400 + 52900)​
= √66669 ≈ 258.2

3.1.4、计算余弦相似度,点积 ÷(两个模长的乘积)

cosθ = 59730 ÷ (250.8 × 258.2) ≈ 59730 ÷ 64757 ≈ 0.92​

结果接近 1,说明样本 A 和样本 B(历史异常服务器)非常相似,样本 A 大概率是异常状态。

3.4、步骤 4:投票决定未知服务器的状态

我们计算了样本 A 与训练集中 80 条历史数据的余弦相似度,然后选出 "相似度最高的 5 个邻居"(K=5),假设这 5 个邻居的状态如下:

      • 状态 1(异常):4 个​
      • 状态 0(正常):1 个

按照 "少数服从多数" 的投票原则,样本 A 被判定为 "异常状态"(标签 1),对应运维动作:触发 “进程泄漏排查” 告警,自动执行 “进程重启” 脚本(如果已配置自动化)。​

四、用 Python 写一个服务器异常检测工具

我们用 SRE 最常用的 "Prometheus 指标数据" 为原型,模拟历史标注数据,用 scikit-learn 实现 KNN 算法,最后验证工具的准确率。​

4.1、前置准备

pip install numpy pandas scikit-learn matplotlib  # numpy/pandas处理数据,scikit-learn实现KNN

4.2、完整代码实现(含注释)

# 1. 导入必要的库
import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier  # KNN分类器
from sklearn.model_selection import train_test_split  # 划分训练集/测试集
from sklearn.metrics import accuracy_score, confusion_matrix  # 评估模型(准确率、混淆矩阵)
from sklearn.preprocessing import StandardScaler  # 指标标准化(避免CPU%和进程数量级差异影响结果)# 2. 模拟SRE服务器指标数据(替代鸢尾花数据)
# 生成100条数据:4个指标(CPU%, 内存%, 网络入流量MB/s, 进程数),1个标签(0=正常,1=异常)
np.random.seed(42)  # 固定随机种子,保证结果可复现
# 正常服务器数据(60条):指标偏低且稳定
normal_data = np.random.normal(loc=[30, 35, 8, 100],  # 正常指标均值(CPU30%, 内存35%, 流量8MB/s, 进程100)scale=[5, 6, 2, 15],   # 正常指标波动范围size=(60, 4)
)
normal_label = np.zeros(60)  # 正常标签为0# 异常服务器数据(40条):指标偏高(比如进程泄漏导致CPU/进程数高)
abnormal_data = np.random.normal(loc=[85, 70, 18, 220],  # 异常指标均值(CPU85%, 内存70%, 流量18MB/s, 进程220)scale=[8, 10, 4, 30],   # 异常指标波动范围size=(40, 4)
)
abnormal_label = np.ones(40)  # 异常标签为1# 合并数据:特征矩阵X(100条指标),标签y(100条状态)
X = np.vstack((normal_data, abnormal_data))
y = np.hstack((normal_label, abnormal_label))# 3. 数据预处理:标准化(关键!避免“进程数(100+)”比“CPU%(0-100)”量级大,影响相似度计算)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)  # 标准化后,每个指标的均值为0,标准差为1# 4. 划分训练集(80%,历史参考数据)和测试集(20%,验证准确率)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42  # test_size=0.2表示20%当测试集
)# 5. 创建KNN模型:K=5,用余弦相似度计算距离
knn = KNeighborsClassifier(n_neighbors=5,  # K=5,参考5个邻居metric='cosine'  # 距离 metric 选余弦相似度
)# 6. “训练”模型:KNN实际是存储训练数据,没有传统意义的“训练”
knn.fit(X_train, y_train)# 7. 测试模型:用测试集验证准确率(SRE关注的“工具好不好用”)
y_pred = knn.predict(X_test)  # 用模型预测测试集的状态
accuracy = accuracy_score(y_test, y_pred)  # 计算准确率:预测对的数量/总测试数
confusion = confusion_matrix(y_test, y_pred)  # 混淆矩阵:看“正常判异常”“异常判正常”的情况# 8. 输出结果(运维视角解读)
print("=== 服务器异常检测KNN模型结果 ===")
print(f"模型准确率:{accuracy:.2f}(越高越好,>90%可落地)")
print("\n混淆矩阵(SRE解读):")
print("行=实际状态,列=预测状态;0=正常,1=异常")
print(confusion)
print(f"实际正常、预测正常:{confusion[0][0]}条(没误报,好)")
print(f"实际正常、预测异常:{confusion[0][1]}条(误报,需要优化)")
print(f"实际异常、预测正常:{confusion[1][0]}条(漏报,必须优化,SRE最在意这个)")
print(f"实际异常、预测异常:{confusion[1][1]}条(正确检测,好)")# 9. 实战:预测新服务器的状态(SRE真实场景)
# 新服务器指标:CPU=92%,内存=75%,流量=19MB/s,进程数=230(看起来像异常)
new_server = np.array([[92, 75, 19, 230]])
# 先标准化(必须和训练数据用同一套scaler)
new_server_scaled = scaler.transform(new_server)
# 预测状态
new_pred = knn.predict(new_server_scaled)
# 输出运维建议
if new_pred[0] == 1:print(f"\n=== 新服务器预测结果 ===")print("状态:异常(进程泄漏/资源过载可能性高)")print("运维建议:1. 查看top进程,找到CPU/内存占用高的进程;2. 若为已知泄漏进程,执行重启脚本;3. 记录本次案例到历史数据")
else:print("\n=== 新服务器预测结果 ===")print("状态:正常")print("运维建议:持续监控,无需干预")

4.3、代码运行结果解读

=== 服务器异常检测KNN模型结果 ===
模型准确率:0.95(越高越好,>90%可落地)混淆矩阵:
行=实际状态,列=预测状态;0=正常,1=异常
[[12  0][ 1  7]]
实际正常、预测正常:12条(没误报,好)
实际正常、预测异常:0条(误报,需要优化)
实际异常、预测正常:1条(漏报,必须优化,SRE最在意这个)
实际异常、预测异常:7条(正确检测,好)=== 新服务器预测结果 ===
状态:异常(进程泄漏/资源过载可能性高)
运维建议:1. 查看top进程,找到CPU/内存占用高的进程;2. 若为已知泄漏进程,执行重启脚本;3. 记录本次案例到历史数据

准确率 95%:说明这个工具 100 次预测能对 95 次,满足 SRE 落地需求; 

http://www.hskmm.com/?act=detail&tid=30267

相关文章:

  • 博客园地址 - yuyue
  • 【终章】:幸福的复利——打造你的每日幸福微习惯 - 指南
  • 实用指南:Go 语言中的**数组 (Array)*用法
  • 行业词汇
  • Java实现业务数据报表的邮件定时发送功能
  • 编写Python自动化脚本,使用Autodesk Fusion辅助Ansys HFSS进行建模
  • 单 Pod DNS 记录(`web-0.nginx.default.svc.cluster.local`)排障与启用
  • 云原生周刊:KubeSphere社区版正式发布
  • 最好的感情
  • 三剑客系列-sed命令
  • 超景深立体显微镜厂家Top10推荐:拓界光电引领行业新风尚
  • 20232419 2025-2026-1《网络与系统攻防技术》实验一实验报告
  • 完整教程:用deepseek部署全自动的机器人--bytebot
  • 44. 开发商购买土地
  • 当AI与机器人走进生活:我们即将迎来的日常变革
  • 显微镜厂家TOP10推荐:拓界光电以创新技术引领精密观测新时代
  • net中使用了垃圾回收机制(GC)功能
  • 2025 超景深三维显微镜厂家 TOP10 推荐:三维成像技术的行业应用标杆​
  • 音乐节奏跳动
  • CF2160 Codeforces Round 1058 (Div. 2) 游记
  • 2025年国内铝单板工厂推荐/国内铝单板厂家/ 市场铝单板推/公司榜荐
  • 一个老码农的掏心窝推荐:微擎,我后悔没早点遇到的开发利器
  • 国内铝单板工厂推荐/国内铝单板厂家/ 市场铝单板推荐:四川汇才铝业有限公司
  • 超景深显微镜厂家TOP10推荐:拓界光电引领精密观测新时代
  • 2025 闪蒸/流化床/喷雾/实验型喷雾/离心喷雾/压力喷雾/流化床喷雾/桨叶/盘式/真空耙式干燥机厂家推荐榜单:技术适配与场景落地能力成核心考量
  • 2025 年点胶机源头厂家最新推荐排行榜:自动 / 果冻胶 / 无痕内衣 / 烫钻 / 珠宝热熔胶等多类型设备优质企业精选
  • harbor 局域网https 自签名证书搭建
  • HyperWorks许可证使用报告生成
  • 2025年国内铝单板工厂推荐/国内铝单板厂家/ 市场铝单板推/公司权威排行榜荐
  • 小程序 拖动节点