Skip to content

1. 什么是状态

让我们从最简单的例子开始理解状态的本质。

想象两种不同的计算方式:

有状态的计数器:就像一个记账本,每次调用都会在之前的基础上累加。第一次调用返回1,第二次返回2,第三次返回3……它"记住"了之前发生的一切,每次的输出都依赖于历史。

无状态的加法器:就像一个计算器的加法功能,给它输入2和3,无论何时、无论调用多少次,结果永远是5。它不知道也不关心之前发生了什么,每次都是全新的计算。

这个区别看似简单,却是理解整个系统设计的关键。用数学语言表达:

  • 无状态:Output = f(Input)
  • 有状态:Output = f(Input, History)

2. 生活中的状态

为了更好理解,看看生活中的例子:

银行账户是有状态的。你的余额是所有历史交易的累积结果。银行必须记住每一笔存取款,否则你的钱就消失了。

汇率转换是无状态的。100美元换人民币,只需要知道当前汇率,不需要知道你上次换了多少。

对话是有状态的。当朋友说"还记得昨天那件事吗?",需要共同的记忆才能继续。

翻译是无状态的。把"Hello"翻译成"你好",不需要知道之前翻译过什么。

这个区别看似简单,却深刻影响着系统设计的方方面面。

3. 分布式时代的必然选择

2000年,Roy Fielding在博士论文《Architectural Styles andthe Design of Network-based Software Architectures》 中提出REST架构,将无状态作为核心约束。他的理由很简单:在分布式系统中,状态是扩展性的敌人。

对比两种设计:

  • 有状态:服务器记住用户会话,但请求被分配到其他服务器时就失效了。需要在所有服务器间同步会话,复杂且昂贵。
  • 无状态:每个请求携带JWT令牌,包含所有必要信息。任何服务器都能处理,可随意增减服务器。

这就是为什么 REST 能支撑互联网规模的应用——以无状态为前提的设计降低了横向扩容的复杂度,成为互联网级系统的基础实践之一

4. 如何选择?一个简单的判断标准

我最喜欢用这个问题来判断:

"如果系统崩溃重启,用户能接受从零开始吗?"

  • 编译器崩溃了?重新编译就行 → 无状态
  • 游戏崩溃了?存档丢失不可接受 → 有状态
  • 搜索崩溃了?重新搜索就行 → 无状态
  • 购物车崩溃了?商品丢失很恼人 → 有状态

这个简单的问题能帮你快速定位系统的本质需求。

5. 混合策略:现实世界的智慧

无状态和有状态,看上去是布尔变量true/false般的两个完全对立的值。但这其实是中文语境里的一个误解——英文的 stateless/stateful 并非“无/有状态”的二元开关,更像 -less/-ful 的“程度词”:强调依赖的轻重与记录方式的取舍,而非是否“完全没有/完全存在”

6. 最常见的模式:无状态计算 + 有状态存储

这就像餐厅的运营模式:服务员(无状态)可以随时换班,任何服务员都能为任何桌子服务;但收银系统(有状态)必须准确记录每一笔账单。应用服务器是无状态的,可以随意扩展;数据库是有状态的,负责持久化。

现代云架构几乎都采用这种模式:

  • 无状态的API服务器 → 有状态的数据库
  • 无状态的Lambda函数 → 有状态的DynamoDB
  • 无状态的容器 → 有状态的Redis缓存

7. 不同场景,不同选择

这不是技术优劣的绝对判断,而是设计哲学的不同选择。每种方案都有其最适合的场景:

  • Cursor的向量索引适合创意编程场景——当你大概知道要什么但不确定具体名称时,语义搜索能帮你探索代码库。它特别适合学习新项目或寻找灵感。

  • JetBrains的传统索引是企业级开发的黄金标准——当你需要可靠的重构、精确的类型检查、复杂的代码导航时,经过20年打磨的索引系统无可替代。

  • Claude Code的grep方案则是Unix哲学的现代传承——当你重视简单、可控、可组合时,当你需要绝对的确定性和隐私保护时,这种"原始"的方案反而是最先进的选择。

8. 无状态之美:在AI时代的新意义

Claude Code的选择,让我们重新思考什么是"智能"。 在一个AI无处不在的时代,真正稀缺的不是智能,而是可预测性;不是功能的丰富,而是行为的确定;不是记住一切,而是知道何时遗忘

这就是为什么grep在2025年依然重要,为什么Unix哲学历经50年依然闪光,为什么Claude Code的"倒退"其实是一种清醒。

简单的工具活得最久,"健忘"的设计最自由。

9. Unix

“Unix革命:管道的哲学(1973)”。

Unix更侧重“正交设计”、“组合很实用(组合比集成实用)”