> For the complete documentation index, see [llms.txt](https://documentation.alluxio.io/ee-ai-cn/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.alluxio.io/ee-ai-cn/cache/loading-data-into-the-cache.md).

# 缓存加载

Alluxio 通过两种方式填充缓存：**被动缓存**（首次读取时自动触发，无需配置）和**主动预加载**（通过 `job load` 命令在作业运行前显式加载数据）。

## 前提条件

* 至少有一个 Worker 的 Alluxio 集群正在运行
* 已配置至少一个 UFS 挂载（通过 `alluxio mount list` 验证）

{% hint style="info" %}
Alluxio 会根据配置的驱逐策略自动腾出空间来存放新数据，提交加载作业前无需手动清理缓存。
{% endhint %}

## 被动缓存

每次缓存未命中时，Alluxio 会从 UFS 获取文件，并在将数据流式传输给应用程序的同时将其写入 Worker 缓存。无需任何配置——后续读取直接从缓存提供。

这是默认行为。当无法承受首次读取延迟时，请使用主动预加载。

## 使用 `job load` 主动预加载

`job load` 提交一个分布式加载作业：Coordinator 将任务分发给所有 Worker，每个 Worker 直接从 UFS 拉取分配给自己的文件。调度原理、HA 配置及高级调优请参阅 [Job Service](/ee-ai-cn/administration/managing-job-service.md)。

### 速查

有三种**互斥**的方式指定加载内容（三选一），下表还列出了常见后续任务对应的做法：

| 场景 / 任务                    | 做法                                        |
| -------------------------- | ----------------------------------------- |
| 加载一个目录或整个数据集（递归）           | `--path`（见下文）                             |
| UFS 上已有的显式文件清单             | `--index-file`（见*从索引文件加载*）                |
| 客户端上的文件清单（如脚本生成），无需上传到 UFS | `--local-index-file`（见*从索引文件加载*）          |
| 第一次 load 后有失败文件，补齐         | 加 `--skip-if-exists` 重跑（见*常用参数* / *故障处理*） |
| 数据源被原地覆盖更新，缓存跟着更新          | `--load-policy IF_CHANGED`（见*增量加载*）       |
| 提交后需要改参数、重来                | 加 `--overwrite`（见*修改运行中作业的参数*）            |
| 超大数据集（几十万文件以上）             | 拆成多个作业（见*拆分超大数据集*）                        |

下文示例以 `--path` 为主；另两种索引文件形式见*从索引文件加载*。

### 提交前检查

三个快速检查可避免大部分"整批失败"：

1. **挂载点路径拼写**——目标必须在已挂载的 UFS 下。bucket 名拼错会导致每个文件瞬间失败、作业秒级 FAILED 且零字节加载。用 `alluxio mount list` 核对。
2. **清单尽量干净**——不存在的条目会各记为 1 个失败文件（重试到上限后放弃），其余照常加载，但作业最终为 FAILED。能提前清洗就提前清洗。
3. **重复提交是幂等的**——作业运行期间用同一 path/清单重复提交，不会新建作业、也不会更改其参数，而是并入现有作业。要更改参数请用 `--overwrite`（见*修改运行中作业的参数*）。

### 提交与监控

`--path` 支持 UFS 路径（如 `s3://my-bucket/dataset/`）或 Alluxio 虚拟路径（如 `/mnt/dataset/`），详见 [CLI 参考](/ee-ai-cn/reference/user-cli.md#job-load)。

{% tabs %}
{% tab title="Kubernetes (Operator)" %}

```shell
# 提交（立即返回）
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path <ufs-or-alluxio-path> --submit

# 查看进度
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path <ufs-or-alluxio-path> --progress
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}

```shell
# 提交（立即返回）
bin/alluxio job load --path <ufs-or-alluxio-path> --submit

# 查看进度
bin/alluxio job load --path <ufs-or-alluxio-path> --progress
```

{% endtab %}
{% endtabs %}

进度输出示例：

```console
Progress for loading path 's3://my-bucket/dataset/':
        Settings:       replicas: unset  batch-size: 600  verify: false  metadata-only: false  quota-check: false
        Time start: 2026-04-15T22:05:01  Time finished: 2026-04-15T22:05:08  Time Elapsed: 7s
        Job State: SUCCEEDED
        Inodes Scanned: 1000  Non Empty File Copies Loaded: 1000
        Bytes Scanned: 125.00MiB  Bytes Loaded: 125.00MiB  Throughput: 17.86MiB/s
        File Failure rate: 0.00%  Subtask Failure rate: 0.00%
        Files Failed: 0  Subtask Retry rate: 0.00%  Subtasks on Retry Dead Letter Queue: 0
```

### 通过 REST API 提交

每个 `job load` 操作也可通过 Coordinator 的 REST 接口完成（端口 `19999` 上的 `POST /api/v1/load`），便于程序化提交。请求体字段与 CLI 参数一一对应：

* `path` —— 单个目录或文件（相当于 `--path`）
* `index` —— UFS 索引文件（相当于 `--index-file`）
* `paths` + `alias` —— 内联路径列表（相当于 `--local-index-file`）；`alias` 是调用方自定义的名字，用于后续按它查询进度/停止作业
* `isOverWrite` —— 顶层字段，相当于 `--overwrite`
* `options` —— 嵌套对象：`skipIfExists`、`loadPolicy`（`"IF_CHANGED"`）、`verify`、`batchSize`、`fileFilterRegex`

```shell
# 提交目录加载
curl -X POST http://<coordinator>:19999/api/v1/load \
  -H 'Content-Type: application/json' \
  -d '{"path": "s3://my-bucket/dataset/", "options": {"skipIfExists": true}}'

# 提交内联路径列表（必须带 alias）
curl -X POST http://<coordinator>:19999/api/v1/load \
  -H 'Content-Type: application/json' \
  -d '{"paths": ["s3://my-bucket/a.parquet", "s3://my-bucket/day=1/"], "alias": "warmup-1"}'

# 查询进度——按 path，或对内联列表作业按 alias
curl -s 'http://<coordinator>:19999/api/v1/load?target=warmup-1'
```

完整的请求/响应格式、错误码以及停止/文件列表接口，参见 [REST API 参考](/ee-ai-cn/reference/rest-api.md)。

### 停止运行中的作业

{% tabs %}
{% tab title="Kubernetes (Operator)" %}

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path <ufs-or-alluxio-path> --stop
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}

```shell
bin/alluxio job load --path <ufs-or-alluxio-path> --stop
```

{% endtab %}
{% endtabs %}

已停止的作业可通过再次使用 `--submit` 提交来恢复。已缓存的文件若加上 `--skip-if-exists` 参数则会被跳过。

### 常用参数

| 参数                                | 说明                                                    |
| --------------------------------- | ----------------------------------------------------- |
| `--submit`                        | 异步提交作业（立即返回）                                          |
| `--progress`                      | 查看已提交作业的进度                                            |
| `--stop`                          | 停止运行中的作业                                              |
| `--verify`                        | 加载完成后验证所有文件均已缓存，并重新加载缺失的文件                            |
| `--replicas <n>`                  | 每个文件加载 `n` 个副本（默认：1）；适用于高并发读取场景                       |
| `--skip-if-exists`                | 跳过已完全缓存的文件（可安全重复执行加载作业）                               |
| `--load-policy IF_CHANGED`        | 对每个已缓存文件与 UFS 元数据进行比对，仅重新加载内容发生变化的文件。适用于可变数据集的增量同步。   |
| `--metadata-only`                 | 仅加载文件元数据，不缓存文件数据                                      |
| `--batch-size <n>`                | 每个 Worker 每批处理的文件数，默认值 600。该默认值对大小文件都适用，通常无需调整。       |
| `--partial-listing`               | 在完整目录列举完成前开始加载；适用于超大目录                                |
| `--index-file <ufs-path>`         | 从 UFS 索引文件中加载指定文件列表（每行一个路径）                           |
| `--local-index-file <local-path>` | 与 `--index-file` 类似，但清单从客户端本地文件系统读取并随请求发送——无需先上传到 UFS |
| `--overwrite`                     | 终止同一路径的现有作业，并以新参数提交一个全新作业（见*修改运行中作业的参数*）              |

完整参数说明请参阅 [`job load` CLI 文档](/ee-ai-cn/reference/user-cli.md#job-load)。

### 从索引文件加载

适用于选择性加载，或目录树过大不适合整体遍历的场景：

{% tabs %}
{% tab title="Kubernetes (Operator)" %}

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --index-file s3://my-bucket/load-manifest.txt --submit
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}

```shell
bin/alluxio job load --index-file s3://my-bucket/load-manifest.txt --submit
```

{% endtab %}
{% endtabs %}

索引文件格式——每行一个 UFS 路径，以 `#` 开头的行为注释：

```
s3://my-bucket/dataset/train/
s3://my-bucket/dataset/val/file.parquet
# s3://my-bucket/dataset/test/   <- 跳过此行
```

每行是以下两种之一：

* **文件**（不以 `/` 结尾）会被直接派发给 Worker——coordinator 对它不做任何列举，是开销最低的形式。
* **目录**（以 `/` 结尾）会被 coordinator 递归列举。若清单中某个条目不存在，该行会被计为 1 个失败文件，其余行继续处理（见故障处理一节）。

若清单位于**客户端本地文件系统**（例如脚本生成的清单），改用 `--local-index-file <local-path>`——客户端读取该文件并随请求一起发送，无需先上传到 UFS。文件格式完全相同。对于很长的清单（几十万行以上），建议改用 UFS 上的 `--index-file`：本地清单会在单个请求中发送，过大时可能超出请求大小上限。

### 增量加载（可变数据集）

当数据集周期性更新时（例如每日模型 checkpoint、更新的训练集划分），使用 `--load-policy IF_CHANGED` 只同步自上次加载以来发生变化的文件：

{% tabs %}
{% tab title="Kubernetes (Operator)" %}

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path <ufs-or-alluxio-path> --submit --load-policy IF_CHANGED
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}

```shell
bin/alluxio job load --path <ufs-or-alluxio-path> --submit --load-policy IF_CHANGED
```

{% endtab %}
{% endtabs %}

`--load-policy IF_CHANGED` 会对每个**已缓存**文件与 UFS 元数据进行比对，仅在内容发生变化时重新加载；尚未缓存的文件会无条件加载。这使得它非常适合可变数据集的周期性同步：新文件会被缓存，已变化的文件会被刷新，未变化的文件会被跳过。

| 参数                         | 已缓存文件       | 未缓存文件 |
| -------------------------- | ----------- | ----- |
| `--submit`（无额外 flag）       | 无条件重新加载     | 加载    |
| `--skip-if-exists`         | 跳过          | 加载    |
| `--load-policy IF_CHANGED` | 仅在内容变化时重新加载 | 加载    |

### 修改运行中作业的参数

作业运行期间用同一路径重复提交是幂等的——运行中的作业保持原有参数，新传入的参数会被忽略（CLI 会提示 `Load already running ... Other params will remain the same`）。如果提交后需要修改某个提交时参数，无需先 `--stop` 再重提：加上 `--overwrite` 即可一步完成"终止现有作业 + 以新参数提交全新作业"。下面的示例调大了 `--batch-size`——这是少数值得覆盖默认值的场景之一，例如小文件工作负载下 Worker 大多处于空闲时。

{% tabs %}
{% tab title="Kubernetes (Operator)" %}

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path <ufs-or-alluxio-path> --submit --overwrite --batch-size 2000 --skip-if-exists
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}

```shell
bin/alluxio job load --path <ufs-or-alluxio-path> --submit --overwrite --batch-size 2000 --skip-if-exists
```

{% endtab %}
{% endtabs %}

旧作业会被终止并标记为 `FAILED`（原因：`will be overwritten`）——这是预期现象。`--overwrite` **不会驱逐已缓存的数据**（它不是 `job free`），因此请配合 `--skip-if-exists`：新作业会重新枚举所有文件，但 Worker 会跳过已完全缓存的文件，只重新加载剩余部分。

### 拆分超大数据集

单个作业加载几十万文件是可行的，但拆分成多个中等规模的作业通常体验更好：故障影响面更小（单个作业失败只影响它那部分数据），补齐重跑也更快。可按目录拆分（每个分区一个作业），或把清单分组（每组一个 `--local-index-file`）。这关乎故障隔离与补齐粒度，而非并发——Coordinator 对同时运行的作业数有上限，因此几个到十几个并行作业是合适的规模。

## 与 ML 训练集成

典型工作流：加载数据 → 验证 → 启动训练。

{% tabs %}
{% tab title="Kubernetes (Operator)" %}

```shell
# 1. 提交加载
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path s3://my-bucket/dataset/ --submit --verify

# 2. 轮询直到完成
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path s3://my-bucket/dataset/ --progress
# 重复执行直到 "Job State: SUCCEEDED"，然后启动训练 Pod
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}

```shell
# 1. 提交加载
bin/alluxio job load --path s3://my-bucket/dataset/ --submit --verify

# 2. 等待完成
bin/alluxio job load --path s3://my-bucket/dataset/ --progress
# 重复执行直到 "Job State: SUCCEEDED"

# 3. 启动训练
python train.py --data /mnt/alluxio/fuse/dataset/
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**近 100% 缓存覆盖率：** 对于关键数据集，建议在第一次 job 达到 `SUCCEEDED` 后再执行一次 `--skip-if-exists` 的补充加载。极少数情况下（Worker 短暂故障或哈希环边界时序问题），单次加载可能遗漏极小比例的文件。第二次执行可以填补这些空缺，且不会重复加载已缓存的数据：

{% tabs %}
{% tab title="Kubernetes (Operator)" %}

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path <ufs-or-alluxio-path> --submit --skip-if-exists
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}

```shell
bin/alluxio job load --path <ufs-or-alluxio-path> --submit --skip-if-exists
```

{% endtab %}
{% endtabs %}
{% endhint %}

## 故障处理

`job load` 是一个尽力而为（best-effort）的长时作业；它**不**保证 100% 成功，也不是"全有或全无"。大数据集上个别文件失败是正常现象（对象存储瞬时超时、Worker 重启等）。最终 `Job State: FAILED` 表示*部分失败*——已成功加载的文件仍在缓存中，并不代表什么都没加载。每个失败文件会重试有限次数（默认 40 次，`alluxio.master.dora.load.job.subtask.max.retry.attempts`）后才计为失败，因此失败不会无限重试或卡死作业。标准的补齐方式是加 `--skip-if-exists` 重新运行。

**`Job State: FAILED`，`Files Failed > 0`**

查看文件级别的失败列表：

{% tabs %}
{% tab title="Kubernetes (Operator)" %}

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path <path> --progress --file-status FAILURE
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}

```shell
bin/alluxio job load --path <path> --progress --file-status FAILURE
```

{% endtab %}
{% endtabs %}

常见原因：UFS 访问错误、网络超时或凭证缺失。排查根本原因后，使用 `--skip-if-exists` 重新提交，避免重复加载已缓存的文件（若忘加 `--skip-if-exists`，默认会全量重跑、耗时很长）。进度报告顶部的 `Failed files saved to: <路径>` 会给出落在 Coordinator 本地的完整失败清单文件，可据此生成只含失败文件的补齐用 index 文件；`--progress --format JSON --verbose` 可获取结构化详情与失败原因样本。

**提交后立即出现 `Job State: FAILED`**

使用 `--verbose` 获取详情：

{% tabs %}
{% tab title="Kubernetes (Operator)" %}

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path <path> --progress --verbose
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}

```shell
bin/alluxio job load --path <path> --progress --verbose
```

{% endtab %}
{% endtabs %}

常见原因：挂载表中找不到路径（通过 `alluxio mount list` 验证），或缓存配额不足。

**加载成功但读取仍走 UFS**

验证特定文件是否已缓存：

{% tabs %}
{% tab title="Kubernetes (Operator)" %}

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio fs check-cached <path>
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}

```shell
bin/alluxio fs check-cached <path>
```

{% endtab %}
{% endtabs %}

若文件在加载成功后显示为未缓存，数据可能已被驱逐。请检查缓存容量和驱逐配置——参阅[缓存驱逐](/ee-ai-cn/cache/removing-data-from-the-cache.md)。集群级缓存命中率可通过[监控](/ee-ai-cn/administration/monitoring-alluxio.md)查看。

`check-cached` 作用于目录或清单（用 `--index-file <manifest>` 检查指定列表），不接受单个文件路径。若要核实某个具体文件，直接查询 Worker，看 `mInAlluxioPercentage` 是否为 `100`：

```shell
curl -s 'http://<worker>:28080/v1/info?path=<url-encoded-ufs-path>'
```

若路径中含 `=`——例如 `date=2026-07-01` 这类 Hive 分区目录——需将其编码为 `%253D`，否则路径会被截断、查询返回 404。

故障速查：

| 现象                       | 处理                                                         |
| ------------------------ | ---------------------------------------------------------- |
| 结束显示 FAILED，但大部分文件都能读且很快 | 正常的部分失败；看 `Files Failed` 与失败清单，用 `--skip-if-exists` 重跑补齐   |
| 提交后秒级 FAILED、零字节加载       | 目标多半不在挂载点下（bucket 拼错）；核对挂载与路径                              |
| 清单里有不存在的文件               | 各记 1 个失败，其余正常加载；终态 FAILED，按失败清单核对                          |
| 重跑一次很久                   | 忘加 `--skip-if-exists`（默认全量）；或用失败清单精确补齐                     |
| 源文件更新了但读到旧内容             | 用 `--load-policy IF_CHANGED` 重新预热该路径                       |
| 确认某个文件是否已缓存              | 单文件用 worker `/v1/info`，批量用 `check-cached --index-file`（见上） |

## 历史作业保留

已完成的作业记录会保留一段可配置的时间，默认为 7 天。如需调整：

```properties
# 将已完成作业记录保留 3 天（默认：7d）
alluxio.job.retention.time=3d
```

## 相关文档

* [缓存驱逐](/ee-ai-cn/cache/removing-data-from-the-cache.md) — `job free` 手动释放、版本更新模式以及自动驱逐策略
* [Job Service](/ee-ai-cn/administration/managing-job-service.md) — `job list`、作业状态、Coordinator HA、故障恢复和配置调优
* [多副本](/ee-ai-cn/high-availability/multiple-replicas.md) — 为每个文件加载多个副本以提高容错性
* [`job load` CLI 参考](/ee-ai-cn/reference/user-cli.md#job-load)
