# S3写缓存

{% hint style="warning" %}
此功能为实验性功能。
{% endhint %}

## 背景

随着云原生架构的普及，Amazon S3 及其兼容协议已成为数据持久化的事实标准。 然而，标准的对象存储服务通常针对“冷数据归档”或“通用访问”进行了优化，在高吞吐计算场景下，读写性能往往难以兼得。

为了解决上述问题，我们研发了全新的 S3 兼容读写缓存（后面简称 S3 Write Cache）。 它部署在计算集群侧，利用高性能 NVMe/SSD 介质，提供了一个极低延迟、高吞吐的 S3 协议数据层，并具备智能的数据生命周期管理能力。

## 核心价值和适用场景

* **极致的写入性能 ：** 通过接管客户端的 PUT 请求，数据直接落入Alluxio Worker的本地NVMe/SSD存储，无需等待上传至远端 S3。这消除了网络和远端存储限速等影响，能够吸纳极高的突发写入流量，实现毫秒级的写入确认。
* **极速的写后读取：** 凡是保留在缓存中的热数据，客户端发起的 GET 请求将直接从Worker响应，吞吐量可达网络带宽上限，完全规避了从远端对象存储回读的高延迟。
* **可靠的异步持久化：** 写入缓存的数据不仅仅停留在本地。系统会在后台自动将数据异步持久化到标准的底层存储（UFS），如 Amazon S3 或 HDFS。这既保证了写入路径的低延迟，又确保了数据的最终可靠性和安全性，防止单点故障导致数据丢失。
* **自动化的空间管理 ：** 为了确保持续的高性能写入，系统实现了智能的驱逐机制。一旦数据被安全持久化到底层存储中，缓存会自动识别并清理这些“冷数据”，为新的“热数据”腾出宝贵的 NVMe/SSD 空间，无需人工运维介入。
* **透明的统一访问体验：** 无论数据当前存储在Worker，还是已被驱逐到底层存储，客户端均通过统一的 S3 端点进行访问。如果客户端请求的数据已被驱逐，Alluxio 会智能地从 UFS 拉取数据并按需重新缓存。这一过程对应用层完全透明，用户无需修改代码即可享受分层存储带来的成本与性能优势。

本组件特别适用于 **“写多读多”且对数据写入延迟**敏感的场景：

* **AI/LLM 训练 Checkpoint 与 Resume：** 快速写入数百 GB 模型参数，并能在训练失败时从缓存极速恢复。
* **大数据 ETL 管道：** 承接中间阶段产生的海量 Shuffle 数据，供下一阶段任务零等待读取。
* **混合云/存算分离架构：** 在本地计算集群与远端对象存储之间构建高性能缓冲层，掩盖网络延迟。

## 部署与使用

### 部署

S3 Write Cache 已集成进 Alluxio Operator。在部署 AlluxioCluster 时，只需增加相关属性配置 `alluxio.write.cache.enabled=true` 并启用 FDB 即可。

```yaml
apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
spec:
  properties:
    # enable s3 write cache
    alluxio.write.cache.enabled: "true"
    # enable automatic FDB deployment 
    fdb:
      enabled: true
    tieredstore:
      levels:
        - level: 0
          alias: SSD
          mediumtype: SSD
          path: /data1/cacheonly/worker
          type: hostPath
          quota: 10Gi
```

部署完成后，我们即可通过 S3 协议访问 Alluxio，参考：[S3 API](https://documentation.alluxio.io/ee-ai-cn/data-access/s3-api). **注意：** S3 Write Cache 的默认行为是 `WRITE_THROUGH`（同步穿透写）。 如需配置为 `WRITE_BACK`（异步回写）以获得更高性能，请参考下文的路径配置。

### 路径配置

#### 写入策略

开启S3 Write Cache 以后， Alluxio支持不同的路径使用不同的缓存写入策略，来区分不同的需求场景，参考下表：

| 策略             | 描述                                                              |
| -------------- | --------------------------------------------------------------- |
| WRITE\_THROUGH | (默认) 同步写。数据写入缓存的同时同步写入 UFS，两者都成功才返回成功。适合数据安全优先的场景，但写入延迟受限于 UFS。 |
| TRANSIENT      | 临时存储。数据仅在缓存内读写，不与 UFS 交互。适用于性能优先且无需持久化的临时数据。                    |
| WRITE\_BACK    | 异步回写。数据写入缓存即返回成功，后台异步上传至 UFS。适用于性能优先，且数据需要持久化的场景， 提供低延迟，和最终一致性。 |
| READ\_ONLY     | 不允许写入任何数据。                                                      |
| NO\_CACHE      | 直接向 UFS 进行读写，不经过 Alluxio 缓存。                                    |

如何选择写策略：

1. **写入必须立刻可恢复/可追溯：** 优先 `WRITE_THROUGH`
2. **追求低延迟且需要最终落盘：** 用 `WRITE_BACK`
3. **纯临时数据（可丢 / 可重算）：** 用 `TRANSIENT`

#### 多副本写入

在 `TRANSIENT` 和 `WRITE_BACK` 策略下，Alluxio 支持配置多副本写入。 通过在缓存层增加数据副本数，可以显著提升数据在落盘（持久化到 UFS）之前的可用性与容错能力。

在实际业务中，建议从数据可靠性与系统性能两个维度权衡副本数的设置：

**数据可靠性（Reliability）**

* **WRITE\_BACK 模式：** 增加 writeReplicas 可以缩短“风险窗口期”。在数据完成异步持久化之前，多副本机制能有效规避因单个 Worker 节点宕机导致的数据丢失风险。
* **TRANSIENT 模式：** 由于该模式下数据不进行 UFS 持久化，增加写入副本数是确保数据不丢失的唯一手段。它能防止因缓存节点故障导致的临时数据永久性丢失，提高中间计算结果的稳健性。

**性能权衡（Performance Trade-off）**

* **写入开销：** 增加副本数会带来额外的集群内部网络带宽消耗，并占用更多的 NVMe/SSD 存储空间。同时，由于需要同步写入多个副本，写入延迟（Latency）会随副本数增加而略微上升。
* **读取收益：** 更多的副本意味着更强的并发读取能力。对于“一写多读”的热点数据，多副本分布在不同 Worker 上可以实现负载均衡，显著提升读吞吐量，消除单点访问瓶颈。

#### 路径配置管理命令

使用以下命令在线编辑路径配置（类似 `kubectl edit`）：

```bash
alluxio pathconfig edit
```

编辑器打开后，可输入如下 JSON 配置。例如：

1. 将全局默认设为 `WRITE_THROUGH`；
2. 对路径 /foo/bar/write\_back 及其子目录启用 WRITE\_BACK 模式，设置 writeReplicas 为 1（单副本写入）；
3. 对路径 /foo/bar/transient 及其子目录启用 TRANSIENT 模式，并将 writeReplicas 设为 2，通过双副本冗余确保临时数据在单个 Worker 故障时仍能访问。

```json
{
  "apiVersion": "v1.0",
  "defaultRule": {
    "description": "Hardcoded global default rule.",
    "policyMode": "WRITE_THROUGH",
    "properties": {
      "writeReplicas": 1
    }
  },
  "pathRules": [
    {
      "alluxioPath": "/foo/bar/write_back/**",
      "description": "Path for write back",
      "policyMode": "WRITE_BACK",
      "properties": {
        "writeReplicas": 1
      }
    },
    {
      "alluxioPath": "/foo/bar/transient/**",
      "description": "Path for transient",
      "policyMode": "TRANSIENT",
      "properties": {
        "writeReplicas": 2
      }
    }
  ]
}
```

#### 验证配置

编辑生效后，使用以下命令测试特定路径命中的策略：

```bash
alluxio pathconfig test --path /foo/bar/write_back/a.txt
```

输出如下：

```
Get result for path: /foo/bar/write_back/a.txt
get(/foo/bar/write_back/a.txt) => RULE glob='/foo/bar/write_back/**'
  - specificity: literalPrefixLen=20, domain='/foo/bar/write_back/', kind=SUBTREE, depth=4, order=0
{
  "alluxioPath" : "/foo/bar/write_back/**",
  "description" : "NOT_SPECIFIED",
  "policyMode" : "WRITE_BACK",
  "properties" : {
    "writeReplicas" : 1
  }
}
  - anchorDir='/foo/bar/write_back/'
  - description=NOT_SPECIFIED
candidates:
  * [WIN] glob='/foo/bar/write_back/**' (lp=20, domain='/foo/bar/write_back/', kind=SUBTREE, depth=4, order=0)

List result for path (if the path is a directory): foo/bar/write_back/a.txt
list(/foo/bar/write_back/a.txt/) => BOTH
[reason] nearest ancestor anchor-domain
nearest-ancestor anchors:
  - anchorDir='/foo/bar/write_back/', glob='/foo/bar/write_back/**', policy=WRITE_BACK -> BOTH
in-domain child-possible contributors:
  - glob='/foo/bar/write_back/**', policy=WRITE_BACK -> BOTH
```

#### 路径配置管理 Rest API

此外，Alluxio 也提供了 Rest API 用于管理路径配置，Rest API 更适合与应用进行代码层面的集成。 以下是一个使用 Rest API 设置路径配置的样例：

```bash
curl -X PUT \
  -H "Content-Type: application/json" \
  -d @<(cat <<EOF
{
  "key": "PathConfigEntityV2",
  "conf": {
    "apiVersion": "v1.0",
    "defaultRule": {
      "description": "Hardcoded global default rule.",
      "policyMode": "WRITE_THROUGH",
      "properties": {
        "writeReplicas": 1
      }
    },
    "pathRules": [
      {
        "alluxioPath": "/foo/bar/write_back/**",
        "description": "Path for write back",
        "policyMode": "WRITE_BACK"
      },
      {
        "alluxioPath": "/foo/bar/transient/**",
        "description": "Path for transient",
        "policyMode": "TRANSIENT"
      }
    ]
  }
}
EOF
) \
  http://<coordinator-host>:<coordinator-port>/api/v1/conf
```

## 限制与依赖

本节列出了 S3 Write Cache 在一致性与可靠性方面的关键设计约束。 这些限制主要是为了确保 `WRITE_BACK` 模式下的数据可靠性。

### 独立的资源开销

S3 Write Cache 作为一个高性能组件，需要独占一定的计算资源（CPU/Memory）和高性能存储介质（NVMe SSD）。

**对于现有 Alluxio 用户：** 部署本组件不会增加额外的运维复杂度（可复用现有的 Operator 和管理体系），但需要评估现有磁盘和网络是否能够满足 S3 Write Cache 的性能需求。

**对于新用户：** 意味着在应用与底层存储之间增加了一层独立的存储服务，需要进行相应的容量规划。

### 元数据存储依赖

为了实现元数据的高吞吐处理与强一致性，本组件强制依赖 FoundationDB (FDB) 作为元数据存储引擎。

部署之前，必须确保环境中已有可用的 FDB 集群，或随 Alluxio 一同部署 FDB(Alluxio 已经集成 FDB 的部署)。

FDB 的稳定性和性能将作为关键路径影响缓存层的元数据操作效率。

### 驱逐策略与持久化依赖

本组件的数据生命周期管理策略发生了重大变更，驱逐行为与数据的持久化状态强绑定：

* **未持久化即锁定** 为了确保数据零丢失，在数据成功异步上传至 UFS 之前，绝对不会被驱逐策略选中。
* **持久化后遵循 LRU** 仅当数据确认已安全存储在底层 UFS 后，才会进入淘汰候选列表，并遵循 LRU (Least Recently Used) 策略在空间不足时自动清理。
* **无持久化则无淘汰** 如果未配置异步持久化功能，写入缓存的所有数据将被视为永久驻留，永远不会被自动淘汰。并且 Alluxio 提供的管理命令 `alluxio job free` 也不能释放这些数据，此时只能通过手动调用删除接口来释放空间。

## 运维与调优

### 配置总览

S3 Write Cache 的默认配置即可满足大部分场景的需求，如果有其他需求，我们可以参考下表调整配置：

| 配置项                                                | 默认值    | 描述                                                            |
| -------------------------------------------------- | ------ | ------------------------------------------------------------- |
| alluxio.write.cache.enabled                        | false  | 是否启用 S3 Write Cache 特性                                        |
| alluxio.foundationdb.cluster.file.path             | -      | FDB 连接配置文件路径。若使用 Operator 部署 FDB 则自动注入；若使用外部 FDB 集群需手动指定。     |
| alluxio.write.cache.async.check.orphan.timeout     | 1 hour | 孤儿文件超时时间。若文件写入开始后超过此时间仍未提交（Committed），将被视为异常中断的垃圾数据并清理。       |
| alluxio.write.cache.async.file.check.period        | 10 min | 清理扫描周期。检查孤儿文件的频率，设置过短会增加 FDB 负载。                              |
| alluxio.write.cache.async.persist.thread.pool.size | 16     | 异步持久化并发度。仅对 WRITE\_BACK 策略生效，决定了单个 Worker 节点同时向 UFS 上传文件的线程数。 |

### 异步持久化重试策略

对于配置了 `WRITE_BACK` 的路径，为了确保数据持久性，Alluxio 在上传 UFS 失败时会执行**指数退避**重试机制。 重试间隔随失败次数指数增长（例如：1s -> 2s -> 4s...），直至达到最大间隔上限。 这种机制可以防止在 UFS 故障或拥塞时，高频重试导致“雪崩效应”，加重后端负担。 请注意：重试发生在后台异步持久化线程中，不阻塞 `WRITE_BACK` 路径的前端写入返回。

相关配置项：

| 配置项                                                             | 默认值 | 描述     |
| --------------------------------------------------------------- | --- | ------ |
| alluxio.worker.write.cache.async.persist.retry.initial.interval | 1s  | 初始重试间隔 |
| alluxio.worker.write.cache.async.persist.retry.max.interval     | 1h  | 最大重试间隔 |

### 缓存空间耗尽风险

由于未持久化的数据受保护机制限制，无法被自动驱逐。若未启用异步持久化，或持久化带宽显著滞后于写入流量， 缓存内的“脏数据”将持续累积并占用存储空间。一旦触及物理存储容量上限，Alluxio将抛出 **“空间不足”** 错误， 导致后续写入请求被拒绝。**建议：** 开启并优化异步持久化功能，或配置足够的缓存空间并制定严格的手动清理策略以释放空间。

### 读写缓存空间划分

在 S3 Write Cache 启用后，由于 **未持久化数据不可驱逐** 的特性，物理缓存空间在逻辑上被划分为两部分：

* **写缓存**：包含正在写入或等待持久化的数据（Dirty Data）。这部分空间不可被驱逐。
* **读缓存**：包含已从 UFS 加载或已完成持久化的数据。这部分空间遵循 LRU 策略，可被自动驱逐。

这两部分共享同一个Worker管理的物理存储。默认情况下，写缓存允许占用 30% 的磁盘空间。 可以通过以下配置限制写缓存（Pinned Files）的最大比例：

| 配置项                                                        | 默认值 | 描述                                                         |
| ---------------------------------------------------------- | --- | ---------------------------------------------------------- |
| alluxio.worker.page.store.pinned.file.capacity.limit.ratio | 0.3 | 写缓存（不可驱逐数据）允许占用的最大空间比例（0.0 - 1.0）。例如设置为 0.3 表示预留 70% 给读缓存。 |

## 性能参考

本节提供 S3 Write Cache（`WRITE_BACK`）在典型负载下的**性能参考区间**，用于帮助用户建立性能预期与容量规划直觉。\
具体性能结果会受到硬件规格、网络条件、并发度及对象大小等因素影响，以下数据仅供参考。

### 测试环境概览

* Client：AWS `c5n.metal`（100 Gbps 网络）
* Worker：AWS `i3en.metal`（本地 NVMe SSD）
* 工具：Warp / COSBench
* 对象规模：10 KB / 1 MB / 10 MB
* 并发度：1 → 256

### 小对象写入延迟（10 KB PUT）

在小对象、高频写入场景下，S3 Write Cache 能显著降低写入延迟：

* **WRITE\_BACK 写入延迟：**
  * 低并发：**3–5 ms**
  * 中并发：**4–9 ms**
* **Direct S3 写入延迟：**
  * 通常在 **30–60 ms** 区间

**结论：**\
在低至中等并发下，小对象写入延迟可降低 **一个数量级**，显著改善对写入延迟敏感的业务体验。

### 大对象写入吞吐（10 MB PUT）

在大对象连续写入场景下，S3 Write Cache 能快速利用本地 NVMe 带宽：

* **单 Worker 写入吞吐：**
  * 稳定在 **3–6 GB/s**
* **性能特征：**
  * 写入延迟保持在 **几十毫秒以内**
  * 吞吐能力随 Worker 数量**近线性扩展**

**对比说明：**\
Direct S3 在高吞吐场景下通常受限于 Bucket 分区与服务端限速，整体吞吐和尾延迟更难预测。

### 写后读性能（Read-after-write）

在“写入后立即读取”的典型流水线场景中（如 AI 训练、ETL 阶段衔接）：

* **GET 延迟：**
  * S3 Write Cache：**3–7 ms**
  * Direct S3：**90–130 ms**
* **GET 吞吐：**
  * 提升约 **4–8×**

**结论：**\
S3 Write Cache 实现了真正的“写入即热点”，避免了远端对象存储的读放大与往返延迟。

### 异步持久化性能特征（WRITE\_BACK）

在 `WRITE_BACK` 模式下，前端写入与后台持久化完全解耦：

* **前端写入额外开销：** 约 **0 ms**
* **后台异步持久化能力：**
  * 单 Worker 可达 **\~2000 objects/s**
* **系统行为：**
  * 前端写入性能不受 UFS 波动直接影响
  * 回写能力可通过并发与带宽独立调优

## 小结

* S3 Write Cache 更关注 **低写入延迟 + 可预测吞吐**
* 性能主要受限于 **本地磁盘与网络能力**
* 在多 Worker 部署下，可通过横向扩展获得稳定的带宽提升
* 非目标：取代远端对象存储的最终吞吐上限，而是**屏蔽其延迟与抖动**
