碎碎念 - 参考站测试
type: channel
link: https://haic.fun/index.php/tag/tag-ca0a4fdc9305/
items: 06 根因分析 RCA：传统算法与 LLM 融合的应用架构
items: 07 分布式锁的生产实践与避坑指南
items: 1. Spark核心调度与容错机制
items: 字符串嵌套解码与基本计算器：栈处理嵌套结构的终极范式
items: 05 核心工作负载对象深度解析
items: 09 LLM 与 Agentic AI：大模型在 AIOps 中的边界与实践

06 根因分析 RCA：传统算法与 LLM 融合的应用架构
type: item
date: 2026-06-09T22:38:29+08:00
description: 测试导入来源：https://ting.is-a.dev/LLM/AiOps/06-%E6%A0%B9%E5%9B%A0%E5%88%86%E6%9E%90-RCA%EF%BC%9A%E4%BC%A0%E7%BB%9F%E7%AE%97%E6%B3%95%E4%B8%8E-LLM-%E8%9E%8D%E5%90%88%E7%9A%84%E5%BA%94%E7%94%A8%E6%9E%B6%E6%9E%8406 根因分析 RCA：传统算法与 LLM 融合的应用架构摘要本文是专栏第六篇，深度解析 AiOps 中最具技术挑战性的能力：根因分析（Root Cause Analysis，RCA）。文章从 RCA 的本质定义和工程边界切入，系统梳理传统 RCA 算法体系（图论方法 RCSF / 统计方法 Isolation Forest / 时序方法变点检测 / 因果推断方法），分析每类算法在大数据集群场景下的适用性和局限性，深度讨论 LLM 介入 RCA 的合理边界（精排器而非决策者）以及”传统算法粗筛 + CoT 推理 + RAG 历史案例检索”的融合架构设计，给出一个工程上可落地的 RCA 流水线设计。本文的核心主张：RCA 不是”用最先进的模型就能解决”的问题，而是”领域知识 + 数据质量 + 算法选择 + 工程约束”的综合工程问题；先把传统算法做扎实，LLM 才能真正发挥增强效果。第 1 章 RCA 的本质定义与工程边界1.1 什么是 RCA根因分析（Root Cause Analysis）在字面意思上很简单：找到问题的根本原因。但在大型分布式系统的运维场景中，这个问题的复杂性被严重低估。在一个有 500 个组件的大数据集群中，一次故障事件可能同时伴随着：300 条告警、50 个可能相关的指标异常、10 个最近的配置变更、若干个可疑的日志错误。如果没有系统性的分析框架，工程师的”排查”往往是靠直觉和经验在这片信息海洋中寻找线索，效率极低。RCA 系统的目标是将这个”海量信息 → 人工经验 → 结论”的过程，转化为”海量信息 → 系统算法 → Top-N 根因候选 + 证据链 → 工程师验证 → 确认结论”的过程。这里有两个关键词需要强调：Top-N（不是 Top-1）：生产环境的 RCA 不是考试出题有标准答案，而是在不确定性中寻找最可能的解释。给出 Top-3 到 Top-5 的候选根因 + 每个候选的置信度分数 + 支撑证据，是比强行给出一个”答案”更诚实、也更实用的输出格式。证据链（而不是黑盒结论）：每一个根因候选，系统必须给出它为什么排在这个位置的理由——哪些指标在什么时间出现了什么异常、与哪个变更有时间关联。没有证据链的 RCA 结论，工程师无法验证，也无法信任，最终会弃用。1.2 RCA 的难点：学术界 vs 工业界的鸿沟关于 RCA 的学术研究非常丰富，但业界落地的实际效果往往跟论文数字有很大差距。这个鸿沟的主要来源是：数据分布差异：学术研究使用的数据集（如 Alibaba Cluster Traces、Google Borg Traces）与特定公司的实际集群数据在统计特征上有显著差异。在公开数据集上准确率 90% 的算法，在私有集群上可能落到 40%。故障类型的长尾分布：大数据集群的故障类型遵循帕累托法则（80% 的故障来自 20% 的故障模式）。对于头部 20% 的故障，很多算法都能做到较高准确率；对于尾部 80% 的罕见故障，算法往往束手无策。而故障复盘最有价值的，往往恰恰是那些罕见的、没有先例的故障类型。标签数据稀缺：监督学习方法需要大量已标注的”告警 X + 根因 Y = 关联”的训练样本。大数据集群的故障复盘数据往往是非结构化的文档，不是可直接用于训练的标注数据。系统动态变化：大数据集群不是静态的——每次版本升级、配置变更、集群扩展，都可能改变故障模式的分布。在旧数据上训练的模型，在集群大改动后可能迅速失效。正因如此，业界最有效的 RCA 实践，往往不是依赖单一的机器学习模型，而是**领域专家规则（覆盖已知故障模式）+ 统计异常检测（发现偏离基线的异常指标）+ 图论方法（沿拓扑传播路径溯源）+ LLM 精排（综合推理和自然语言生成）**的组合方案。第 2 章 传统 RCA 算法体系2.1 图论方法：RCSF（频繁项集挖掘）RCSF（Random Call-context Subgraph Filtering）是由微软等学术机构提出的基于告警调用路径的根因定位算法。其核心思想是：在组件依赖图上，出现异常最集中的区域，最有可能包含根因节点。RCSF 的执行步骤： 从最终用户感知到异常的组件（“症状节点”）出发，在依赖图上生成从症状节点到各个可能根因节点的所有调用路径 将这些路径表示为路径序列（如：[Hiv…

07 分布式锁的生产实践与避坑指南
type: item
date: 2026-06-09T22:37:29+08:00
description: 测试导入来源：https://ting.is-a.dev/%E5%88%86%E5%B8%83%E5%BC%8F/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/07-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E7%9A%84%E7%94%9F%E4%BA%A7%E5%AE%9E%E8%B7%B5%E4%B8%8E%E9%81%BF%E5%9D%91%E6%8C%87%E5%8D%9707 分布式锁的生产实践与避坑指南摘要：前六篇文章系统讲解了分布式锁的理论原理与各方案的实现机制。本篇回到工程现场，聚焦那些理论文章不会告诉你、但在生产环境中真实发生过的问题。内容分为四个维度：锁粒度设计（粒度过粗和过细各有什么代价、如何找到合适的粒度）、加锁失败的降级策略（快速失败 vs 排队等待，如何设计合理的降级链路）、监控与告警（分布式锁应该暴露哪些指标、异常告警阈值如何设定）、以及典型生产故障复盘（真实案例分析：死锁、锁泄漏、锁风暴、误解锁的根因与修复方案）。第 1 章 锁粒度设计：最容易被忽视的架构决策1.1 什么是锁粒度锁粒度（Lock Granularity） 是指分布式锁所保护的资源范围大小。粒度越粗，一把锁保护的资源越多；粒度越细，一把锁保护的资源越少。用一个具体的例子来说明：假设一个电商系统需要保护库存扣减操作。锁粒度可以是：粒度 1（最粗）：全局库存锁 lock_key = "inventory_lock" → 所有商品的库存扣减都竞争同一把锁 → 串行化程度最高，吞吐量最低 粒度 2：商品级锁 lock_key = "inventory_lock:product:{productId}" → 不同商品的库存扣减互不影响 → 同一商品的并发请求串行化 粒度 3：商品+仓库级锁 lock_key = "inventory_lock:product:{productId}:warehouse:{warehouseId}" → 不同仓库的同一商品可以并发扣减 → 粒度最细，并发度最高 粒度 4（最细）：订单级锁 lock_key = "inventory_lock:order:{orderId}" → 每个订单独享一把锁 → 但无法防止同一商品被多个订单同时超卖 1.2 锁粒度过粗的代价核心问题：并发度被人为压低粒度过粗的锁会将大量本不需要互斥的操作强制串行化。考虑上例中”全局库存锁”方案：商品 A 和商品 B 的库存扣减操作完全独立，没有任何共享资源需要保护，但全局锁强迫它们排队执行。量化影响：假设单次库存扣减操作耗时 10ms，使用全局锁的系统 QPS 上限 = 1000ms / 10ms = 100 QPS。而使用商品级锁，如果有 1000 种商品，理论上可以支持 100,000 QPS（1000 商品 × 100 QPS）。真实案例：某电商平台在大促活动中，将所有商品的秒杀库存扣减都用一把全局 Redis 锁保护，在压测中发现 QPS 极低（仅 200 左右），原因就是全局锁将所有商品的扣减操作完全串行化。修改为商品级锁（lock_key = "seckill:product:{productId}"）后，QPS 提升了 200 倍。1.3 锁粒度过细的代价核心问题：数据一致性边界被打破粒度过细的锁可能无法保护真正需要保护的一致性约束。以上例中”订单级锁”为例：每个订单都有自己的锁，但订单之间是可以并发执行的。如果两个订单同时对同一商品进行库存扣减，它们各自持有不同的订单锁，互不阻塞，最终可能导致超卖。粒度过细的另一个问题是锁数量爆炸。如果系统中有百万级商品，“商品+用户级锁”会产生海量不同的 lock_key，虽然每把锁的竞争度都很低，但这些锁记录会占用大量内存（Redis）或 ZNode（ZooKeeper），同时增加了锁管理的复杂度。量化参考（Redis）：一个 Redis String key 约占 50100 字节（含 key 名、value、元数据）。百万级 lock_key = 约 50100MB 内存占用，通常可以接受；但亿级 lock_key = 5~10GB，可能影响 Redis 的内存和扫描性能。1.4 锁粒度的设计原则原则一：以”最小化互斥范围”为目标锁的范围应该恰好覆盖”需要原子执行的操作集合”，不多也不少。如果两个操作之间完全没有共享资源（不存在数据竞争），就不应该让它们互斥。原则二：先识别”竞争维度”，再设计 key 结构竞争维度是指哪个维度的并发操作可能产生冲突。常见的竞争维度： 用户维度：同一用户的并发请求（防止重复下单）→ lock_key = "order:user:{userId}" 资源维度：竞争同一资源（防止超卖）→ l…

1. Spark核心调度与容错机制
type: item
date: 2026-06-09T22:36:29+08:00
description: 测试导入来源：https://ting.is-a.dev/%E5%A4%A7%E6%95%B0%E6%8D%AE/Spark/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0-spark%E5%86%85%E6%A0%B8/03_%E8%B0%83%E5%BA%A6%E4%B8%8E%E6%89%A7%E8%A1%8C%E6%9C%BA%E5%88%B6/1.-Spark%E6%A0%B8%E5%BF%83%E8%B0%83%E5%BA%A6%E4%B8%8E%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B6导语在大数据处理领域，Spark以其卓越的性能和易用性成为业界标杆。理解Spark内部的DAG调度机制和容错原理，是掌握Spark性能调优和故障排查的关键。本文将深入剖析Spark如何通过DAG优化计算流程，以及RDD如何实现高效的容错机制。一、DAG逻辑视图：Spark的计算优化引擎1.1 DAG的基本概念在Spark中，有向无环图（DAG） 是任务调度的核心数据结构。DAG将一个计算作业分解为一系列有依赖关系的任务，每个顶点代表一个任务，每条边代表任务间的依赖约束。flowchart TD A["读取文件"] --> B["flatMap操作"] B --> C["map操作"] C --> D["reduceByKey本地操作"] D -->|"Shuffle"| E["reduceByKey Shuffle操作"] E --> F["结果输出"] subgraph "Stage 0" A B C D end subgraph "Stage 1" E end 1.2 DAG生成机制1.2.1 Stage划分原理Spark通过Stage划分来优化计算流程，划分依据是RDD的依赖关系：依赖类型特点Stage处理方式窄依赖父RDD的每个分区最多被子RDD的一个分区使用归并到同一个Stage宽依赖父RDD的分区可能被子RDD的多个分区使用（需要Shuffle）在此处切断，形成新的StageStage划分算法（回溯算法）： 初始时将所有RDD视为一个Stage 从最后一个RDD开始向前回溯 遇到宽依赖（Shuffle）时切断，形成新的Stage 遇到窄依赖时，合并到当前Stage 回溯完成后形成完整的DAG图 1.2.2 源码实现DAG生成的核心逻辑位于DAGScheduler.scala，关键方法getOrCreateParentStages：privatedefgetOrCreateParentStages(rdd:RDD[_],firstJobId:Int):List[Stage]={ getShuffleDependencies(rdd).map { shuffleDep=> getOrCreateShuffleMapStage(shuffleDep, firstJobId) }.toList } private[scheduler]defgetShuffleDependencies( rdd:RDD[_]):HashSet[ShuffleDependency[_, _, _]]={ valparents=newHashSet[ShuffleDependency[_, _, _]] valvisited=newHashSet[RDD[_]] valwaitingForVisit=newStack[RDD[_]] waitingForVisit.push(rdd) while(waitingForVisit.nonEmpty) { valtoVisit=waitingForVisit.pop() if(!visited(toVisit)) { visited+=toVisit toVisit.dependencies.foreach { caseshuffleDep:ShuffleDependency[_, _, _]=> parents+=shuffleDep casedependency=> waitingForVisit.push(dependency.rdd) } } } parents }1.3 WordCount案例的DAG生成分析通过一个具体的WordCount示例，我们可以直观理解DAG的生成过程：valconf=newSparkConf() conf.setAppName("WordCount Example") conf.setMaster("local") valsc=newSparkContext(conf) vallines=sc.textFile("data.txt",1) valwords=lines.flatMap { line=>line.s…

字符串嵌套解码与基本计算器：栈处理嵌套结构的终极范式
type: item
date: 2026-06-09T22:35:29+08:00
description: 测试导入来源：https://ting.is-a.dev/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/%E6%A0%88%E4%B8%8E%E9%98%9F%E5%88%97/07-%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B5%8C%E5%A5%97%E8%A7%A3%E7%A0%81%E4%B8%8E%E5%9F%BA%E6%9C%AC%E8%AE%A1%E7%AE%97%E5%99%A8字符串嵌套解码与基本计算器：栈处理嵌套结构的终极范式摘要本篇是栈与队列专栏的收尾篇，以两道经典题收尾：LeetCode 394（Decode String）和 LeetCode 224（Basic Calculator）。它们共同揭示了栈处理嵌套结构的通用范式：遇到开括号时，将当前状态压栈以”保存现场”；遇到闭括号时，弹栈以”恢复现场”，然后在恢复的状态上继续处理。掌握这个范式，括号匹配、嵌套解析、递归求值等一类问题都可以用同一套思维框架解决。篇末附有专栏全局复习：题目索引、高频考点、学习路径与下一步建议。第 1 章 LeetCode 394：字符串解码1.1 题目LeetCode 394 - Decode String（中等）给定一个编码字符串，按规则解码并返回结果：k[encoded_string] 表示将 encoded_string 重复 k 次。数字 k 可以是多位数，嵌套可以有多层。"3[a]2[bc]" → "aaabcbc" "3[a2[c]]" → "accaccacc" "2[abc]3[cd]ef" → "abcabccdcdcdef" 约束：数字只出现在 [ 前，字母只出现在方括号内或方括号外（不会有数字紧跟字母的情况如 3a），输入字符串保证合法。1.2 思路推导递归思路：3[a2[c]] 的含义是：解码 a2[c]，然后重复 3 次。解码 a2[c] 又需要解码 c 重复 2 次——这是一个递归结构，每遇到 [ 就”下一层”，遇到 ] 就”上一层”。用栈模拟递归：递归和栈本质等价。用两个栈： countStack：保存当前层的重复次数 k stringStack：保存当前层在遇到 [ 之前已经构建好的字符串 逐字符处理规则：当前字符操作数字累积多位数：num = num * 10 + digit[将当前 num 和 current 分别压入 countStack 和 stringStack；重置 num=0, current=""]弹出 count 和 prev；current = prev + current.repeat(count)字母直接追加到 current1.3 代码实现publicStringdecodeString(String s) { Deque<Integer> countStack=newArrayDeque<>();// 保存重复次数 Deque<StringBuilder> stringStack=newArrayDeque<>();// 保存上一层字符串 StringBuilder current=newStringBuilder();// 当前层正在构建的字符串 intnum=0;// 当前累积的数字 for(charc:s.toCharArray()) { if(Character.isDigit(c)) { // 累积多位数 num=num*10+(c-'0'); }elseif(c=='[') { // 保存现场：当前 num 和 current 压栈 countStack.push(num); stringStack.push(current); // 重置，准备处理下一层 num=0; current=newStringBuilder(); }elseif(c==']') { // 恢复现场：弹出重复次数和上一层字符串 intcount=countStack.pop(); StringBuilder prev=stringStack.pop(); // current 重复 count 次，拼接到 prev 后面 for(inti=0; i<count; i++) { prev.append(current); } current=prev;// 恢复为上一层 }else{ // 普通字母，追加到当前层 current.append(c); } } returncurrent.toString(); }1.4 逐步模拟s = "3[a2[c]]" 字符处理过程： '3': num=3 '[': 压栈 count=3, prev=""; num=0, current="…

05 核心工作负载对象深度解析
type: item
date: 2026-06-09T22:34:29+08:00
description: 测试导入来源：https://ting.is-a.dev/%E4%BA%91%E5%8E%9F%E7%94%9F/Kubernetes/kubernetes%E6%9E%B6%E6%9E%84%E5%8E%9F%E5%88%99%E5%92%8C%E5%AF%B9%E8%B1%A1%E8%AE%BE%E8%AE%A1/05-%E6%A0%B8%E5%BF%83%E5%B7%A5%E4%BD%9C%E8%B4%9F%E8%BD%BD%E5%AF%B9%E8%B1%A1%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%9005 核心工作负载对象深度解析摘要：前几篇文章建立了 K8s 的基础认知框架：设计哲学、组件架构、API 对象模型、Label/Selector 关联机制。本文将这些知识聚焦到用户日常接触最多的领域——工作负载对象。K8s 定义了多种工作负载对象来满足不同的应用运行模式：Pod 是最小的调度单元，Deployment 管理无状态服务的副本和滚动更新，StatefulSet 为有状态应用提供稳定标识和有序管理，DaemonSet 确保每个节点运行特定的守护进程，Job/CronJob 处理一次性和定时批处理任务。本文不止于”这些对象是什么”——更重要的是剖析为什么需要这种对象、没有它会怎样、它解决了哪些具体的工程问题，使读者能够在面对实际业务需求时准确选择合适的工作负载类型。第 1 章 Pod：为什么不是容器而是 Pod1.1 Pod 的定义Pod 是 Kubernetes 中最小的可调度单元——注意不是”容器”，而是”Pod”。一个 Pod 可以包含一个或多个容器，这些容器共享网络（同一个 Network Namespace）和存储（共享 Volume），被作为一个整体调度到同一个节点上。1.2 为什么不直接调度容器这是理解 Pod 设计的核心问题。Docker 和 containerd 都以单个容器为管理单元——为什么 K8s 要在容器之上再抽象一层”Pod”？原因一：紧耦合的辅助进程很多应用不是一个单独的进程就能完成所有工作的。考虑一个 Java Web 应用： 主容器：Tomcat 运行业务逻辑 日志采集 Sidecar：Filebeat 从共享的日志目录读取日志并发送到 Elasticsearch 配置热加载 Sidecar：监听 ConfigMap 变化并通知主容器重新加载配置 这三个进程有极强的共生关系——它们必须运行在同一台机器上（共享日志目录），需要通过 localhost 通信（主容器暴露管理端口供配置热加载 Sidecar 调用），它们的生命周期应该绑定在一起（主容器崩溃时，日志采集也应该停止）。如果 K8s 以容器为调度单元，这三个容器可能被调度到不同的节点上——日志采集容器无法读取主容器的日志文件。你需要手动添加亲和性约束确保它们在同一节点，还需要自己管理共享存储和网络——这些正是 Pod 自动处理的。原因二：共享网络栈的需求在 02 Linux Namespace 深度解析 中我们介绍了 Kubernetes 的 Pod 网络模型——同一个 Pod 内的所有容器共享一个 Network Namespace。这意味着： 容器之间可以通过 localhost 互相访问 它们共享同一个 IP 地址和端口空间 不需要跨网络的服务发现 如果没有 Pod 的抽象，要实现这种”同一网络空间”的共享，用户需要手动使用 Docker 的 Container 网络模式（--network container:<name>）——这在大规模集群中几乎不可管理。原因三：共享存储的需求Pod 中的容器可以通过 Volume 共享文件。上面的日志采集场景中，主容器将日志写入一个 emptyDir Volume，Sidecar 从同一个 Volume 读取——不需要跨网络传输，直接读取本地文件系统。1.3 Pod 内部的 pause 容器在 02 Linux Namespace 深度解析 中我们已经提到过 pause 容器（也叫 infra 容器或 sandbox 容器）。kubelet 创建 Pod 时，首先创建一个极其轻量的 pause 容器——它的进程只是调用 pause() 系统调用永远休眠。pause 容器的唯一作用是持有 Pod 的 Network Namespace 和 IPC Namespace。Pod 中的其他业务容器通过 setns() 加入 pause 容器的 Namespace。这样即使业务容器重启（进程崩溃后被 kubelet 重新创建），Pod 的 Network Namespace 仍然由 pause 容器持有——Pod 的 IP 地址不会因为业务容器重启而变化。1.4 …

09 LLM 与 Agentic AI：大模型在 AIOps 中的边界与实践
type: item
date: 2026-06-09T22:31:44+08:00
description: 测试导入来源：https://ting.is-a.dev/%E5%8F%AF%E8%A7%82%E6%B5%8B/AIOps%E4%B8%8E%E5%8F%AF%E8%A7%82%E6%B5%8B%E6%80%A7%E5%AE%9E%E6%88%98/09-LLM-%E4%B8%8E-Agentic-AI%EF%BC%9A%E5%A4%A7%E6%A8%A1%E5%9E%8B%E5%9C%A8-AIOps-%E4%B8%AD%E7%9A%84%E8%BE%B9%E7%95%8C%E4%B8%8E%E5%AE%9E%E8%B7%B5摘要2023 年 ChatGPT 的爆发让整个技术圈陷入了一种集体幻觉：大语言模型将颠覆所有软件工程实践，包括运维。“AI SRE”的概念在各大技术会议上频繁出现，不少公司开始内部测试”让 LLM 自动处理告警”。两年后，理性回归：LLM 在特定运维场景中有显著价值，但也有不可忽视的能力边界。本文将直面大模型在 AIOps 中的真实能力与局限，探讨 Agentic AI 架构的设计原则，以及 Human-in-the-Loop 的工程实践。第 1 章 LLM 与传统 AIOps 的本质差异1.1 规则引擎 vs 大模型：两种不同的智能形态在 LLM 出现之前，AIOps 主要依赖两类技术：规则引擎（基于专家知识编写的 if-then 规则，处理已知的告警模式）和机器学习模型（Isolation Forest、LSTM 等，处理数值型时序数据）。这两种技术有一个共同的特点：它们只能处理被显式建模的情况。规则引擎只能触发预先写好的规则，机器学习模型只能识别训练数据中出现过的模式。对于从未见过的新型故障，这两种方法都是盲区。LLM 带来了一种本质不同的智能形态：基于语言理解的通用推理。当工程师把故障时的日志、指标摘要、告警信息输入 LLM，LLM 不需要见过完全相同的故障，就能根据其在海量技术文档上的预训练知识，推断出可能的原因并建议排查步骤。这个能力的核心价值是：降低处理”新型故障”的认知门槛。对于一个刚入职的 SRE 新人，面对一个从未见过的错误类型，通过向 LLM 描述症状，可以快速获得有价值的排查方向，不需要在 Google 搜索中逐步摸索。1.2 LLM 的三个核心运维能力能力一：自然语言查询可观测性系统的技术门槛之一是查询语言（PromQL、LogQL、NRQL）的学习成本。工程师需要花相当时间学习这些领域特定语言，才能从监控系统中提取想要的信息。LLM 可以将自然语言查询转化为对应的查询语句：用户输入”显示过去 1 小时内支付服务的错误率趋势”，LLM 输出对应的 PromQL 表达式。这降低了可观测性工具的使用门槛，让开发人员（而不只是专职 SRE）也能快速查询相关指标。能力二：日志语义分析传统的日志分析依赖关键词搜索（grep）或结构化字段过滤，无法理解日志的语义上下文。LLM 能够理解日志的自然语言含义，回答”这段日志中有哪些潜在的问题”或”这个错误栈最可能的原因是什么”等语义性问题。能力三：知识库问答将 Runbook、架构文档、历史 Post-mortem 报告向量化存储（RAG 模式），构建一个可检索的技术知识库。工程师在处理告警时，可以向 LLM 提问”这类问题以前是如何解决的”，LLM 从知识库中检索相关案例并给出参考答案。第 2 章 LLM 的能力边界：哪些事不能做2.1 LLM 不擅长的运维任务直面 LLM 的局限，是避免在 AIOps 实践中踩坑的前提：精确的数值推理：LLM 在处理数值计算时不可靠，特别是涉及概率、统计、比率计算等场景。“过去 1 小时内错误率升高了多少百分点”这个问题，不应该让 LLM 计算，而应该通过 Prometheus 查询得到精确结果后再告知 LLM。实时系统状态感知：LLM 没有直接访问监控系统的能力（除非通过工具集成）。在没有实时数据接入的情况下，LLM 不知道”现在”系统的状态，只能基于用户提供的信息做分析。让 LLM 在没有数据的情况下判断”系统现在是否健康”，只会得到幻觉答案。精确的系统拓扑感知：LLM 没有你的系统拓扑知识（服务依赖关系、数据流向、基础设施部署方式），除非你明确地在 prompt 中提供这些信息。LLM 可能基于通用的微服务架构假设给出建议，但这些建议不一定适合你的具体架构。生产操作的执行：LLM 不应该直接执行生产环境的修改操作（重启服务、修改配置、回滚部署）。LLM 的输出是”建议”，而不是”命令”。所有的生产操作，必须经过人类工程师的审核和确认。2.2 幻觉问题在 AIOps 中的风险LLM 的”幻觉”（Hallucination）——生成听起来合理但实际上错误的信息——在一般文本任务中是烦人的缺陷，在运维场景…