# 写入文件

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

在某些情况下，UFS 的性能和带宽可能不能满足大量数据写入的需求。为了解决这个问题，Alluxio 提供了 CACHE\_ONLY 的写入方式： Alluxio 支持将数据只写入到 Alluxio 集群，由于整个过程不与 UFS 交互，写入性能和带宽完全取决于 Alluxio 集群本身的性能和带宽。这个功能被称为 **CACHE\_ONLY。**

推荐的使用场景如下：

* AI 训练过程中临时保存 checkpoint 文件；
* 大数据计算中产生的 shuffle 文件。

在这些场景中，文件仅仅只是临时写入，并不需要长期存储。

> 此外，对于需要最终将 CACHE\_ONLY 文件持久化的场景，Alluxio 支持异步持久化功能选项，可按照[启用异步持久化](#qi-yong-yi-bu-chi-jiu-hua)部分中的说明进行配置。

## 启用 CACHE\_ONLY

要使用 CACHE\_ONLY 功能，应单独部署 CACHE\_ONLY 存储组件。需注意的是，Alluxio 客户端会直接与 CACHE\_ONLY 存储进行交互，而不会与 Alluxio Worker 通信。CACHE\_ONLY 存储中的数据和元数据由其自身独立管理。由于文件是独立管理的，CACHE\_ONLY 中的文件无法与由 Alluxio Worker 提供服务的其他文件进行交互。

<figure><img src="https://3373003307-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwnevsZwPNckCUenYadxu%2Fuploads%2Fgit-blob-cb5ea96bc65d16b6a1e38497b94fe5769bf2769e%2Fcache_only.png?alt=media" alt=""><figcaption></figcaption></figure>

### 在 Kubernetes 上部署 CACHE\_ONLY Storage

CACHE\_ONLY 存储的部署已集成到 Alluxio Operator 中。只需在 Alluxio 部署文件中配置 `cacheOnly` 字段即可启用该功能。

```yaml
apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
metadata:
  name: alluxio
spec:
  image: <PRIVATE_REGISTRY>/alluxio-enterprise
  imageTag: <TAG>
  properties:

  worker:
    count: 2

  pagestore:
    size: 100Gi

  cacheOnly:
    enabled: true
    mountPath: "/cache-only"
    image: <PRIVATE_REGISTRY>/alluxio-cacheonly
    imageTag: <TAG>
    imagePullPolicy: IfNotPresent

    # Replace with base64 encoded license generated by
    # cat /path/to/license.json | base64 |  tr -d "\n"
    license:

    properties:

    journal:
      storageClass: "gp2"

    worker:
      count: 2
    tieredstore:
      levels:
        - level: 0
          alias: SSD
          mediumtype: SSD
          path: /data1/cacheonly/worker
          type: hostPath
          quota: 10Gi
```

**注意：**&#x43;ACHE\_ONLY Worker 需要本地磁盘存储 CACHE\_ONLY 类型的数据，这部分的磁盘空间与 Alluxio Worker 的缓存完全独立，所以需要提前预估 CACHE\_ONLY 的使用容量，预留磁盘空间。

### 配置资源使用量

类似 coordinator 和 worker，我们可以使用类似的字段来配置 CACHE\_ONLY Master 和 Worker 使用的资源 `cacheOnly.master.resources` 和 `cacheOnly.worker.resources`。

```yaml
apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
metadata:
  name: alluxio
spec:
  cacheOnly:
    enabled: true
    master:
      count: 1
      resources:
        limits:
          cpu: "8"
          memory: "40Gi"
        requests:
          cpu: "8"
          memory: "40Gi"
      jvmOptions:
        - "-Xmx24g"
        - "-Xms24g"
        - "-XX:MaxDirectMemorySize=8g"
    worker:
      count: 2
      resources:
        limits:
          cpu: "8"
          memory: "20Gi"
        requests:
          cpu: "8"
          memory: "20Gi"
      jvmOptions:
        - "-Xmx8g"
        - "-Xms8g"
        - "-XX:MaxDirectMemorySize=8g"
```

推荐的内存计算方式为：

```
(${Xmx} + ${MaxDirectMemorySize}) * 1.1 <= ${requests} = ${limit}
```

### 访问 CACHE\_ONLY

在 CACHE\_ONLY Storage 部署完成后，所有访问 `/cache_only` 挂载点的请求都是 CACHE\_ONLY 类型的请求，我们可以以多种形式来访问 CACHE\_ONLY 的数据。

使用 Alluxio Cli 访问：

```shell
bin/alluxio fs ls /cache_only
```

使用 Alluxio FUSE 接口访问：

```shell
cd ${fuse_mount_path}/cache_only
echo '123' > test.txt
cat test.txt
```

## 启用异步持久化

对于需要将 Alluxio 中的临时数据最终持久化的场景，Alluxio 提供了异步持久化机制。该机制允许写入 CACHE\_ONLY 挂载点的数据，异步上传到配置好的对应 UFS 路径中。

此功能特别适用于无需立即持久化但需要实现最终一致性的环境。

### 局限性

1. **元数据操作受限**：仅支持基本的文件持久化，重命名等操作无法可靠处理
2. **UFS清理缺失**：从 Alluxio 删除文件不会自动清除UFS中的对应数据。
3. **恢复机制较弱**：如果某个文件在 UFS 和 Alluxio 中的版本出现差异，Alluxio 当前无法对其进行一致性修复。
4. **文件修改会重新触发持久化**：在 Alluxio 中修改文件会调度新的异步持久化任务，可能导致 Alluxio 和 UFS 间版本不一致。
5. **缓存隔离**：通过 `CACHE_ONLY` 写入并最终持久化到 UFS 的文件，在写入 UFS 后也不会从`CACHE_ONLY` 中移除。通过原始的`CACHE_ONLY` 路径读取会命中 `CACHE_ONLY` 缓存，而通过 UFS 路径读取则会走标准的 Alluxio Worker 读取流程——这两种缓存相互隔离，不共享数据。

### 功能启用

需完成以下配置：

1. 启用 CACHE\_ONLY（作为异步持久化的前提条件）
2. 配置`alluxio.gemini.master.async.upload.local.file.path`及对应的 JSON 路径（需在 Alluxio 和 Alluxio CACHE\_ONLY 节点上同时设置，详见下文说明）。
3. 启用 Alluxio Coordinator（异步持久化依赖 job 服务）。
4. 确保 CACHE\_ONLY Master 可连接 ETCD。
5. 如果通过 Operator 部署，请确保在 Alluxio CACHE\_ONLY 组件的配置中同步设置 Alluxio 全局参数。由于当前 Operator 的限制，部分操作生成的属性需要手动在 CACHE\_ONLY 组件中指定。

### 配置选项

| 属性                                                     | 描述                  | 默认    |
| ------------------------------------------------------ | ------------------- | ----- |
| `alluxio.gemini.master.async.upload.local.file.path`   | 异步上传路径映射JSON文件的存储路径 | *N/A* |
| `alluxio.gemini.master.persistence.checker.interval`   | 检查并更新异步持久化状态的时间间隔   | `1s`  |
| `alluxio.gemini.master.persistence.scheduler.interval` | 调度新的异步持久化任务的时间间隔    | `1s`  |

#### 异步上传路径映射配置文件

在 `alluxio.gemini.master.async.upload.local.file.path` 中指定的文件路径应为 JSON 格式。示例如下：

```json
{
  "cacheOnlyMountPoint": "/cache-only",
  "asyncUploadPathMapping": {
    "/cache-only/a": "/s3/a",
    "/cache-only/b": "/local/c"
  },
  "blackList": [
    ".tmp"
  ]
}
```

#### 支持的配置键

| 键名                       | 是否必填  | 描述                                             |
| ------------------------ | ----- | ---------------------------------------------- |
| `cacheOnlyMountPoint`    | 是     | CACHE\_ONLY 存储的挂载点路径                           |
| `asyncUploadPathMapping` | 是     | 键为 CACHE\_ONLY 子路径，值为要持久化的 Alluxio 路径（通过挂载表解析） |
| `blackList`              | 否（可选） | 简单的文件名模式排除列表（非正则表达式）                           |

***

### 容错机制

1. **Worker 故障**: 如果某个 `CACHE_ONLY` Worker 下线， Alluxio 可从其他存有副本的 CACHE\_ONLY Worker 获取数据（需启用副本机制）
2. **Master 故障切换**：异步持久化所需的元数据存储于 Alluxio Master 日志中。当一个 Master 故障时，备用 Master 可通过读取日志恢复元数据。
3. **Coordinator 重启**：异步持久化任务由 Alluxio Coordinator 管理，其 job 状态存储于本地 RocksDB。Coordinator 重启后可通过读取 RocksDB 状态恢复进行中的任务。
4. **Worker 重分配**：如果负责 UFS 上传的 Worker 故障，Coordinator 会将任务重新调度至其他 Worker。

***

### 从 UFS 恢复丢失数据

当文件从 `CACHE_ONLY` 中丢失时，Alluxio 支持通过以下机制从 UFS 恢复数据：

#### 恢复触发条件

1. **打开文件时发现数据块缺失**：通过 `CACHE_ONLY` 路径打开的文件若存在缺失块，客户端会自动从 UFS 拉取缺失内容并缓存。
2. **文件读取错误**：如果 Alluxio 在读取 `CACHE_ONLY` 中的文件时遇到错误，客户端将回退为直接从 UFS 读取该文件，**不会重新缓存到 Alluxio**。

#### 恢复所需前提条件

* 文件之前已经通过异步持久化写入到了 UFS；
* UFS中的文件修改时间**晚于** Alluxio 中的记录；
* UFS 中的文件长度与 Alluxio 元数据中记录的长度一致。

## 高级配置

### 启用多副本

CACHE\_ONLY 支持写入多副本，需要在部署文件里增加配置 `alluxio.gemini.user.file.replication`：

```yaml
apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
metadata:
  name: alluxio
spec:
  properties:
    "alluxio.gemini.user.file.replication": "2"
```

### 启用 multipart-upload

Alluxio 支持将写入的数据暂存到内存，在后台使用 multipart-upload 多线程上传到 CACHE\_ONLY 集群，这能够有效提高写入的性能。要开启此功能，需要增加以下配置：

```yaml
apiVersion: k8s-operator.alluxio.com/v1
kind: AlluxioCluster
metadata:
  name: alluxio
spec:
  properties:
    "alluxio.gemini.user.file.cache.only.multipart.upload.enabled": "true"
    "alluxio.gemini.user.file.cache.only.multipart.upload.threads": "16"
    "alluxio.gemini.user.file.cache.only.multipart.upload.buffer.number": "16"
```

| 配置项                                                                | 默认值   | 描述                                 |
| ------------------------------------------------------------------ | ----- | ---------------------------------- |
| alluxio.gemini.user.file.cache.only.multipart.upload.enabled       | false | 是否启用 multipart upload 功能           |
| alluxio.gemini.user.file.cache.only.multipart.upload.threads       | 16    | multipart upload 可使用的最大线程数         |
| alluxio.gemini.user.file.cache.only.multipart.upload.buffer.number | 16    | multipart upload 可使用的内存 buffer 的数量 |

**注意：**&#x5F00;启 multipart-upload 会显著增加 Alluxio Client 的内存使用量，内存使用量计算如下：

```
${alluxio.gemini.user.file.cache.only.multipart.upload.buffer.number} * 64MB 
```

### 缓存驱逐

以 CACHE\_ONLY 模式存储的文件不会被自动驱逐。 如果存储容量接近满载，可以手动删除这些文件以释放空间。 比如在 Alluxio FUSE 里使用 `rm ${file_path}` 或者在命令行里使用 `bin/alluxio fs rm ${file_path}`。
