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

news/2025/10/13 19:02:40/文章来源:https://www.cnblogs.com/zuoyang/p/19139125

【左扬精讲】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.mzph.cn/news/936347.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】AVL详解 - 教程

【C++】AVL详解 - 教程2025-10-13 18:55 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font…

深入解析:Scikit-learn Python机器学习 - 回归分析算法 - Lasso 回归 (Lasso Regression)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

讲给 SRE 听 —— 零基础入门 KNN 分类算法【左扬精讲】:SRE 运维场景实战(含余弦相似度)

讲给 SRE 听 —— 零基础入门 KNN 分类算法【左扬精讲】:SRE 运维场景实战(含余弦相似度) 一、从 SRE 日常工作理解 KNN 的核心逻辑作为 SRE,你是否经常遇到这样的场景:​某天监控告警响起,某台服务器 CPU 突然飙…

【终章】:幸福的复利——打造你的每日幸福微习惯 - 指南

【终章】:幸福的复利——打造你的每日幸福微习惯 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas…

完整教程:SQLMap注入学习靶机(打靶记录)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

实用指南:Go 语言中的**数组 (Array)*用法

实用指南:Go 语言中的**数组 (Array)*用法pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…

行业词汇

理发|剪发|熟食|时尚|一元|折扣|零食|香油|蛋糕|炸鸡|营业厅|五金|鞋|衣服|服饰|广场|热水器|农合|供销社|牙|药店|日用|烤肉|大盘鸡|虾|农贸|早餐|胡辣汤|化妆品|婚庆|餐厅|餐馆|饭|饮食|酒吧|咖啡|快餐|茶餐厅|小吃|…

Java实现业务数据报表的邮件定时发送功能

Java实现业务数据报表的邮件定时发送功能Java实现业务数据报表的邮件定时发送功能 1.定义apollo的邮件收件人的邮箱地址apollo: @Value("${scooterDataReportEmailAddress}") private String scooterD…

编写Python自动化脚本,使用Autodesk Fusion辅助Ansys HFSS进行建模

前言 最近正在复现一个Vivaldi天线,需要绘制由曲线阵列的圆形构成的开槽。由于HFSS如同大便一般的建模逻辑实在不方便完成这个操作,我决定研究一下使用Autodesk Fusion进行阵列,再将坐标导入到Ansys HFSS中绘制圆柱…

单 Pod DNS 记录(`web-0.nginx.default.svc.cluster.local`)排障与启用

Kubernetes Headless Service & StatefulSet1. 现象Service 类型为 Headless(clusterIP: None) Endpoint 已列出所有 Pod IP Pod 状态 Ready 1/1 但仍无法解析 web-0.nginx.default.svc.cluster.local2. 根因 Co…

云原生周刊:KubeSphere社区版正式发布

云原生热点 KubeSphere社区版正式发布:永久免费,秒享企业级容器管理! 近日, KubeSphere 社区版正式发布,面向开发者与中小团队,永久免费、企业级体验。这一里程碑式版本让云原生技术更易获取、更高效可用。 🌟…

GauGAN详解与实现 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

网络基础17:IRF实验(H3C设备) - 指南

网络基础17:IRF实验(H3C设备) - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Mo…

最好的感情

最好的感情: 是随意,却又彼此在意, 是惬意,却又彼此珍惜。 各自独立,而心在一起; 各自呼吸,而爱不分离。 两个人在一起,最重要的感觉就是舒服。 即使默默不语,也是一种默契; 纵然两两相望,也是一种惺惺相惜…

三剑客系列-sed命令

三剑客与正则系列 - sed 命令 1.1 概述核心功能:取行,过滤,替换修改文件内容。 难点:后向引用(截取)。 sed stream editor 流编辑器。1.2 格式命令 选项 详细格式 参数sed 选项条件动作 文件 找谁干啥1 找谁:…

超景深立体显微镜厂家Top10推荐:拓界光电引领行业新风尚

超景深立体显微镜厂家Top10推荐:拓界光电引领行业新风尚在精密制造与科研探索的广阔天地中,超景深立体显微镜以其独特的景深扩展能力和三维成像技术,成为洞察微观世界不可或缺的“智慧之眼”。本文精心筛选出超景深…

深入解析:D018 vue+django 旅游图谱推荐问答系统|neo4j数据库|智能问答

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

20232419 2025-2026-1《网络与系统攻防技术》实验一实验报告

一、实验目标及内容 实验内容:手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。注入一个自己制作的shellcode并运行…

完整教程:用deepseek部署全自动的机器人--bytebot

完整教程:用deepseek部署全自动的机器人--bytebotpre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas"…

44. 开发商购买土地

44. 开发商购买土地 前缀和 思路 可能的情况有两类,A占前 i 行,B占剩余行;A占前 j 列,B占剩余列。 若直接暴力枚举,第一层 for 循环遍历行(控制行的切分),第二层、第三层 for 循环计算A区域中元素和,时间复杂…