Alluxio调研

Alluxio调研

1.简介

Alluxio是世界上第一个用于云分析和AI的开源数据编排技术。弥合了数据驱动应用程序和存储系统之间的差距,使存储层中的数据更接近数据驱动应用程序,并使其易于访问,使应用程序能够通过一个通用接口连接到多个存储系统。Alluxio的内存第一层体系结构使数据访问速度比现有解决方案快几个数量级。
在数据生态系统中,Alluxio介于数据驱动的应用程序(如Apache Spark、Presto、Tensorflow、Apache HBase、Apache Hive或Apache Flink)和各种持久性存储系统(如Amazon S3、Google Cloud storage、OpenStack Swift、HDFS、GlusterFS、IBM Cleversafe、EMC ECS、Ceph、NFS、Minio和阿里巴巴OSS)之间。Alluxio统一了存储在这些不同存储系统中的数据,为其上层数据驱动应用程序提供了统一的客户端API和全局名称空间。

优势
通过简化应用程序访问其数据的方式(无论数据是什么格式或位置),Alluxio 能够帮助克服从数据中提取信息所面临的困难。Alluxio 的优势包括:

  • 内存速度 I/O:Alluxio 能够用作分布式共享缓存服务,这样与 Alluxio 通信的计算应用程序可以透明地缓存频繁访问的数据(尤其是从远程位置),以提供内存级 I/O 吞吐率。此外,Alluxio的层次化存储机制能够充分利用内存、固态硬盘或者磁盘,降低具有弹性扩张特性的数据驱动型应用的成本开销。
  • 简化云存储和对象存储接入:与传统文件系统相比,云存储系统和对象存储系统使用不同的语义,这些语义对性能的影响也不同于传统文件系统。在云存储和对象存储系统上进行常见的文件系统操作(如列出目录和重命名)通常会导致显著的性能开销。当访问云存储中的数据时,应用程序没有节点级数据本地性或跨应用程序缓存。将 Alluxio 与云存储或对象存储一起部署可以缓解这些问题,因为这样将从 Alluxio 中检索读取数据,而不是从底层云存储或对象存储中检索读取。
  • 简化数据管理:Alluxio 提供对多数据源的单点访问。除了连接不同类型的数据源之外,Alluxio 还允许用户同时连接同一存储系统的不同版本,如多个版本的 HDFS,并且无需复杂的系统配置和管理。
  • 应用程序部署简易:Alluxio 管理应用程序和文件或对象存储之间的通信,将应用程序的数据访问请求转换为底层存储接口的请求。Alluxio 与 Hadoop 生态系统兼容,现有的数据分析应用程序,如 Spark 和 MapReduce 程序,无需更改任何代码就能在 Alluxio 上运行。

2.架构

Alluxio可以被分为三个部分:**masters、workers以及clients。**一个典型的设置由一个主服务器、多个备用服务器和多个worker组成。客户端用于通过Spark或MapReduce作业、Alluxio命令行或FUSE层等应用程序与Alluxio服务器通信。

2.1 Master

Alluxio主服务可以部署为一个主master和几个备用master,以实现容错。当主master崩溃时,备用master可以被选为新的主master。

2.1.1 主master(Leading Master)

​ Alluxio中只有一个master进程为主master。主master用于管理全局的元数据。这里面包含文件系统元数据(文件系统节点树)、block元数据(数据块位置)、以及worker的容量元数据(空闲或已占用空间)。Alluxio clients与主master通信用来读取或修改元数据。所有的worker都会定期的向主master发送心跳。主master会在一个分布式的持久化系统上记录所有的文件系统事务,这样可以恢复主master的信息。这组日志被称为journal。

2.1.2 备用master(Standby Masters)

​ 备用master读取主master写入的journal日志,以保持与主master的状态同步。它们会对journal日志写入检查点,用于快速恢复。它们不处理来自Alluxio组件的任何请求。

2.2 Worker

Alluxio的worker用于管理用户为Alluxio定义的本地资源(内存、SSD、HDD)。Alluxio的worker将数据存储为block,并通过在其本地资源上读或者创建新的数据块来响应client请求。Workers只用于管理数据块;文件到数据块的映射存储在master中。Workers在其底层存储上进行数据操作。这带来两个重要的优势:

  1. 从底层存储系统读取的数据能被存储在worker中,这样别的client可以立即使用。
  2. client可以是轻量级的,不依赖于底层存储的连接器,

因为RAM的容量有限,所以当空间满了的时候block会被清理。Workers使用清理策略决定什么数据留在Alluxio中。

2.3 Client

Alluxio Client为用户提供与Alluxio服务交互的网关,client先向leading master请求元数据信息,然后向worker发送读写请求。

  • 向master发起操作文件的RPC请求
  • 从worker读取写入数据
  • client的jar包在编译后的源码文件${ALLUXIO_HOME}/client中
  • client jar 不能单独使用,需要与应用程序在同一个JVM里面,否则会抛异常
  • woker与client在一台机器,会短路读取数据(绕过请求worker的RPC请求,直接用本地文件系统读取woker里数据)

3. Alluxio存储

Alluxio在帮助统一跨各种平台用户数据的同时还有助于为用户提升总体I / O吞吐量。 Alluxio是通过把存储分为两个不同的类别来实现这一目标的。

  • UFS(底层文件存储,也称为底层存储) -该存储空间代表不受Alluxio管理的空间。 UFS存储可能来自外部文件系统,包括如HDFS或S3。 Alluxio可能连接到一个或多个UFS并在一个命名空间中统一呈现这类底层存储。 -通常,UFS存储旨在相当长一段时间持久存储大量数据。
  • Alluxio存储
    • Alluxio做为一个分布式缓存来管理Alluxio workers本地存储,包括内存。这个在用户应用程序与各种底层存储之间的快速数据层带来的是显著提高的I / O性能。
    • Alluxio存储主要用于存储热数据,暂态数据,而不是长期持久数据存储。
    • 每个Alluxio节点要管理的存储量和类型由用户配置决定。
    • 即使数据当前不在Alluxio存储中,通过Alluxio连接的UFS中的文件仍然 对Alluxio客户可见。当客户端尝试读取仅可从UFS获得的文件时数据将被复制到Alluxio存储中。

Alluxio存储通过将数据存储在计算节点内存中来提高性能。 Alluxio存储中的数据可以被复制来形成“热”数据,更易于I/O并行操作和使用。
Alluxio中的数据副本独立于UFS中可能已存在的副本。 Alluxio存储中的数据副本数是由集群活动动态决定的。 由于Alluxio依赖底层文件存储来存储大部分数据, Alluxio不需要保存未使用的数据副本。
Alluxio还支持让系统存储软件可感知的分层存储,使类似L1/L2 CPU缓存一样的数据存储优化成为可能。

3.1 Alluxio存储配置

3.1.1 单层存储

配置Alluxio存储的最简单方法是使用默认的单层模式。在启动时,Alluxio将在每个worker节点上发放一个ramdisk并占用一定比例的系统的总内存。 此ramdisk将用作分配给每个Alluxio worker的唯一存储介质。通过Alluxio配置中的alluxio-site.properties来配置Alluxio存储。对默认值的常见修改是明确设置ramdisk的大小。 例如,设置每个worker的ramdisk大小为16GB:

alluxio.worker.ramdisk.size=16GB
3.1.2 多层存储

通常建议异构存储介质也使用单个存储层。 在特定环境中,工作负载将受益于基于I/O速度存储介质明确排序。 Alluxio假定根据按I/O性能从高到低来对多层存储进行排序。 例如,用户经常指定以下层:

  • MEM(内存)
  • SSD(固态存储)
  • HDD(硬盘存储)
3.1.3 写数据

用户写新的数据块时,默认情况下会将其写入顶层存储。如果顶层没有足够的可用空间, 则会尝试下一层存储。如果在所有层上均未找到存储空间,因Alluxio的设计是易失性存储,Alluxio会释放空间来存储新写入的数据块。 根据块注释策略,空间释放操作会从work中释放数据块。 块注释政策。 如果空间释放操作无法释放新空间,则写数据将失败。

**注意:**新的释放空间模型是同步模式并会代表要求为其要写入的数据块释放新空白存储空间的客户端来执行释放空间操作。 在块注释策略的帮助下,同步模式释放空间不会引起性能下降,因为总有已排序的数据块列表可用。 然而,可以将alluxio.worker.tieredstore.free.ahead.bytes(默认值:0)配置为每次释放超过释放空间请求所需字节数来保证有多余的已释放空间满足写数据需求。

用户还可以通过configuration settings来指定写入数据层。

3.1.4 读取数据

如果数据已经存在于Alluxio中,则客户端将简单地从已存储的数据块读取数据。 如果将Alluxio配置为多层,则不一定是从顶层读取数据块, 因为数据可能已经透明地挪到更低的存储层。

ReadType.CACHE_PROMOTE读取数据将在从worker读取数据前尝试首先将数据块挪到 顶层存储。也可以将其用作为一种数据管理策略 明确地将热数据移动到更高层存储读取。

3.1.5 配置分层存储

可以使用以下方式在Alluxio中启用分层存储 配置参数。 为Alluxio指定额外存储层,使用以下配置参数:

alluxio.worker.tieredstore.levels
alluxio.worker.tieredstore.level{x}.alias
alluxio.worker.tieredstore.level{x}.dirs.quota
alluxio.worker.tieredstore.level{x}.dirs.path
alluxio.worker.tieredstore.level{x}.dirs.mediumtype

例如,如果计划将Alluxio配置为具有两层存储,内存和硬盘存储, 可以使用类似于以下的配置:

# configure 2 tiers in Alluxio
alluxio.worker.tieredstore.levels=2
# the first (top) tier to be a memory tier
alluxio.worker.tieredstore.level0.alias=MEM
# defined `/mnt/ramdisk` to be the file path to the first tier
alluxio.worker.tieredstore.level0.dirs.path=/mnt/ramdisk
# defined MEM to be the medium type of the ramdisk directory
alluxio.worker.tieredstore.level0.dirs.mediumtype=MEM
# set the quota for the ramdisk to be `100GB`
alluxio.worker.tieredstore.level0.dirs.quota=100GB
# configure the second tier to be a hard disk tier
alluxio.worker.tieredstore.level1.alias=HDD
# configured 3 separate file paths for the second tier
alluxio.worker.tieredstore.level1.dirs.path=/mnt/hdd1,/mnt/hdd2,/mnt/hdd3
# defined HDD to be the medium type of the second tier
alluxio.worker.tieredstore.level1.dirs.mediumtype=HDD,HDD,HDD
# define the quota for each of the 3 file paths of the second tier
alluxio.worker.tieredstore.level1.dirs.quota=2TB,5TB,500GB

可配置层数没有限制 但是每个层都必须使用唯一的别名进行标识。 典型的配置将具有三层,分别是内存,SSD和HDD。 要在HDD层中使用多个硬盘存储,需要在配置alluxio.worker.tieredstore.level{x}.dirs.path时指定多个路径。

3.1.6 Alluxio 数据生命周期

用户需要理解以下概念,以正确利用可用资源:

  • free:释放数据是指从Alluxio缓存中删除数据,而不是从底层UFS中删除数据。 释放操作后,数据仍然可供用户使用,但对Alluxio释放文件后尝试访问该文件 的客户端来讲性能可能会降低。
  • load:加载数据意味着将其从UFS复制到Alluxio缓存中。如果Alluxio使用 基于内存的存储,加载后用户可能会看到I/O性能的提高。
  • persist:持久数据是指将Alluxio存储中可能被修改过或未被修改过的数据写回UFS。 通过将数据写回到UFS,可以保证如果Alluxio节点发生故障数据还是可恢复的。
  • TTL(Time to Live):TTL属性设置文件和目录的生存时间,以 在数据超过其生存时间时将它们从Alluxio空间中删除。还可以配置 TTL来删除存储在UFS中的相应数据。

明白以上概念之后可以通过命令行的形式去进行释放、加载、持久化保留数据操作。

## 释放数据:从Alluxio存储中删除位于给定路径的数据。如果数据是持久存储到UFS的则仍然可以访问该数据。
$ ./bin/alluxio fs free ${PATH_TO_UNUSED_DATA}

## 加载数据到 Alluxio 存储中,如果数据已经在UFS中,使用 alluxio fs load,要从本地文件系统加载数据,使用命令 alluxio fs copyFromLocal。 这只会将文件加载到Alluxio存储中,而不会将数据持久保存到UFS中。 将写入类型设置为MUST_CACHE写入类型将不会将数据持久保存到UFS, 而设置为CACHE和CACHE_THROUGH将会持久化保存。不建议手动加载数据,因为,当首次使用文件时Alluxio会自动将数据加载到Alluxio缓存中。
$ ./bin/alluxio fs load ${PATH_TO_FILE}

## 在Alluxio中持久化保留数据,命令alluxio fs persist 允许用户将数据从Alluxio缓存推送到UFS。
$ ./bin/alluxio fs persist ${PATH_TO_FILE}

设置生存时间(TTL)

Alluxio支持命名空间中每个文件和目录的”生存时间(TTL)”设置。可用于有效地管理Alluxio缓存,尤其是在严格保证数据访问模式的环境中。例如,如果对上一周提取数据进行分析, 则TTL功能可用于明确刷新旧数据,从而为新文件释放缓存空间。

Alluxio具有与每个文件或目录关联的TTL属性。这些属性将保存为 日志的一部分,所以集群重新后也能持久保持。活跃master节点负责 当Alluxio提供服务时将元数据保存在内存中。在内部,master运行一个后台线程,该线程定期检查文件是否已达到其TTL到期时间。

注意,后台线程按配置的间隔运行,默认设置为一个小时。 在检查后立即达到其TTL期限的数据不会马上删除, 而是等到一个小时后下一个检查间隔才会被删除。

如将间隔设置为10分钟,在alluxio-site.properties添加以下配置:

alluxio.master.ttl.checker.interval=10m
3.1.7 在Alluxio中管理数据复制

被动复制

与许多分布式文件系统一样,Alluxio中的每个文件都包含一个或多个分布在集群中存储的存储块。默认情况下,Alluxio可以根据工作负载和存储容量自动调整不同块的复制级别。例如,当更多的客户以类型CACHECACHE_PROMOTE请求来读取此块时Alluxio可能会创建此特定块更多副本。当较少使用现有副本时,Alluxio可能会删除一些不常用现有副本 来为经常访问的数据征回空间(块注释策略)。 在同一文件中不同的块可能根据访问频率不同而具有不同数量副本。

默认情况下,此复制或征回决定以及相应的数据传输 对访问存储在Alluxio中数据的用户和应用程序完全透明。

主动复制

除了动态复制调整之外,Alluxio还提供API和命令行 界面供用户明确设置文件的复制级别目标范围。 尤其是,用户可以在Alluxio中为文件配置以下两个属性:

  1. alluxio.user.file.replication.min是此文件的最小副本数。 默认值为0,即在默认情况下,Alluxio可能会在文件变冷后从Alluxio管理空间完全删除该文件。 通过将此属性设置为正整数,Alluxio 将定期检查此文件中所有块的复制级别。当某些块 的复制数不足时,Alluxio不会删除这些块中的任何一个,而是主动创建更多 副本以恢复其复制级别。
  2. alluxio.user.file.replication.max是最大副本数。一旦文件该属性 设置为正整数,Alluxio将检查复制级别并删除多余的 副本。将此属性设置为-1为不设上限(默认情况),设置为0以防止 在Alluxio中存储此文件的任何数据。注意,alluxio.user.file.replication.max的值 必须不少于alluxio.user.file.replication.min

3.2 统一命名空间

Alluxio通过使用透明的命名机制和挂载API来实现有效的跨不同底层存储系统的数据管理。

3.2.1 统一命名空间

Alluxio提供的主要好处之一是为应用程序提供统一命名空间。 通过统一命名空间的抽象,应用程序可以通过统一命名空间和接口来访问多个独立的存储系统。 与其与每个独立的存储系统进行通信,应用程序可以只连接到Alluxio并委托Alluxio来与不同的底层存储通信。

master配置属性alluxio.master.mount.table.root.ufs指定的目录挂载到Alluxio命名空间根目录,该目录代表Alluxio 的”primary storage”。在此基础上,用户可以通过挂载API添加和删除数据源。

void mount(AlluxioURI alluxioPath, AlluxioURI ufsPath);
void mount(AlluxioURI alluxioPath, AlluxioURI ufsPath, MountOptions options);
void unmount(AlluxioURI path);
void unmount(AlluxioURI path, UnmountOptions options);

例如,可以通过以下方式将一个新的S3存储桶挂载到Data目录中

mount(new AlluxioURI("alluxio://host:port/Data"), new AlluxioURI("s3://bucket/directory"));
3.2.2 UFS命名空间

除了Alluxio提供的统一命名空间之外,每个已挂载的基础文件系统 在Alluxio命名空间中有自己的命名空间; 称为UFS命名空间。 如果在没有通过Alluxio的情况下更改了UFS名称空间中的文件, UFS命名空间和Alluxio命名空间可能不同步的情况。 发生这种情况时,需要执行UFS元数据同步操作才能重新使两个名称空间同步。

3.3 透明命名机制

透明命名机制保证了Alluxio和底层存储系统命名空间身份一致性。

当用户在Alluxio命名空间创建对象时,可以选择这些对象是否要在底层存储系统中持久化。对于需要持久化的对象, Alluxio会保存底层存储系统存储这些对象的路径。例如,一个用户在根目录下创建了一个Users目录及AliceBob两个子目录,底层存储系统也会保存相同的目录结构和命名。类似地,当用户在 Alluxio命名空间中对一个持久化的对象进行重命名或者删除操作时,底层存储系统中也会对其执行相同的重命名或删除操作。

Alluxio能够透明发现底层存储系统中并非通过Alluxio创建的内容。例如,底层存储系统中包含一个Data文件夹, 其中包含ReportsSales文件,都不是通过Alluxio创建的,当它们第一次被访问时,如用户请求打开文 件,Alluxio会自动加载这些对象的元数据。然而在该过程中Alluxio不会加载文件内容数据,若要将其内容加载到Alluxio, 可以用FileInStream来读数据,或者通过Alluxio Shell中的load命令。

3.4 挂载底层存储系统

定义Alluxio命名空间和UFS命名空间之间的关联是通过将底层存储系统挂载到Alluxio文件系统命名空间的机制完成的。 在Alluxio中挂载底层存储与在Linux文件系统中挂载一个卷类似。 mount命令将UFS挂载到Alluxio命名空间中文件系统树。

根挂载点

Alluxio命名空间的根挂载点是在masters上’conf/alluxio-site.properties’中配置的。 下一行是一个配置样例,一个HDFS路径挂载到 Alluxio命名空间根目录。

alluxio.master.mount.table.root.ufs=hdfs://HDFS_HOSTNAME:8020

3.5 Alluxio和UFS命名空间之间的关系

通过Alluxio访问UFS文件的与直接通过UFS访问文件的相同。 如果UFS根目录是s3://bucket/data,则列出alluxio:///下内容应该与列出s3://bucket/data相同。 在alluxio:///file上运行cat的结果应与在s3://bucket/data/file上运行cat的结果相同。

Alluxio按需从UFS加载元数据。 在上面的示例中,Alluxio在启动时并没有有关s3://bucket/data/file的信息。 直到当用户试图列出alluxio:///或尝试使用cat alluxio:///file时,才发现该文件。 这样好处是可以防止在安装新的UFS时进行不必要的文件发现工作。

默认情况下,* Alluxio预期所有对底层文件系统修改都是通过Alluxio 来进行的*。 这样Alluxio只需扫描每个UFS目录一次,从而在UFS元数据操作很慢情况下显著提高性能。 当出现在Alluxio之外对UFS进行更改的情况下, 就需要用元数据同步功能用于同步两个命名空间。

UFS元数据同步

当Alluxio扫描UFS目录并加载其子目录元数据时, 它将创建元数据的副本,以便将来无需再从UFS加载。 元数据的缓存副本将根据 alluxio.user.file.metadata.sync.interval客户端属性配置的间隔段刷新。 此属性适用于客户端操作。 例如,如果客户执行一个命令基于间隔设置为一分钟的配置, 如果最后一次刷新是在一分钟之前,则相关元数据将据UFS刷新。 设值为0表示针对每个操作都会进行实时元数据同步, 而默认值-1表示在初始加载后不会再重新同步元数据。

低间隔值使Alluxio客户端可以快速发现对UFS的外部修改, 但由于导致调用UFS的次数增加,因此是以降低性能为代价的。

元数据同步会保留每个UFS文件的指纹记录,以便Alluxio可以在文件更改时做出相应更新。 指纹记录包括诸如文件大小和上次修改时间之类的信息。 如果在UFS中修改了文件,Alluxio将通过指纹检测到该修改,释放现有文件 元数据,然后重新加载更新文件的元数据。 如果在UFS中添加或删除了文件,Alluxio还将更新对其命名空间中的元数据做出相应刷新。

3.6 Alluxio读取

3.6.1 本地缓存命中

本地缓存命中发生在请求数据位于本地Alluxio worker。如果一个应用通过Alluxio client请求数据,client会向Alluxio master请求数据所在的worker。如果数据在本地可用,Alluxio client使用“短路”读取来绕过Alluxio worker,并直接通过本地文件系统读取文件。短路读取避免通过TCP套接字传输数据,并提供数据的直接访问。
还要注意,Alluxio除了内存之外还可以管理其他存储介质(例如SSD、HDD),因此本地数据访问速度可能会因本地存储介质的不同而有所不同。

3.6.2 远程缓存命中

当请求的数据存储在Alluxio中,而不是存储在client的本地worker上时,client将对具有数据的worker进行远程读取。client完成读取后,会要求本地的worker(如果存在)创建一个copy,这样以后读取的时候可以在本地读取相同的数据。远程缓存击中提供了网络级别速度的数据读取。Alluxio优先从远程worker读取数据,而不是从底层存储,因为Alluxio worker间的速度一般会快过Alluxio workers和底层存储的速度。

3.6.3 缓存Miss

如果数据在Alluxio中找不到,则会发生缓存丢失,应用将不得不从底层存储读取数据。Alluxio client会将数据读取请求委托给worker(有限本地worker)。这个worker会从底层存储读取数据并缓存。缓存丢失通常会导致最大的延迟,因为数据必须从底层存储获取。
当client只读取块的一部分或不按照顺序读取块时,client将指示worker异步缓存整个块。异步缓存不会阻塞client,但是如果Alluxio和底层存储系统之间的网络带宽是瓶颈,那么异步缓存仍然可能影响性能。

3.7 Alluxio 写

用户可以通过选择不同的写类型来配置应该如何写数据。写类型可以通过Alluxio API设置,也可以通过在客户机中配置属性Alluxio .user.file.writetype.default来设置,不同写类型的行为以及对应用程序的性能影响也不同。

3.7.1 只写入到Alluxion(MAST_CACHE)

当写类型设置为MUST_CACHE,Alluxio client将数据写入本地Alluxio worker,而不会写入到底层存储。如果“短路”写可用,Alluxio client直接写入到本地RAM的文件,绕过Alluxio worker,避免网络传输。由于数据没有持久存储在under storage中,因此如果机器崩溃或需要释放数据以进行更新的写操作,数据可能会丢失。当可以容忍数据丢失时,MUST_CACHE设置对于写临时数据非常有用。

3.7.2 写到UFS(CACHE_THROUGH)

使用CACHE_THROUGH写类型,数据被同步地写到一个Alluxio worker和下一个底层存储。Alluxio client将写操作委托给本地worker,而worker同时将对本地内存和底层存储进行写操作。由于底层存储的写入速度通常比本地存储慢,所以client的写入速度将与底层存储的速度相匹配。当需要数据持久化时,建议使用CACHE_THROUGH写类型。在本地还存了一份副本,以便可以直接从本地内存中读取数据。

3.7.3 写回UFS(ASYNC_THROUGH)

Alluxio提供了一个叫做ASYNC_THROUGH的写类型。数据被同步地写入到一个Alluxio worker,并异步地写入到底层存储。ASYNC_THROUGH可以在持久化数据的同时以内存速度提供数据写入。

你可能感兴趣的:(大数据)