# 哈希环与 Worker 生命周期

本指南涵盖一致性哈希环的配置、Worker 生命周期操作和诊断流程。关于单个 Worker 的配置（存储、资源、JVM、网络），请参阅 [Worker 配置](/ee-ai-cn/administration/managing-worker.md)。关于集群级别的操作（扩展、升级、Coordinator），请参阅 [集群管理](/ee-ai-cn/administration/managing-alluxio.md)。

{% hint style="warning" %}
哈希环设置应在初始集群设置期间定义。在正在运行的集群上修改这些配置是一项破坏性操作，将导致所有缓存数据丢失，因为它会更改数据到 Worker 的映射方式。
{% endhint %}

Alluxio 使用一致性哈希环以去中心化的方式将数据映射到 Worker。您可以微调其行为，以针对不同的集群环境和工作负载进行优化。

## 1. 部署前配置

在首次部署前设置以下属性：

| 属性                                                                                   | 默认值        | 何时调整                                                                                             |
| ------------------------------------------------------------------------------------ | ---------- | ------------------------------------------------------------------------------------------------ |
| `alluxio.user.dynamic.consistent.hash.ring.enabled`                                  | `true`（动态） | 仅当需要在 Worker 短暂不可用时保持稳定的环视图，才设置为 `false`（静态）——参见[配置哈希环模式](#pei-zhi-ha-xi-huan-mo-shi)            |
| `alluxio.user.worker.selection.policy.consistent.hash.virtual.node.count.per.worker` | `2000`     | 极少调整——仅适用于非常小或严重不均衡的集群。参见[调整虚拟节点以实现负载均衡](#tiao-zheng-xu-ni-jie-dian-yi-shi-xian-fu-zai-jun-heng) |
| `alluxio.user.worker.selection.policy.consistent.hash.provider.impl`                 | `DEFAULT`  | 异构 Worker 集群设置为 `CAPACITY`。参见[针对异构 Worker 进行优化](#zhen-dui-yi-gou-worker-jin-xing-you-hua)        |

{% tabs %}
{% tab title="Kubernetes (Operator)" %}
在 `alluxio-cluster.yaml` 的 `.spec.properties` 下设置：

```yaml
spec:
  properties:
    alluxio.user.dynamic.consistent.hash.ring.enabled: "true"
    alluxio.user.worker.selection.policy.consistent.hash.provider.impl: DEFAULT
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}
在 `conf/alluxio-site.properties` 中设置（对 client、worker、coordinator 进程都生效）：

```properties
alluxio.user.dynamic.consistent.hash.ring.enabled=true
alluxio.user.worker.selection.policy.consistent.hash.provider.impl=DEFAULT
```

{% endtab %}
{% endtabs %}

## 2. 哈希环配置

### 配置哈希环模式

一致性哈希环可以以两种模式运行：动态（默认）或静态。

在**动态模式**（默认）下，哈希环仅包含在线的 Worker。当 Worker 下线并超过存活检测超时后，它会从环中移除，其虚拟节点被重新分配给在线 Worker。这是大多数部署的最佳选择——环能自动适应永久性拓扑变更（如扩缩容或节点替换）。

在**静态模式**下，哈希环保留所有已注册的 Worker，无论其在线状态如何。此模式专为**计划性短期维护**场景设计——滚动软件升级、硬件维护或短暂重启等 Worker 预期会很快重新加入的情况。通过将离线 Worker 保留在环中，Alluxio 避免了缓存数据的重新分片：当 Worker 恢复时，它收回原始环槽位，所有缓存数据立即可路由。代价是在停机窗口期间，哈希到离线 Worker 的请求会 fallback 到 UFS。

要配置模式，请设置 `alluxio.user.dynamic.consistent.hash.ring.enabled` 属性。将其设置为 `true` 表示动态模式（默认值），设置为 `false` 表示静态模式。

### 调整虚拟节点以实现负载均衡

为确保数据和 I/O 请求的均匀分布，Alluxio 使用虚拟节点。每个 Worker 都映射到哈希环上的多个虚拟节点，这有助于在集群中更有效地平衡负载。

您可以通过配置 `alluxio.user.worker.selection.policy.consistent.hash.virtual.node.count.per.worker` 属性（默认值：`2000`）来调整每个 Worker 的虚拟节点数。调整此值有助于微调负载分布，尤其是在具有不同工作负载或少量 Worker 的集群中。

### 针对异构 Worker 进行优化

默认情况下，一致性哈希算法假定所有 Worker 都具有相同的容量。在具有异构 Worker（例如，不同的存储容量或网络速度）的集群中，您可以启用基于容量的分配，以实现更均衡的资源利用。这确保了具有更多存储空间的 Worker 能处理相应更大部分的数据。

要启用此功能，请将 `alluxio.user.worker.selection.policy.consistent.hash.provider.impl` 属性设置为 `CAPACITY`。默认值为 `DEFAULT`，它为每个 Worker 分配相同数量的虚拟节点。

关于 Worker 侧的 YAML 配置（节点标记、`workerGroups`），请参阅 [异构 Worker](/ee-ai-cn/administration/managing-worker.md#yi-gou-worker)。

### Worker 存活检测

每个 Worker 主动与 etcd 保持通信以维持其活跃状态。若 Worker 在超时时间内未能与 etcd 通信，则被视为离线：

```properties
# 网络抖动后 worker 重连较慢时可适当增大（默认值：15s）
alluxio.worker.failure.detection.timeout=30s
```

在动态模式下，`OFFLINE` 的 Worker 在超时后从哈希环中移除，其虚拟节点被重新分配给在线 Worker。在静态模式下，`OFFLINE` 条目仍留在环中——哈希到该节点的请求会 fallback 到 UFS，直到 Worker 重新加入或被显式移除。

### 客户端 Worker 列表刷新

客户端维护 Worker 列表的本地快照，并定期从 etcd 刷新：

```properties
# 降低可加快故障切换；增大可减少 etcd 读压力（默认值：45s）
alluxio.user.worker.list.refresh.interval=2m
```

添加或移除 Worker 后，客户端将在一个刷新周期内反映变更。如需在故障恢复时立即生效，可重启客户端进程或临时缩短此间隔。

## 3. Worker 在环上的生命周期

Alluxio 的去中心化架构依赖于通过一致性哈希环管理的 Worker。本节介绍 Worker 加入、离开和重启环的操作流程。

### 检查 Worker 状态

查看所有已注册 Worker 及其当前状态：

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

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- alluxio info nodes
```

{% endtab %}

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

```shell
bin/alluxio info nodes
```

{% endtab %}
{% endtabs %}

```console
WorkerID                              Host               Status
e87b4097-b7f8-48a4-a388-3197124ebbe7  ip-172-16-10-12    ONLINE
a1f23c45-d678-90ab-cdef-123456789012  ip-172-16-10-13    ONLINE
```

#### 诊断 OFFLINE 条目导致的哈希环膨胀

健康集群的 `alluxio info nodes` 输出中，ONLINE 条目数应等于配置的 Worker 数。若总条目数超出预期，或 ONLINE 数低于 Worker 数，说明 etcd 中存在过期 `OFFLINE` 条目。

**影响（静态模式）：** 在静态模式（`alluxio.user.dynamic.consistent.hash.ring.enabled=false`）下，`OFFLINE` 条目在环中无限期保留。过期条目占比越高，fallback 到 UFS 的哈希查找比例越大——将缓存命中变为直接读 S3/GCS 的速度。

在动态模式（默认）下，`OFFLINE` 条目在 `alluxio.worker.failure.detection.timeout` 后自动从环中移除（参见 [Worker 存活检测](#worker-cun-huo-jian-ce)），不会持续膨胀。但每次以新 UUID 重启仍会重新分配虚拟节点，导致已缓存数据暂时不可访问。

验证哈希环健康——ONLINE 数量应等于配置的 Worker 数：

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

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- alluxio info nodes | grep -c ONLINE
```

{% endtab %}

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

```shell
bin/alluxio info nodes | grep -c ONLINE
```

{% endtab %}
{% endtabs %}

如需从 etcd 中删除某个过期的 `OFFLINE` 条目，从 `alluxio info nodes` 输出中获取其 UUID，然后执行 `alluxio process remove-worker`：

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

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio process remove-worker -n <STALE_WORKER_UUID>
```

{% endtab %}

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

```shell
bin/alluxio process remove-worker -n <STALE_WORKER_UUID>
```

{% endtab %}
{% endtabs %}

### 添加或移除 Worker

新 Worker 在启动时会自动在 etcd 中注册并加入哈希环。移除 Worker 后，其哈希环部分将被重新分配给剩余 Worker，在数据从 UFS 重新加载期间会出现缓存未命中率暂时增加。

{% tabs %}
{% tab title="Kubernetes (Operator)" %}
调整 `alluxio-cluster.yaml` 中的 `worker.count` 并应用——完整步骤参见 [扩展集群](/ee-ai-cn/administration/managing-alluxio.md#kuo-zhan-ji-qun)。
{% endtab %}

{% tab title="Docker / Bare-Metal" %}
在目标主机上启动新的 Worker 进程（Docker：`docker run ... alluxio/alluxio-enterprise worker`；裸机：`bin/alluxio process start worker`）。要移除，则停止该 Worker 进程；注销步骤参见[永久移除 Worker](#yong-jiu-yi-chu-worker)。
{% endtab %}
{% endtabs %}

### 永久移除 Worker

下线某个节点时，需先停止 Worker，再从 etcd 中显式注销该 Worker，避免其以过期 `OFFLINE` 条目的形式残留。

**步骤 1：停止 Worker。**

{% tabs %}
{% tab title="Kubernetes (Operator)" %}
在 `alluxio-cluster.yaml` 中缩减 `worker.count` 并应用：

```shell
kubectl apply -f alluxio-cluster.yaml
```

{% endtab %}

{% tab title="Docker / Bare-Metal" %}
停止下线主机上的 Worker 进程（Docker：`docker stop alluxio-worker`；裸机：`bin/alluxio process stop worker`）。
{% endtab %}
{% endtabs %}

**步骤 2：从 etcd 注销 Worker。** 通过 `alluxio info nodes` 获取该 Worker 的 UUID，然后执行 `alluxio process remove-worker`：

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

```shell
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- alluxio info nodes
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio process remove-worker -n <WORKER_UUID>
```

{% endtab %}

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

```shell
bin/alluxio info nodes
bin/alluxio process remove-worker -n <WORKER_UUID>
```

{% endtab %}
{% endtabs %}

在动态模式下，跳过步骤 2 通常是安全的——`OFFLINE` 条目会在 `alluxio.worker.failure.detection.timeout` 超时后自动清除。在静态模式下，步骤 2 是必须执行的，否则过期条目将无限期留在哈希环中。

### 重启 Worker

Worker 重启时会暂时被标记为离线。配置身份持久化后，Worker 将以相同 UUID 重新加入——保留其环位置、缓存数据和负载分布。

未配置身份持久化时，每次重启会生成新的 UUID 和不同的环槽位，导致缓存未命中和潜在的环膨胀。详情请参阅 [配置哈希环模式](#pei-zhi-ha-xi-huan-mo-shi) 和 [诊断 OFFLINE 条目导致的哈希环膨胀](#zhen-duan-offline-tiao-mu-dao-zhi-de-ha-xi-huan-peng-zhang)。

#### 持久化 Worker 身份

{% tabs %}
{% tab title="Kubernetes (Operator)" %}
在首次部署前，在 `alluxio-cluster.yaml` 中设置 `worker.systemInfo.hostPath`：

```yaml
spec:
  worker:
    useExternalId: false
    systemInfo:
      hostPath: /mnt/alluxio/system-info
```

{% endtab %}

{% tab title="Docker" %}
在首次启动前，在宿主机上预先创建空文件并挂载为 volume。Alluxio 启动时会将 UUID 写入该文件，容器重建后文件依然保留：

```shell
sudo mkdir -p /etc/alluxio
sudo touch /etc/alluxio/worker_identity
```

在 worker `docker run` 命令中添加：

```shell
-v /etc/alluxio/worker_identity:/opt/alluxio/conf/worker_identity
```

{% hint style="warning" %}
使用 `-v` 挂载前，**必须**先在宿主机上创建该文件。若宿主机路径不存在，Docker 会在该路径创建一个**目录**而非文件，导致 Alluxio 启动失败并报错 `IOException: Is a directory`。
{% endhint %}

完整 Docker 配置指南参见 [附录 B：Worker 节点身份](https://documentation.alluxio.io/ee-ai-cn/administration/pages/Wb9Sk0fPVxU8wn1ZLnEK#b.-worker-节点身份)。
{% endtab %}

{% tab title="裸机" %}
将 `alluxio.worker.identity.uuid.file.path` 设置为重启后仍然存在的路径：

```properties
alluxio.worker.identity.uuid.file.path=/etc/alluxio/worker_identity
```

该文件在首次启动时自动创建。若需手动固定现有 Worker 的 UUID（如迁移到持久路径时），先从 `alluxio info nodes` 获取当前 UUID，再写入配置的路径。
{% endtab %}
{% endtabs %}

{% hint style="warning" %}
如果 Worker 被迁移到不同的主机，请在启动 Worker 之前将身份文件复制到新主机的相同路径。若文件缺失，Worker 将以新 UUID 注册，之前身份下的所有缓存数据将不可访问。
{% endhint %}

### Worker 重启后的缓存恢复

**已配置身份持久化的情况下**，重启的 Worker 以相同 UUID 重新加入哈希环，其此前缓存的数据页仍可访问。但是，恢复的 Worker 可能缺少**在其离线期间被加载到其他 Worker 上的数据**——停机期间，这些文件被路由到临时持有该 Worker 哈希环槽位的其他 Worker，因此恢复的 Worker 从未缓存过它们。一旦重新加入哈希环，这些文件重新映射到此 Worker，但其本地缓存中并没有这些数据。

使用以下步骤填补空洞，同时避免重复加载：

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

```shell
# 确认 Worker 已重新加入哈希环
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio info nodes | grep ONLINE
# 预期：N 条记录全部显示 ONLINE（N = 配置的 Worker 数量）

# 重新触发加载——跳过任意 Worker 上已缓存的文件
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path <ufs-or-alluxio-path> --submit --skip-if-exists

# 监控直到 SUCCEEDED
kubectl exec -n <NAMESPACE> alluxio-cluster-coordinator-0 -- \
  alluxio job load --path <ufs-or-alluxio-path> --progress
```

{% endtab %}

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

```shell
# 确认 Worker 已重新加入哈希环
bin/alluxio info nodes | grep ONLINE
# 预期：N 条记录全部显示 ONLINE（N = 配置的 Worker 数量）

# 重新触发加载
bin/alluxio job load --path <ufs-or-alluxio-path> --submit --skip-if-exists

# 监控直到 SUCCEEDED
bin/alluxio job load --path <ufs-or-alluxio-path> --progress
```

{% endtab %}
{% endtabs %}

`--skip-if-exists` 确保已在健康 Worker 上缓存的文件不会从 UFS 重复拉取。只有当前映射到恢复 Worker 但该 Worker 尚未缓存的文件才会被加载。

**未配置身份持久化的情况下**，Worker 以新 UUID 注册，占据不同的哈希环槽位。旧 UUID 下缓存的所有数据变为不可访问，需要完整重新加载才能恢复缓存覆盖率。这正是身份持久化作为生产环境必备配置的原因——参阅 [持久化 Worker 身份](#chi-jiu-hua-worker-shen-fen)。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://documentation.alluxio.io/ee-ai-cn/administration/managing-ring.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
