<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>FoundationDB on Hellokitty&#39;s Blog</title>
    <link>https://yangyang233333.github.io/tags/foundationdb/</link>
    <description>Recent content in FoundationDB on Hellokitty&#39;s Blog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Fri, 14 Aug 2026 19:10:00 +0800</lastBuildDate>
    <atom:link href="https://yangyang233333.github.io/tags/foundationdb/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>3FS 如何使用 FoundationDB：元数据模型、事务与并发控制</title>
      <link>https://yangyang233333.github.io/posts/3fs-foundationdb-metadata-design/</link>
      <pubDate>Fri, 14 Aug 2026 19:10:00 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/3fs-foundationdb-metadata-design/</guid>
      <description>&lt;p&gt;3FS 是面向 AI 训练和推理负载设计的分布式文件系统。它没有把 FoundationDB 当成普通的持久化 KV 使用，而是围绕 FoundationDB 的有序键空间、乐观事务、冲突检测和 Versionstamp，构建了一套强一致的文件系统元数据服务。&lt;/p&gt;
&lt;p&gt;本文从源码出发，梳理 3FS 如何接入 FoundationDB，如何编码 inode 和目录项，以及 create、rename、remove、list 等文件系统操作怎样映射为 FoundationDB 事务。&lt;/p&gt;
&lt;p&gt;本文分析的源码位于 3FS 仓库中的以下目录：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;src/fdb/             FoundationDB C API 封装
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;src/common/kv/       通用 KV 和事务接口
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;src/meta/store/      inode、目录项和元数据操作
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;src/meta/components/ ID 分配、服务分布和 GC 等组件
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;src/meta/service/    Meta Service RPC 入口
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;一3fs-中-foundationdb-的定位&#34;&gt;一、3FS 中 FoundationDB 的定位&lt;/h2&gt;
&lt;p&gt;3FS 将数据面和元数据面分开：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文件的 chunk 数据由 Storage Service 保存。&lt;/li&gt;
&lt;li&gt;文件系统元数据由 Meta Service 管理，并持久化到 FoundationDB。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;FoundationDB 中保存的主要内容包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;inode；&lt;/li&gt;
&lt;li&gt;directory entry，也就是目录项；&lt;/li&gt;
&lt;li&gt;文件打开会话；&lt;/li&gt;
&lt;li&gt;RPC 幂等记录；&lt;/li&gt;
&lt;li&gt;Meta Server 分布信息；&lt;/li&gt;
&lt;li&gt;用户、配置和其他全局状态。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;整体调用链可以简化为：&lt;/p&gt;</description>
    </item>
    <item>
      <title>FoundationDB 事务如何实现？从源码看 GRV、Resolver、TLog 与 Storage Server</title>
      <link>https://yangyang233333.github.io/posts/foundationdb-transaction-implementation/</link>
      <pubDate>Fri, 14 Aug 2026 17:00:00 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/foundationdb-transaction-implementation/</guid>
      <description>&lt;p&gt;FoundationDB 支持跨任意 key range 的 ACID 事务，并向应用提供严格可串行化语义。但它既没有让每个 Storage Server 参与经典的两阶段提交，也不是传统单机数据库中“共享缓冲池 + Undo/Redo”的事务实现。&lt;/p&gt;
&lt;p&gt;它的核心方案可以概括为：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;全局版本号 + MVCC 快照读 + 客户端暂存修改 + Resolver 乐观冲突检测 + 多副本 TLog 持久化。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;本文结合 FoundationDB 官方源码，沿着一笔事务的完整路径，解释它如何从读取、提交、冲突检测，一直走到日志持久化和 Storage Server 应用。&lt;/p&gt;
&lt;p&gt;本文分析的源码版本为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;commit: eab21ffe07c20575d5bac9ab0745375b8f7f8357
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;date:   2026-08-12
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;源码中的具体行号会随版本变化，阅读时应以函数和类型名为主要定位依据。&lt;/p&gt;
&lt;h2 id=&#34;一整体架构&#34;&gt;一、整体架构&lt;/h2&gt;
&lt;p&gt;FoundationDB 的事务涉及以下核心角色：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;角色&lt;/th&gt;
					&lt;th&gt;主要职责&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Client&lt;/td&gt;
					&lt;td&gt;保存事务 mutations、读冲突范围和写冲突范围&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;GRV Proxy&lt;/td&gt;
					&lt;td&gt;分配 Read Version&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Commit Proxy&lt;/td&gt;
					&lt;td&gt;批量接收事务、分配 Commit Version、组织提交流水线&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Resolver&lt;/td&gt;
					&lt;td&gt;检测乐观事务冲突&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;TLog&lt;/td&gt;
					&lt;td&gt;复制并持久化已提交 mutations&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Storage Server&lt;/td&gt;
					&lt;td&gt;提供版本化读取，异步应用 TLog mutations&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Sequencer&lt;/td&gt;
					&lt;td&gt;为事务系统提供版本推进基础&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;完整流程可以简化为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Client
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ├── 获取 Read Version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ├── 从 Storage Server 读取该版本
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ├── 在客户端积累 mutations 和 conflict ranges
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  └── 提交
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Commit Proxy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├── 组成 Commit Batch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├── 分配 Commit Version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── 按 key range 发给 Resolver
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     Resolver
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├── 检查 read conflict ranges
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├── 登记 write conflict ranges
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── 返回 committed / conflict / too old
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Commit Proxy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├── 丢弃冲突事务
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├── 为 mutation 添加 Storage Server tag
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── 将成功事务写入 TLog
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       TLog
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├── 按冗余策略复制和持久化
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── 返回 durable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Commit Proxy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── 向 Client 返回 Commit Version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Storage Server
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├── 异步读取自己的 tagged mutations
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ├── 应用到内存中的版本化数据
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── 后台持久化到 Storage Engine
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最关键的解耦是：&lt;/p&gt;</description>
    </item>
    <item>
      <title>FoundationDB 中有 Undo 和 Redo 吗？从 TLog、MVCC 到故障恢复</title>
      <link>https://yangyang233333.github.io/posts/foundationdb-undo-redo/</link>
      <pubDate>Fri, 14 Aug 2026 10:00:00 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/foundationdb-undo-redo/</guid>
      <description>&lt;p&gt;传统数据库通过 Undo Log 和 Redo Log 保证事务的原子性与持久性：Undo 撤销未提交的修改，Redo 恢复已经提交但尚未写入数据文件的修改。那么，在采用分布式事务架构的 FoundationDB 中，是否也存在这两类日志？&lt;/p&gt;
&lt;p&gt;简短回答是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;FoundationDB 有承担类似 Redo 职责的 TLog，但通常没有传统意义上的 Undo Log。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这并不意味着 FoundationDB 不支持事务回滚或 MVCC，而是因为它对未提交数据、提交日志和历史版本的组织方式与传统数据库不同。&lt;/p&gt;
&lt;h2 id=&#34;一先回顾传统数据库为什么需要-undo-和-redo&#34;&gt;一、先回顾传统数据库为什么需要 Undo 和 Redo&lt;/h2&gt;
&lt;p&gt;传统数据库通常允许事务直接修改缓冲池中的共享数据页。数据页何时写入磁盘，与事务何时提交并不完全同步。&lt;/p&gt;
&lt;p&gt;因此会出现两种状态。&lt;/p&gt;
&lt;h3 id=&#34;1-事务未提交数据页却已经落盘&#34;&gt;1. 事务未提交，数据页却已经落盘&lt;/h3&gt;
&lt;p&gt;例如事务把账户余额从 &lt;code&gt;100&lt;/code&gt; 改成 &lt;code&gt;80&lt;/code&gt;，但随后事务失败：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;BEGIN&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;UPDATE&lt;/span&gt; account
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; balance &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;A&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ROLLBACK&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果包含 &lt;code&gt;80&lt;/code&gt; 的脏页已经写入磁盘，数据库就必须知道原值是 &lt;code&gt;100&lt;/code&gt;，才能撤销这次修改。这是 Undo Log 的主要职责。&lt;/p&gt;
&lt;h3 id=&#34;2-事务已经提交数据页却尚未落盘&#34;&gt;2. 事务已经提交，数据页却尚未落盘&lt;/h3&gt;
&lt;p&gt;另一个事务已经执行 &lt;code&gt;COMMIT&lt;/code&gt;，但修改可能仍然只存在于内存中的脏页里。如果服务器此时断电，已提交的数据就会丢失。&lt;/p&gt;
&lt;p&gt;因此数据库先持久化 Redo Log，再返回提交成功。重启后，即使数据页没有及时落盘，也可以通过 Redo 重新应用修改。&lt;/p&gt;
&lt;p&gt;可以把二者概括为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Undo：事务不应该生效，但修改可能已经进入数据文件。
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Redo：事务应该生效，但修改可能还没有进入数据文件。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;二foundationdb-的事务提交流程&#34;&gt;二、FoundationDB 的事务提交流程&lt;/h2&gt;
&lt;p&gt;FoundationDB 并不是把客户端事务中的每次 &lt;code&gt;set&lt;/code&gt; 或 &lt;code&gt;clear&lt;/code&gt; 立即写入 Storage Server。事务提交前，这些操作首先保存在客户端的事务对象中。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
