一只阿木木

我有一个两年没有打开过的知识库

我有一个两年没有打开过的知识库

——"赛博时代的认知进化论"系列 第四篇


2022年的某个周五下午,我们的线上服务出现了一个故障。

现象很奇怪:每隔大约四十分钟,某个核心接口的响应时间会突然飙升,持续大约三分钟,然后恢复正常,像钟表一样精确。

我们排查了将近两个小时。看监控,看日志,看数据库慢查询,都没有发现明显的问题。

然后我们的运维同事老陈走过来,站在我们背后看了一眼监控图,说了一句话:

“是不是定时任务和GC撞上了?”

我们转头看他。他解释说,这个周期和JVM的GC触发间隔很接近,如果有一个定时任务恰好在GC的时候执行大量的对象创建,就会放大GC的停顿时间,造成这个周期性的响应延迟。

我们去查了定时任务的执行日志,完全吻合。

问题十分钟之内解决了。


事后我问老陈,他怎么会第一眼就想到这个方向。

他想了一会儿,说:“我也不知道,就是……见过类似的。”

说不清楚,但就是知道。

这是我在之前几篇文章里一直在讲的那个东西:隐性知识。

但这一次,我想从另一个角度来看它。

老陈的那个直觉,不是凭空产生的。它来自于某一次他亲手处理过的故障,某一次他在深夜对着监控图发呆,最终找到了那个根因的经历。

那个经历,在他脑子里存了多少年,我不知道。

但我知道一件事:如果他当年把那次经历记在了Obsidian里,然后两年之内再也没有打开过,那条笔记和没有记是一样的。


这让我意识到一个问题,一个我在建立知识库的过程中一直没有认真面对过的问题:

知识会腐烂吗?


一、你的知识库,此刻正在腐烂

作为一个程序员,我对"腐烂"这个词并不陌生。

代码会腐烂。一段今天运行正常的代码,两年之后可能因为依赖库升级、运行环境变化、业务逻辑迭代,变成一段随时会爆炸的定时炸弹。程序员有一个专门的词来描述这个现象:技术债务(Technical Debt)。

知识也会腐烂。只是腐烂的方式不一样。

代码的腐烂是外部环境变化导致的。知识的腐烂是你自己变化导致的。

两年前,你对某个问题的理解是A。两年后,你经历了更多,读了更多,你对同一个问题的理解变成了B。但你两年前写的那条笔记,还安静地躺在你的Obsidian库里,上面写着A,像一个停止走动的时钟。

更危险的是:你已经忘了那条笔记的存在。

所以当你下一次遇到相关的问题,你不会去查那条笔记。但如果你偶尔翻出来,以你现在的认知水平,你会觉得两年前的自己说的是废话,或者说的是错的,但你不会去修改它,因为那条笔记和你现在做的事情没有直接关系,修改它感觉是在浪费时间。

然后它继续躺在那里。腐烂,但无声无息。


我去年做了一件有点残忍的事。

我随机打开了Obsidian库里五十条笔记,专门挑那些超过一年没有被访问过的。然后我逐条判断:这条笔记现在还是对的吗?

结果让我沉默了一段时间。

五十条里,我认为完全准确、现在仍然成立的,只有十一条。

有十九条,我有了新的理解,但笔记里没有更新。

有十三条,我的观点已经彻底改变,但笔记里写的还是旧观点。

有七条,我已经完全不记得我为什么写了这个,上下文丢失了。

72%的笔记,处于不同程度的腐烂状态。

这不是我的问题,这是所有知识库的命运——如果你不主动干预的话。


然后我开始思考:有没有一套方法,能让知识库自动维护自己?

我找到了一个答案,在一个意想不到的地方。


二、一个客服行业的方法论,解决了我最头疼的问题

KCS,全称Knowledge-Centered Service,是由一个叫做"服务创新联盟(Consortium for Service Innovation)"的组织开发的方法论,主要用于企业的客服和IT支持团队管理知识库。

第一次听到这个来源,我的第一反应是:这跟我有什么关系?

但当我真正读进去之后,我意识到KCS解决的问题,和我的个人知识库面临的问题,在结构上是完全一样的。

KCS的核心洞察只有一句话,但它让我重新理解了"维护"这件事:

知识库不应该被专门维护,它应该在被使用的过程中自动维护自己。


传统的知识库维护逻辑是这样的:

  1. 有一批专门负责写文档的人(或者你自己在专门"整理笔记"的时间里)。

  2. 他们先把知识整理好,然后发布。

  3. 知识库随着时间推移开始腐烂。

  4. 定期安排专门的时间来更新。

这套逻辑的问题在哪里?

在于步骤1和步骤4都是脱离使用场景的纯维护行为。你坐下来专门"整理笔记",但你不在一个真实的问题场景里,你不知道哪条笔记是真正重要的,你也不知道哪条笔记说的是错的,因为你没有在用它解决问题。

这就像是你在家里对着镜子练习游泳——动作可能是正确的,但你不在水里,你感受不到水的阻力,所以你无法判断哪里需要改进。

KCS提出了一个完全不同的逻辑,叫做**“在使用中修正(Fix it when you use it)”**。

核心流程是四个字:Use it, Flag it, Fix it, Add it。

  • Use it:当你遇到一个问题,先去知识库里找。如果找到了相关内容,用它来解决问题。

  • Flag it:在使用的过程中,如果你发现这条知识有问题——过时了、不准确了、不完整了——给它打一个标记。

  • Fix it:在这个当下,你最清楚这条知识哪里不对,因为你刚刚用它碰壁了。趁热把它修正。

  • Add it:如果你搜索之后发现知识库里根本没有这个问题的答案,那就在这个当下,把你摸索出来的解决过程,记录下来,加进去。

这个逻辑的革命性在于:维护行为和使用行为合并了。

你不再需要专门的"整理时间"。每一次你使用知识库解决问题的过程,同时就是你在维护知识库的过程。


我在自己的Obsidian工作流里,把这个逻辑直接移植了进来。

效果是这样的:

之前,我会在每个周日晚上,给自己安排一个小时的"整理笔记时间"。这一个小时里,我会打开库,翻一翻,觉得哪条笔记应该补充就补充一下,觉得应该连接就连接一下。

这一个小时,是我最容易放弃的一个习惯,因为它的收益感极低。你不知道你在整理的东西有没有价值,你不知道你修改的方向对不对,整个过程充满了一种无力感。

后来,我把这个逻辑改成了:每次我在工作中用到某条笔记,或者翻出某条笔记发现它不对了,我就在那个当下,花五分钟修正它。

不在专门的时间。不在专门的心情。在那个我刚刚被它坑过、或者刚刚被它帮过的当下。

这个转变之后,我的知识库发生了一件有点奇怪的事:它开始活了。


三、一次真实的"Fix it"过程

2024年的某个下午,我在处理一个服务超时的问题,想起来我好像在某条笔记里记过关于"超时设置策略"的内容。

我在Obsidian里搜索,找到了那条笔记。笔记写于2022年,标题是"微服务超时时间如何设置",内容是一套我当时觉得很合理的策略:根据接口的历史平均响应时间,设置2倍作为超时阈值。

我看了看,然后开始往下执行。

但执行过程中,我遇到了一个这条笔记没有提到的问题:如果下游服务本身存在长尾延迟(少数请求响应时间极长),2倍平均值的阈值会导致这些长尾请求大量超时重试,反而加重下游的压力,形成雪崩。

这是我在过去两年里踩过的一个真实的坑,但2022年我写那条笔记的时候还没踩过,所以笔记里没有这个内容。

按照KCS的逻辑,我就在那个当下,打开了那条笔记,加了一段:

Markdown

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## 2024.8.12 更新——长尾延迟场景的补充

如果下游服务存在长尾延迟(P99 >> P50),
不应该以平均响应时间为基准设置超时阈值。

更好的方式是:
1. 用P95或P99作为基准,而不是平均值
2. 同时设置熔断,当超时率超过阈值时直接熔断,
   而不是让重试请求持续打压下游

原因:2倍平均值的阈值对正态分布有效,
     对长尾分布会放大尾部效应。

踩坑记录:[日期]的某某服务超时事故,
          根因就是这个问题。

总共花了七分钟。

然后我继续处理手头的问题。


但这里有一个现实的难题:

我怎么知道哪些笔记已经腐烂了,但我还没有用到它们?

KCS的"Fix it when you use it"逻辑,只能修正那些"恰好被用到"的笔记。那些安静躺在库里、从来没被用到但已经腐烂的笔记,怎么办?

这是KCS解决不了的问题。这是我们需要引入AI的地方。


四、让AI当你的"知识库体检医生"

我在Obsidian里用Dataview插件建了一个仪表盘,它会自动找出两类笔记:

第一类:很久没有被访问,但被大量其他笔记引用的笔记。

这些笔记是你的知识库里的"枢纽节点"——很多其他知识都依赖它们,但你自己已经很久没有检查它们是否还准确了。这是腐烂风险最高的一类。

第二类:最近被访问过,但没有被修改过的笔记。

这类笔记是你最近遇到问题时翻出来过的,但你当时没有更新。可能是因为它基本准确,也可能是因为你当时太忙,“先用着,回头再说”,然后忘了。

Dataview的查询代码:

dataview

1
2
3
4
5
6
7
8
9
10
11
TABLE 
  file.mtime as "最后修改",
  file.atime as "最后访问",
  length(file.inlinks) as "被引用次数"
FROM ""
WHERE 
  date(today) - file.atime < dur(30 days)
  AND date(today) - file.mtime > dur(90 days)
  AND length(file.inlinks) > 3
SORT length(file.inlinks) DESC
LIMIT 20

这个查询的含义是:找出那些最近30天内被访问过、但超过90天没有被修改过、且被超过3条其他笔记引用的笔记,按被引用次数降序排列,取前20条。

这20条,就是你的"高风险腐烂候选人"。


但找出来之后怎么办?

逐条手动检查,太累了。

这里我用了一个我自己觉得比较有效的AI辅助方式,我称之为**“时间机器对话”**:

把一条旧笔记的内容发给AI,然后这样问:

text

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
以下是我在[写作时间]写的一条笔记:

[粘贴笔记内容]

请帮我做一个"时间机器检查":

1. 这条笔记的核心观点,在今天(2025年)还成立吗?
   如果有已知的反例或新的发展,请指出来。

2. 这条笔记是否存在"当时正确,但现在环境变了所以不适用"的部分?

3. 这条笔记里,有没有哪个地方的表述过于绝对,
   实际上应该加上更多的条件限制?

不需要帮我重写这条笔记,只需要告诉我哪里可能有问题。

AI会给你指出潜在的问题,但你自己来判断这些问题是否真实存在,以及如何修改。

这一点非常重要。

AI不了解你的具体上下文,它只能告诉你"这个观点在通用场景下可能不成立",但你写这条笔记的时候,可能是针对一个非常具体的场景,所以它实际上是成立的。

AI是你的检查工具,不是你的修改工具。


但在我使用这套工作流大约半年之后,我碰到了一个让我觉得有些意外的问题。

某条笔记被AI判断为"有问题"。我去检查,发现AI说得有道理,我的观点确实应该修改。

我改了。

然后我突然想:原来那个"错误"的观点,我是怎么形成的?

我翻了翻那条笔记的修改历史,没有。Obsidian默认不保存历史版本。

那个"错误的过程",就这样消失了。


这让我想到了另一本书,一本看起来和知识管理毫不相关的书:

《清单革命》(The Checklist Manifesto),作者阿图·葛文德(Atul Gawande),一个外科医生。

这本书讲的是医疗、航空、建筑行业如何用清单来避免人为失误。但葛文德在书里有一个观察,让我印象非常深刻:

最有价值的清单,不是"正确操作的步骤",而是"历史上曾经出错的步骤"。

航空业的飞行前检查清单,里面每一条都不是凭空写的。每一条背后,都是一次真实的事故,一条真实的人命。那份清单,是用错误换来的。

正因为如此,那份清单才有重量。

那些条目,不只是在告诉飞行员"做这一步",它们在说:“曾经有人跳过了这一步,然后飞机掉下来了。”

那份清单,是对失败的记忆。


我的知识库,缺少的正是这种东西。

我记录了我学到的东西,但我没有记录我学错的东西。

我记录了正确的结论,但我没有记录走到这个结论之前那些被我推翻的错误路径。

当我把一条"错误的旧观点"改成"正确的新观点"之后,那个错误就永远消失了。但那个错误,也许正是另一个人现在正在犯的错误。也许是三年后的我,在换了一个新的场景之后,会重新犯的错误。


五、引入"错误层":让你的知识库记住失败

基于这个认识,我在我的笔记模板里加了一个区域,叫做**“我曾经错过的地方”**:

Markdown

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# [笔记标题]

## 核心洞察
[当前的观点]

## 我曾经错过的地方

### [日期] 的修正
- 修正前:[旧的观点]
- 修正原因:[什么事情让我意识到这是错的]
- 现在的理解:[新的观点和旧的观点的本质区别是什么]

### [日期] 的修正
...

## 还没解决的问题

这个区域不是用来记"这条笔记的修改历史"的,它是用来记**“我的认知在什么节点、因为什么原因发生了转变”**的。

区别很重要。

修改历史是"我把A改成了B"。 认知转变记录是"我原来以为A,是因为我当时只经历过X场景。后来碰到了Y场景,我才意识到A在Y场景下会失效,B才是更普遍的答案。"

前者是日志,后者是智慧。


现在,我的知识库维护工作流大致是这样的:

日常(每次使用笔记时,5分钟以内): 遇到相关问题时打开对应笔记,使用,然后在那个当下判断它是否需要更新。需要就更新,更新时填写"我曾经错过的地方"。

每周(周五下班前,15分钟): 打开Dataview仪表盘,看"最近访问但未修改"的笔记列表,逐条判断是否需要补充。

每月(月末,一小时): 打开Dataview仪表盘,看"高引用但长期未修改"的笔记列表,选5条做"时间机器对话",让AI帮我检查潜在的腐烂问题。

每季度(季末,两小时): 随机抽取20条笔记,做一次我自己的全面检查,不依赖AI,完全靠自己的判断——这是为了防止我的认知被AI的边界所框定。


这套流程运行了将近一年。

我可以告诉你一个真实的数字:

我的知识库里,现在有超过一半的笔记,有至少一条"我曾经错过的地方"的记录。

这不是让我感到骄傲的数字。

这是让我感到踏实的数字。

因为它意味着:这个库是活的,它在跟着我一起生长。


写在最后

回到老陈那个在两秒钟内指出问题根因的故事。

我一直在想,如果老陈当年把那次故障的处理过程,用我们这套方法记录下来——不只是记录"GC和定时任务会互相干扰"这个结论,还记录了"我当时第一眼看了什么,排除了什么,为什么最后想到了GC这个方向"这个过程——

那条笔记,会比任何一本教科书都更有价值。

因为那条笔记里装的,不只是知识,是一次真实的、在压力下发生的推理过程。

这才是最难被复制的东西。

但老陈没有记录。那个推理过程,永远只存在于他的脑子里。

等他哪天离职了,或者退休了,那个推理过程就消失了,就像它从来没有存在过一样。


我不知道我的Obsidian库,最终会不会变成我的"老陈"——一个积累了足够多的错误记忆和推理轨迹的系统,能够在某个关键时刻,给我指出一个我自己看不见的方向。

但我知道,如果我只记录结论,不记录错误,不记录推理过程,它永远不会有这个机会。

知识库不应该只是一个你在顺境时建造的纪念碑,它更应该是一个在你走弯路时诚实记录的航行日志。

那些弯路,比直路更值得被记住。


下一篇预告:

《最后的知识工作者:在AI时代,如何用Obsidian构建你的"认知护城河"?》

——现在的AI 能回答几乎所有问题了。那么我们这些花了几年时间建立知识库的人,究竟在做一件有意义的事,还是一件浪漫但徒劳的事?这是整个系列最难写的一篇,也是我认为最重要的一篇。