☰
Alluxio 架构深度解析:Master–Worker–Client 体系与读写数据流全解
2026/10/7 9:53:29 网站建设 项目流程
  • 存储
  • 分布式文件系统
  • 缓存
  • 大数据

【免费下载链接】alluxio

Alluxio, data orchestration for analytics and machine learning in the cloud

项目地址:https://gitcode.com/gh_mirrors/al/alluxio
点击查看免费下载

导读:本文以 Alluxio 官方架构文档(docs/en/overview/Architecture.md)为骨架,系统讲解 Alluxio 在存储与计算之间扮演的“数据访问层”角色,拆解 Master(含 Job Master)、Worker(含 Job Worker)与 Client 三大组件的职责边界,并结合本仓库源码逐段分析本地缓存命中、远程缓存命中、缓存未命中以及 MUST_CACHE / CACHE_THROUGH / ASYNC_THROUGH / THROUGH 四种写入模式背后的数据流与一致性语义。读完本文,你将能够准确判断不同读写场景下的数据路径、关键配置项(如alluxio.worker.network.async.cache.manager.threads.max、alluxio.user.file.replication.durable)的调优含义,以及在生产集群中如何规划 Alluxio 组件部署。

一、架构总览:位于存储与计算之间的数据访问层

Alluxio 在大数据与机器学习生态中的定位是全新的数据访问层(data access layer)。它位于任何持久化存储系统(如 Amazon S3、Microsoft Azure Object Store、Apache HDFS、OpenStack Swift)与计算框架(如 Apache Spark、Presto、Hadoop MapReduce)之间。需要特别强调的是:Alluxio 本身不是持久化存储系统,它不对数据做最终保存,而是对上层应用提供高速缓存与统一命名空间视图。

作为数据访问层,Alluxio 带来两个方向的核心收益:

  • 对用户应用与计算框架而言:Alluxio 提供快速存储,促进不同应用之间、应用与数据之间的数据共享与本地性(locality),且与底层计算引擎无关。当数据位于本地时,Alluxio 可以按内存速度提供数据;当数据位于 Alluxio 集群内但不在本机时,则按计算集群网络速度提供数据。数据仅在首次访问时从底层存储系统(Under Storage System,UFS)读取一次。当 UFS 访问较慢时,数据访问会被显著加速。为了达到最佳性能,官方推荐将 Alluxio与计算框架部署在同一个集群中(co-located)。
  • 对底层存储系统而言:Alluxio 弥合了大数据应用与传统存储系统之间的鸿沟,扩展了能够使用这些数据的负载范围。由于 Alluxio 对应用隐藏了 UFS 的集成细节,任何 UFS 都可以支撑运行在 Alluxio 之上的任意应用与框架;当同时挂载(mount)多个 UFS 时,Alluxio 便成为任意数量、多种数据源的统一层。

一个典型的 Alluxio 集群由三类组件构成:

组件组成说明
Master1 个 Leading Master、多个 Standby Master、1 个 Job Master、多个 Standby Job Master管理全局元数据、调度 Job 任务
Worker多个 Worker、多个 Job Worker管理本地资源、以块(block)形式存储与服务数据
ClientSpark/MapReduce 作业、Alluxio CLI、Alluxio FUSE 层等与应用集成,与 Master/Worker 通信

其中 Master 与 Worker 进程合称Alluxio servers,是系统管理员需要维护的组件;Client 则被 Spark、MapReduce 作业、Alluxio CLI 以及 Alluxio FUSE 层等使用,用于与服务器通信。

在源码中,Master 与 Worker 进程的启动入口分别位于 AlluxioMaster.java(main方法启动 Master 进程)与 AlluxioWorker.java;Master 进程的完整装配逻辑可见 AlluxioMasterProcess.java,Worker 进程对应 AlluxioWorkerProcess.java。

1.1 Job Service:轻量任务调度框架

Alluxio Job Master 与 Job Worker 可被独立分离出来,称为Job Service。这是一个轻量级任务调度框架,负责把若干不同类型的操作分配给 Job Worker 执行,包括:

  • 从 UFS 向 Alluxio 加载数据(Load);
  • 将数据持久化到 UFS(Persist);
  • 在 Alluxio 内部复制文件(Replicate);
  • 在 UFS 与 Alluxio 位置之间移动或拷贝数据(Move / Copy)。

Job Service 的设计初衷是:所有与 Job 相关的进程不必与 Alluxio 集群的其他部分放在一起。但官方仍然推荐将 Job Worker 与对应的 Alluxio Worker 部署在同一节点,因为这样可以降低 RPC 与数据传输的延迟。有关 Job Service 的更多说明可参考 docs/en/overview/JobService.md。

二、Master:全局元数据的管理者

Alluxio 包含两类 Master 进程:

  • Alluxio Master:服务所有用户请求,并对文件系统元数据变更进行日志记录(journal);
  • Alluxio Job Master:充当文件系统操作的轻量级调度器,操作最终在Alluxio Job Workers上执行。

Alluxio Master可以部署为 1 个 Leading Master 加多个 Standby Master 以实现容错(HA):当 Leading Master 宕机时,Standby Master 会被选举为新的 Leading Master。在源码层面,Master 进程通过 MasterUtils.createMasters() 统一注册 FileSystemMaster、BlockMaster、MetaMaster、JournalMaster 等核心服务,而选举与主备切换逻辑则由 MasterProcess.java 中的PrimarySelector驱动。

2.1 Leading Master(主 Master)

一个 Alluxio 集群中只能有一个 Leading Master,它负责管理系统的全局元数据,具体包括:

  • 文件系统元数据:如文件系统 inode 树;
  • 块元数据:如块的位置(block locations);
  • Worker 容量元数据:空闲与已用空间(free and used space)。

几个关键行为约束决定了 Alluxio 的数据通路:

  1. Leading Master只查询 UFS 的元数据,应用数据永远不会经过 Master 路由——这是“元数据与数据分离”架构的根基;
  2. 所有 Alluxio Client 与 Leading Master 交互以读取或修改元数据;
  3. 所有 Worker周期性地向 Leading Master 发送心跳(heartbeat)以维持其集群参与状态;Leading Master不会主动向其他组件发起通信,它只通过 RPC 服务响应请求;
  4. Leading Master 将所有文件系统事务记录到分布式持久化存储位置(即 journal),以便恢复 Master 状态。

从源码可以印证这些行为:Master 侧的 RPC 服务由 FileSystemMasterClientServiceHandler.java 提供(createFile、delete、rename、mount、setAttribute等元数据操作均在此实现);Worker 心跳处理在 FileSystemMasterWorkerServiceHandler.fileSystemHeartbeat() 中完成;块元数据(容量、块位置)由 DefaultBlockMaster 负责维护(该文件位于core/server/master/src/main/java/alluxio/master/block/目录下)。

2.2 Standby Master(备用 Master)

Standby Master 运行在不同的服务器上,用于在HA 模式下提供容错。它们的行为特征:

  • 读取 Leading Master 写入的 journal,以保持自身 Master 状态副本最新;
  • 也会写入 journal checkpoint,以便未来更快恢复;
  • 不处理来自其他 Alluxio 组件的任何请求;
  • Leading Master 故障切换(fail-over)后,Standby Masters 之间会重新选举出新的 Leading Master。

2.3 Secondary Master(仅用于 UFS journal)

当以单 Master(非 HA)模式 + UFS journal运行时,可以在与 Leading Master 相同的服务器上启动一个Secondary Master,专门用于写入 journal checkpoint。注意两个关键区别:

  • Secondary Master 的设计目的不是提供高可用,而是为 Leading Master 分担 checkpoint 写入工作,从而加快恢复速度;
  • 与 Standby Master 不同,Secondary Master 永远不能升级为 Leading Master。

源码中对应实现为 AlluxioSecondaryMaster.java,其main方法即启动该辅助进程。

2.4 Job Master:异步调度重型文件系统操作

Alluxio Job Master 是独立进程,负责在 Alluxio 内部异步调度一些较重量级的文件系统操作。将这类操作从 Leading Master 进程内剥离出来,带来两个收益:

  • Leading Alluxio Master 消耗更少资源,能在更短时间内服务更多客户端;
  • 为未来添加更复杂操作提供了可扩展框架。

Job Master 接受上述 Load / Persist / Replicate / Move / Copy 操作请求,并把操作调度到充当 Alluxio 文件系统客户端的Alluxio Job Workers上执行(详见下一节)。在源码中,Job 相关的任务模型(如 LoadJob、PersistJob)定义在 core/server/master/src/main/java/alluxio/master/job/ 目录下。

三、Worker:本地资源与块数据的保管者

3.1 Alluxio Workers

Alluxio Worker 负责管理用户可配置的本地资源(如内存、SSD、HDD),并以**块(block)**为单位存储数据:Worker 在其本地资源中读取已有块或创建新块,从而服务客户端的读写请求。职责边界非常清晰:

  • Worker只负责管理块;
  • 文件到块的映射关系只由 Master 存储(对应 BlockMetadataManager.java 与 DefaultBlockWorker.java 中维护的块存储视图)。

Worker 直接对 UFS 执行数据操作,带来两个重要好处:

  • 从 UFS 读到的数据可以存放在 Worker 中,立即可供其他客户端使用;
  • 客户端可以保持轻量,不必依赖 UFS 连接器。

由于内存容量通常有限,当空间满时 Worker 中的块会被驱逐(evict)。Worker 通过驱逐策略(eviction policy)决定保留哪些数据。源码中,块存储采用分层结构,核心实现为 TieredBlockStore.java;驱逐策略接口 Evictor.java 的默认实现是 LRU(LRUEvictor.java),此外还提供 LRFU 等变体(LRFUAnnotator.java)。有关多级存储(Memory / SSD / HDD 分层)的详细说明,参见多级存储文档。

3.2 Alluxio Job Workers

Alluxio Job Workers 是 Alluxio 文件系统的客户端,负责执行 Job Master 分配的任务:在任意给定的文件系统位置上执行 load、persist、replicate、move 或 copy 操作。

Job Worker 不一定非要与普通 Worker 部署在一起,但官方推荐将两者放在同一物理节点上,以降低调度与数据传输延迟。

四、Client:多语言、多 API 的接入网关

Alluxio Client 为用户提供了与 Alluxio 服务器交互的网关:

  • 它主动与 Leading Master 通信以执行元数据操作;
  • 与 Worker 通信以读写存储在 Alluxio 中的数据。

API 支持矩阵如下:

API 类型说明
原生文件系统 APIJava 原生实现
多语言绑定REST、Go、Python
兼容 APIHDFS API 兼容、Amazon S3 API 兼容

一个非常重要的约束:Alluxio 客户端永远不会直接访问 UFS——数据始终通过 Alluxio Worker 传输。这一点保证了客户端的轻量性,也使得“任何 UFS 支撑任何上层框架”成为可能。

在源码中,客户端与 Master 的元数据交互通过 core/client/fs/src/main/java/alluxio/client/file/FileSystem.java 等入口发起;多语言 REST API 的说明见 docs/en/api/REST-API.md,S3 兼容 API 见 docs/en/api/S3-API.md。

五、数据流(读):四种缓存场景与性能含义

本小节与下一小节基于一个典型 Alluxio 配置来描述读写行为:Alluxio 与计算框架和应用共置部署,持久化存储系统是远程存储集群或云存储。

Alluxio 介于 UFS 与计算框架之间,充当数据读取的缓存层。读路径可划分为以下四种场景。

5.1 本地缓存命中(Local Cache Hit)

当请求的数据位于本地 Alluxio Worker上时,即发生本地缓存命中。典型流程:

  1. 应用通过 Alluxio Client 请求数据;
  2. 客户端向 Master 查询数据的 Worker 位置;
  3. 数据本地可用时,客户端使用short-circuit read(短路读),绕过 Alluxio Worker,直接通过本地文件系统读取文件。

短路读避免了 TCP socket 上的数据传输,是从 Alluxio 读取数据最快的方式。

容器化环境下的注意点:默认情况下,短路读使用本地文件系统操作,要求宽松的权限;当 Worker 与客户端都被容器化时,由于资源记账(resource accounting)不正确,这种默认方式有时不可行。此时 Alluxio 提供基于 domain socket 的短路读:Worker 通过预指定的 domain socket 路径把数据传输给客户端。相关部署说明见在 Docker 上运行 Alluxio。

此外,Alluxio 除了内存还可以管理其他存储介质(SSD、HDD),因此本地数据访问速度会随介质不同而变化,可参考多级存储文档。

5.2 远程缓存命中(Remote Cache Hit)

当请求的数据已存储在 Alluxio 中,但不在客户端的本地 Worker 上时,客户端会从持有数据的远程 Worker 执行远程读。读完数据后,客户端会指示本地 Worker(如果存在)在本地创建一份副本,以便后续对同一数据的读请求可以在本地服务。

远程缓存命中提供网络速度的数据读取。Alluxio优先从远程 Worker 读取,而不是从 UFS 读取,因为 Alluxio Worker 之间的网络速度通常快于 Alluxio Worker 与 UFS 之间的速度。

5.3 缓存未命中(Cache Miss)

当数据在 Alluxio 空间内不可用时,发生缓存未命中,应用必须从 UFS 读取数据:

  1. Alluxio Client 将 UFS 读取委托给一个 Worker(优先本地 Worker);
  2. 该 Worker 从 UFS 读取数据并缓存到本地。

缓存未命中通常造成最大的延迟,因为必须从 UFS 拉取数据。首次读取数据时必然发生缓存未命中。

异步缓存(Asynchronous Caching):当客户端只读取块的某一部分、或以非顺序方式读取块时,客户端会指示 Worker异步缓存完整块。异步缓存不会阻塞客户端,但如果 Alluxio 与 UFS 之间的网络带宽是瓶颈,仍可能影响性能。可通过 Worker 上的alluxio.worker.network.async.cache.manager.threads.max调节影响,文档给出的默认值为8。

源码佐证:该配置对应 PropertyKey.java 中的WORKER_NETWORK_ASYNC_CACHE_MANAGER_THREADS_MAX,实际默认值并非固定 8,而是Math.max(8, 2 * CPU 核心数)——即“至少 8,且不低于 2 倍 CPU 核心数”。官方注释说明,在 Java 8 容器环境中Runtime.availableProcessors()可能只返回 1(不是真实 CPU 数),因此设置 8 作为安全默认下限。该参数的作用域是Scope.WORKER,用于控制数据服务器中异步缓存块的线程数上限。

5.4 缓存跳过(Cache Skip)

可以通过将客户端属性alluxio.user.file.readtype.default设置为NO_CACHE来关闭 Alluxio 缓存。该属性定义于 PropertyKey.java(USER_FILE_READ_TYPE_DEFAULT),其枚举取值(ReadType)还包括CACHE、CACHE_PROMOTE等,用于控制读操作是否缓存以及是否提升到顶层存储介质。

六、数据流(写):四种写入类型与一致性语义

用户可以通过两种途径配置写数据方式:

  • 通过 Alluxio API 直接指定写入类型;
  • 在客户端配置属性alluxio.user.file.writetype.default。

该属性在源码中定义为USER_FILE_WRITE_TYPE_DEFAULT(PropertyKey.java),默认值为ASYNC_THROUGH。下面逐一分析四种写入类型的行为与性能含义。

6.1 仅写入 Alluxio(MUST_CACHE)

  • 客户端只写本地 Alluxio Worker,不写 UFS;
  • 写入过程中,若短路写(short-circuit write)可用,客户端直接写本地 RAM disk 上的文件,绕过 Worker 以避免网络传输;
  • 由于数据未持久化到 UFS,机器宕机或为新写入释放空间时数据可能丢失;
  • 适合可容忍数据丢失的临时数据场景。

6.2 穿透写入 UFS(CACHE_THROUGH)

  • 数据同步写入Alluxio Worker 与 UFS;
  • 客户端把写入委托给本地 Worker,Worker同时写入本地内存与 UFS;
  • 由于 UFS 通常比本地存储写入慢,客户端写入速度会与 UFS 写入速度相当;
  • 在需要数据持久化时推荐使用此类型;同时本地也保留一份副本,后续读取可直接由本地内存服务。

6.3 异步回写 UFS(ASYNC_THROUGH)

  • 数据先同步写入 Alluxio Worker,再在后台持久化到 UFS;
  • 写入速度接近MUST_CACHE,同时仍能持久化数据;
  • 自 Alluxio 2.0 起,ASYNC_THROUGH是默认写入类型。

与ASYNC_THROUGH配套的关键容错属性:alluxio.user.file.replication.durable。该属性为写入完成后、数据持久化到 UFS 之前的 Alluxio 新数据设置目标复制级别,默认值为1。Alluxio 会在后台 persist 完成前维持文件的目标复制级别,之后回收 Alluxio 空间,因此数据只会写入 UFS 一次。源码定义见 PropertyKey.java(USER_FILE_REPLICATION_DURABLE,默认值 1,作用域Scope.CLIENT)。

风险提示:如果以ASYNC_THROUGH写入副本,且所有持有副本的 Worker 在数据持久化前全部崩溃,则会丢失数据。

6.4 仅写入 UFS(THROUGH)

  • 数据同步写入 UFS,不缓存在 Alluxio Worker;
  • 保证写入完成前数据已持久化;
  • 写入速度受限于 UFS 吞吐量。

6.5 数据一致性(Data Consistency)

无论采用何种写入类型,Alluxio 空间内的文件/目录始终是强一致的:所有这些写操作都会先经过 Alluxio Master,在返回成功给客户端/应用之前修改 Alluxio 文件系统。因此,只要对应写操作成功完成,不同 Alluxio 客户端总是能看到最新更新。

但对于同时以 UFS 状态为准的用户或应用,不同写入类型的一致性表现不同:

写入类型UFS 视角的一致性说明
MUST_CACHE从不一致不向 UFS 写数据,Alluxio 空间与 UFS 永远不一致
CACHE_THROUGH取决于 UFS 语义同步写 Alluxio 与 UFS。若 UFS 本身强一致(如 HDFS),且 UFS 无带外更新,则始终一致;若 UFS 最终一致(如 S3),文件可能在 Alluxio 中写入成功、稍后才在 UFS 出现,存在一个“传播窗口”,但 Alluxio 客户端始终查询强一致的 Master,看到的文件系统仍然一致
ASYNC_THROUGH延迟持久化写 Alluxio 即返回应用,数据由 Alluxio 异步传播到 UFS;从用户视角看,文件在 Alluxio 写入成功、稍后在 UFS 才完成持久化
THROUGH元数据仍一致直接写 UFS 而不缓存数据,但 Alluxio 仍然知晓这些文件及其状态,元数据保持一致

七、架构要点速查与实践建议

将全文核心结论汇总如下,便于在部署与调优时快速查阅:

  • 部署位置:为获得最佳性能,Alluxio 应与计算框架共置部署;Job Worker 建议与普通 Worker同节点部署。
  • 数据通路:元数据走 Master,数据走 Worker;客户端永不直连 UFS。
  • 读优化:本地命中走短路读(最快);远程命中优先于 UFS 读;首次访问必然缓存未命中,可调alluxio.worker.network.async.cache.manager.threads.max(默认max(8, 2×CPU核心数))缓解异步缓存对带宽的挤占;需要完全绕过缓存时设置alluxio.user.file.readtype.default=NO_CACHE。
  • 写选择:临时数据用MUST_CACHE;必须持久化且可接受同步写 UFS 的速度用CACHE_THROUGH;默认且兼顾速度与持久化的用ASYNC_THROUGH,并用alluxio.user.file.replication.durable(默认 1)在持久化前维持副本;完全不需缓存时用THROUGH。
  • 一致性:Alluxio 空间内强一致;对 UFS 的一致性取决于写入类型与 UFS 自身的强一致/最终一致语义。

若希望进一步深入,可继续阅读仓库中的相关文档:缓存与多级存储、Job Service 说明、属性完整列表,以及源码侧 DefaultFileSystemMaster.java(Master 文件系统操作核心实现)与 DefaultBlockWorker.java(Worker 块读写核心实现)。

  • 存储
  • 分布式文件系统
  • 缓存
  • 大数据

【免费下载链接】alluxio

Alluxio, data orchestration for analytics and machine learning in the cloud

项目地址:https://gitcode.com/gh_mirrors/al/alluxio
点击查看免费下载

相关推荐

上一篇:G-Helper:华硕笔记本性能管理的轻量化革命
下一篇:【技术解析】嵌入式情感表达系统:为AI硬件注入人性化交互灵魂

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询