技术干货

为什么我用 Rust 重写了 Memoria

作者:MatrixOrigin发布于

为什么我用 Rust 重写了 Memoria

徐鹏 · MatrixOne 技术负责人


先说说我的背景

我是一个老程序员了,写了快二十年代码,过去将近十年一直在做数据库内核的开发。

2019 年 4 月,我遇到了一个以图搜图的需求。一开始的做法很朴素——用 Python 搭了一个应用,调 Faiss 做向量检索,能跑就行。但做着做着我意识到,向量相似度检索不是一个应用层的问题,它应该是一个数据库层面的基础设施。于是我从零开始设计和实现了 Milvus 的前几个版本。如果你去看 Milvus 仓库最早的 commits,整个内核的架构设计和核心实现基本都是我一个人完成的。Milvus 1.0 之前的内核全部是 C++ 实现的,而且不是普通的 C++——GPU 异构索引、多卡调度、混合过滤、动态索引的删除和更新,同时面对计算密集和 IO 密集的混合负载,这些问题放在当时,业界几乎没有现成的参考方案。后来 Milvus 成长为全球最知名的开源向量数据库之一,这是后话了。

之后我到了 MatrixOne,设计并实现了整个存储引擎。MatrixOne 整体是用 Golang 写的,我每天打交道的都是存储引擎、事务处理、查询优化。你可以说,我是一个活在编译器和类型系统里的人,习惯了所有问题在代码跑起来之前就被拦住。

说到 MatrixOne(https://github.com/matrixorigin/matrixone),可能很多人还不太了解。这是我们从 5 年前开始从零写的一个数据库内核项目,核心解决两个问题:一是用一套存储和计算引擎,同时支持 OLTP、OLAP、向量、全文的负载,不需要用户在不同数据系统之间搬数据。二是通过云原生和存算分离的架构,实现了 Git for Data 的能力——你可以对 TB 级别的数据进行跟 git 一样的快照、分支、Diff、Merge 操作。核心是我们在存储引擎层面实现了基于 Copy-on-Write 的数据版本管理:零拷贝分支、即时快照、任意时间点回滚,这对应用开发、数据开发和 AI 训练都非常有用。

今天聊的重点不是 MatrixOne,而是 Memoria——不过 Memoria 是完全基于 MatrixOne 构建的。

┌─────────────────────────────────────────────────────────┐
│                    MatrixOne 架构                         │
│                                                          │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐   │
│  │   OLTP   │ │   OLAP   │ │  Vector  │ │ FullText │   │
│  └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘   │
│       └─────────────┴────────────┴─────────────┘         │
│                         │                                │
│              ┌──────────▼──────────┐                     │
│              │  统一计算引擎        │                     │
│              └──────────┬──────────┘                     │
│                         │                                │
│              ┌──────────▼──────────┐                     │
│              │  CoW 存储引擎       │ ◄── Git for Data    │
│              │                     │                     │
│              │  • 零拷贝分支       │                     │
│              │  • 即时快照         │                     │
│              │  • 任意时间点回滚    │                     │
│              │  • Diff / Merge     │                     │
│              └──────────┬──────────┘                     │
│                         │                                │
│              ┌──────────▼──────────┐                     │
│              │  云原生 · 存算分离   │                     │
│              │   (S3 / 对象存储)    │                     │
│              └─────────────────────┘                     │
└─────────────────────────────────────────────────────────┘

被 AI 颠覆认知,然后开始做 Memoria

数据库内核的世界是确定性的、可控的。但从 2024 年下半年开始,AI coding 工具开始真正影响到我的日常工作。一开始只是用 Copilot 补补代码,后来发现 AI 能做的事情越来越多——不只是补全,而是能理解上下文、能重构、能写测试。作为一个系统程序员,我开始意识到一件事:AI 不只是在改变我们怎么写代码,它在改变什么样的项目值得去做。

这个认知的转变,直接把我推向了 AI 相关的项目。

MatrixOne 原生支持向量索引,我们一直在思考怎么让向量搜索的调优更智能——不是让用户手动调参数,而是让系统自己根据查询模式和数据分布去优化。这个想法需要一个"记忆层":系统要能记住过去的查询、记住哪些调优策略有效、记住用户的使用模式。

这就是 Memoria 的起点。它最初是为 MatrixOne 的向量搜索自动调优而设计的——一个能跨会话持久化、能语义检索、能版本管理的记忆系统。https://github.com/matrixorigin/Memoria

从数据库调优到 AI Agent 记忆:同一个问题

但与此同时,作为一个天天用 coding agent 的人,我发现了一件有意思的事:coding agent 对记忆的需求,和让 AI 给数据库做自动调优,本质上是同一个问题。 Agent 需要记住你的项目结构、你的编码偏好、上次调试到哪里了、哪些方案试过不行。这和数据库调优系统需要记住查询模式、记住哪些索引策略有效,在抽象层面完全一致——都是"跨会话的、可检索的、需要版本管理的持久化记忆"。

而我们手里恰好有 MatrixOne 的 Git for Data 能力。零拷贝分支意味着 agent 可以在不影响主记忆的情况下做实验性推理;即时快照意味着任何记忆变更都可以回滚;向量索引意味着语义检索是原生支持的。这些能力不需要从头造,MatrixOne 已经打磨好了。

        数据库自动调优                          Coding Agent
    ┌─────────────────┐                  ┌─────────────────┐
    │ 记住查询模式     │                  │ 记住项目结构     │
    │ 记住调优策略     │                  │ 记住编码偏好     │
    │ 记住数据分布     │                  │ 记住调试进度     │
    │ 回滚失败的尝试   │                  │ 回滚错误的方案   │
    └────────┬────────┘                  └────────┬────────┘
             │                                    │
             │      同一个抽象问题                  │
             └──────────┬─────────────────────────┘
                        │
                        ▼
          ┌──────────────────────────┐
          │    持久化记忆层            │
          │                          │
          │  • 跨会话持久化           │
          │  • 语义检索              │
          │  • 版本管理 (Git for Data)│
          └──────────┬───────────────┘
                     │
                     ▼
          ┌──────────────────────────┐
          │       MatrixOne          │
          │  CoW · 向量索引 · 分支    │
          └──────────────────────────┘

于是 Memoria 从一个数据库内部的调优工具,自然而然地演变成了一个通用的 AI Agent 记忆层。

如果你回头看,我的职业生涯里有一条反复出现的线索:从具体需求出发,发现通用问题,然后构建基础设施。 以图搜图 → Milvus,数据库调优 → Memoria,模式是一样的。而 Memoria 的核心——embedding、语义检索、混合索引——恰好是我做 Milvus 时积累了多年的领域知识在新场景下的延伸。

最初的版本是用 Python 写的。原因很简单:快。AI 生态里 Python 是默认语言,LangChain、sentence-transformers、各种 embedding 模型的 SDK 都是 Python first。作为一个原型,Python 让我们在几天内就跑通了从语义检索到 Git-style 分支的完整链路。

但随着 Memoria 从原型走向真正被我们内部要用起来的产品,Python 带来的问题开始一个接一个地冒出来。

Python 的问题:不是不能用,是越用越难受

动态类型语言有一个经典的痛点:bug 藏在运行时。

你写了一个函数,参数类型标注了 str,但 Python 不会在编译期检查这件事。某天一个 None 悄悄溜进来,程序在生产环境里炸了,堆栈指向一个你完全没预料到的地方。你加了 type hints,跑了 mypy,但 mypy 覆盖不了所有场景,尤其是涉及到动态反射和第三方库的时候。

这不是个别现象。我在开发 Memoria 的过程中反复碰到这类问题:

  • 一个 Optional[str] 没有被正确处理,导致 embedding 服务偶发性返回空向量
  • 异步代码里的异常被静默吞掉,因为 asyncio 的错误传播机制和你直觉想的不一样
  • 依赖管理是噩梦——不同用户的机器上,同一个 pip install 装出来的东西可能完全不同
  • 打包分发更是灾难,你要么让用户装 Python 环境,要么用 PyInstaller 打一个几百 MB 的包

这些问题单独看都不致命,但加在一起,它们构成了一种持续的摩擦力。每次我想加一个新功能,都要先花时间处理这些"基础设施层面"的麻烦。

我在做 MatrixOne 内核的时候有一个原则:能用编译型语言重写的,坚决不用 Python。 这个原则在 Memoria 上终于也到了兑现的时候。

为什么是 Rust,而不是 Go?

这是一个合理的问题。我写了好几年 Go,MatrixOne 整个内核都是 Go 写的,按理说 Go 应该是我的舒适区。

但我在语言选择上是有过教训的。做 Milvus 的时候,1.0 之前全部是 C++。C++ 给了我极致的性能和控制力,但代价是巨大的——内存安全问题防不胜防,开发效率低,新人上手困难。后来 Milvus 2.0 用 Go 重写,开发效率大幅提升,但在某些需要极致性能的场景下,GC 的存在始终是一个隐患。这两段经历让我对语言选择有了一个很实际的判断框架:不是哪个语言"最好",而是在具体场景下,哪个语言的 trade-off 最合理。

Memoria 的场景和数据库内核不太一样。Memoria 是一个需要被分发到用户本地机器上运行的服务。这意味着:

  • 包体积很重要。 用户不会为了一个 memory server 去装一个几百 MB 的运行时。Rust 编译出来的二进制文件是自包含的,通常只有几 MB。
  • 内存占用很重要。 Memoria 要常驻后台,和 IDE 一起跑。Go 的 GC 虽然已经很好了,但 Rust 的零成本抽象和无 GC 设计意味着内存占用可以低到几乎可以忽略。
  • 性能天花板很重要。 语义检索涉及向量计算,分支合并涉及大量数据比对。Rust 在这些场景下的性能优势是实打实的。

从 C++ 到 Go 再到 Rust,我走了一条完整的弧线。C++ 教会了我性能和控制力的价值,Go 教会了我开发效率和工程化的价值,而 Rust 是我目前找到的最佳平衡点——它有 C++ 级别的性能,有比 C++ 好得多的内存安全保证,同时在 AI 辅助下,开发效率已经不再是瓶颈。

  性能 ▲
       │
  极致 │  ★ C++                              ★ Rust (+ AI)
       │  Milvus 1.0                         Memoria
       │  · 极致性能 ✓                        · 极致性能 ✓
       │  · 内存安全 ✗                        · 内存安全 ✓
       │  · 开发效率 ✗                        · 开发效率 ✓ (AI辅助)
       │
       │                 ★ Go
       │                 MatrixOne
       │                 · 性能良好 ✓
       │                 · 内存安全 ✓ (GC)
       │                 · 开发效率 ✓
       │
       └──────────────────────────────────────────────► 安全性

更重要的是,2026 年的 Rust 和几年前的 Rust 已经不是同一个东西了——不是语言本身变了,而是学习它的方式变了。

AI 磨平了 Rust 的门槛

我要先声明一件事:我在开始重写之前,对 Rust 几乎一无所知。

我知道所有权、借用检查、生命周期这些概念,但从来没有真正用 Rust 写过一个完整的项目。如果是两年前,这可能意味着我需要花几个月时间去啃 The Rust Programming Language,和编译器搏斗,在 Stack Overflow 上搜索各种生命周期报错。

但现在不一样了。

今年 2 月份的时候,Anthropic 的研究员 Nicholas Carlini 发了一篇博客,讲他怎么用 16 个 Claude 实例并行工作,从零开始写了一个 Rust 实现的 C 编译器,能编译整个 Linux 6.9 内核,支持 x86、ARM 和 RISC-V 三个架构。10 万行 Rust 代码,花了大约 2000 个 Claude Code session,成本 2 万美元。

这件事对我的冲击很大。不是因为 AI 能写编译器——编译器本质上是一个规则明确的工程问题。真正让我震撼的是:AI 选择了 Rust 作为实现语言,而且写出来的代码质量足以编译 Linux 内核。 看完这篇博客,我就决定在 Memoria 上试一把。

这个案例说明了两件事:

  1. AI 对 Rust 的理解已经足够深,深到可以处理所有权、生命周期、trait 系统这些"Rust 最难的部分"
  2. Rust 的类型系统和编译器反而成了 AI 的优势——编译器会告诉 AI 哪里写错了,AI 可以根据编译错误自动修正

这和 Python 形成了鲜明对比。Python 的灵活性对人类来说是优势,但对 AI 来说反而是劣势——没有编译器兜底,AI 生成的 Python 代码更容易出现运行时才暴露的 bug。

差不多同一时间,Andrej Karpathy 在播客里说他从 2025 年 12 月开始就没有手写过一行代码了,从自己写 80% 的代码变成了 AI 写 80% 的代码。这个比例还在继续翻转。

我的体验和他类似。在用 AI 重写 Memoria 的过程中,我大概只需要做三件事:

  1. 定义架构——告诉 AI 我要什么样的模块划分、数据流、API 设计
  2. Review 代码——看 AI 生成的代码是否符合我的意图,是否有逻辑问题
  3. 处理编译错误——但大多数时候 AI 自己就能根据 cargo build 的输出修好

Rust 的编译器在这个工作流里扮演了一个关键角色:它是 AI 和人类之间的"质量检查员"。每一次编译,编译器都在告诉你(和 AI):"这里有问题,具体是什么问题,应该怎么改。" 这种反馈循环在动态语言里是不存在的。

  Rust + AI 的反馈循环                    Python + AI 的工作流
  ========================               ========================

  人类: 定义架构 / 需求                    人类: 定义架构 / 需求
         │                                       │
         ▼                                       ▼
  ┌─────────────┐                         ┌─────────────┐
  │  AI 生成代码 │                         │  AI 生成代码 │
  └──────┬──────┘                         └──────┬──────┘
         │                                       │
         ▼                                       ▼
  ┌─────────────┐    编译错误              ┌─────────────┐
  │ cargo build │ ──────────┐              │  直接运行    │
  └──────┬──────┘           │              └──────┬──────┘
         │ 编译通过          │                     │
         ▼                  │                     ▼
    ✅ 基本能跑       AI 自动修正           ❌ 运行时才爆炸
                     (精确的错误信息)        (堆栈不知所云)

行业正在往这个方向走

我不是唯一一个这么想的人。

GitHub 的 Octoverse 2025 报告显示了一个有趣的趋势:AI 编码工具正在创造一种"便利循环"(convenience loop),重塑开发者的语言选择。TypeScript 在 GitHub 上以 66% 的增长率超越了 Python 和 JavaScript,成为使用最多的语言。原因之一是:静态类型给 AI 生成的代码提供了安全网。

同样的逻辑适用于 Rust。Stack Overflow 2024 年度调查显示 Rust 以 83% 的比率蝉联"最受喜爱"语言。State of Rust Survey 显示近半数受访企业已经在生产环境中使用 Rust。微软宣布了到 2030 年用 AI 辅助将 C/C++ 代码迁移到 Rust 的计划。

Python 在 AI 基础设施层的份额正在被编译型语言蚕食。Python 在 AI 研究和原型开发中仍然是王者,但在需要部署、分发、长期维护的系统软件中,编译型语言正在收复失地。

这和我在向量数据库领域看到的趋势完全一致。Milvus 最初的 Python SDK 是生态入口,但内核从来都是编译型语言。Qdrant 从第一天就选了 Rust,LanceDB 也是 Rust。在 AI infra 这个赛道上,"用 Python 做原型,用编译型语言做产品"已经不是个人偏好,而是行业共识。

对于需要嵌入到用户 IDE 中常驻运行的服务来说,零运行时开销、内存安全、单二进制分发这些特性不是锦上添花,而是刚需。Rust 正在成为这类场景的默认选择。

重写的收获

用 Rust 重写 Memoria 之后,我们得到了一些"免费"的提升:

                    Python 版                 Rust 版
                ┌──────────────┐         ┌──────────────┐
  二进制体积     │   ~300 MB    │   →     │    <10 MB    │   ↓ 97%
                ├──────────────┤         ├──────────────┤
  常驻内存       │   200+ MB    │   →     │    ~20 MB    │   ↓ 90%
                ├──────────────┤         ├──────────────┤
  启动速度       │   数秒       │   →     │    毫秒级     │   ↓ 99%
                ├──────────────┤         ├──────────────┤
  分发依赖       │ Python + pip │   →     │   单个二进制   │   零依赖
                │ + venv + ... │         │              │
                ├──────────────┤         ├──────────────┤
  运行时错误     │  随时可能     │   →     │  编译即保证    │   ≈ 0
                └──────────────┘         └──────────────┘
  • 二进制体积:从 Python + PyInstaller 的几百 MB 降到了不到 10 MB 的单个可执行文件
  • 内存占用:常驻内存从 200MB+ 降到了 20MB 左右
  • 启动速度:从 Python 解释器的冷启动几秒,到 Rust 二进制的毫秒级启动
  • 分发体验:用户下载一个二进制文件就能用,不需要装 Python、不需要管 pip、不需要虚拟环境
  • 可靠性:编译通过基本就能跑,不会在运行时突然冒出一个 AttributeError: 'NoneType' object has no attribute 'xxx'

这些提升不是我通过精心优化得到的,而是换了一个语言就自然获得的。这就是我说的"免费提升"。

写在最后

我不是要说 Python 不好。Python 在 AI 研究、数据分析、快速原型开发中的地位短期内不会被动摇。但对于需要分发给用户、需要长期维护、需要在资源受限环境下运行的系统软件来说,Python 的短板正在变得越来越明显。

而 Rust 曾经最大的门槛——陡峭的学习曲线——正在被 AI 快速磨平。当 AI 可以帮你处理所有权和生命周期的细节,当编译器可以作为 AI 的实时反馈机制,Rust 的"难"就不再是一个有效的反对理由了。

作为一个写了多年 Go 的数据库内核程序员,我从来没想过自己会用 Rust 重写一个项目。但 AI 改变了这个等式。它让我可以把精力放在架构设计和产品思考上,而不是和语言的语法细节搏斗。

从 2019 年用 C++ 手撸 Milvus,到用 Go 构建 MatrixOne,再到今天用 Rust 重写 Memoria——每一次语言选择都是在当时的约束条件下做出的最优解。而 AI 的出现,让 Rust 从"想用但用不起"变成了"没有理由不用"。

系统瞬间有了内存安全、性能和分发体积的免费提升,而代价几乎为零。

这就是我用 Rust 重写 Memoria 的原因。


Memoria 是一个为 AI Agent 提供持久化记忆的开源项目,支持 Kiro、Cursor、Claude Code 等主流 AI 编码工具。底层存储基于 MatrixOne 云原生超融合数据库。