Alluxio性能调优

2023-04-03 09:37:44 浏览数 (1)

本文档介绍了各种调优 Alluxio 性能的技巧和配置。

常见性能问题

以下是在调整性能时用于解决常见问题的清单:

所有节点都在工作吗?

检查 Alluxio 集群是否健康。 您可以在 http://:19999 检查 web 用户界面,看看是否可以从浏览器访问 master。 类似地,可以通过单击 Alluxio master UI 的“workers”选项卡或导航到 http://:30000/ 来访问 workers 或者,运行 bin/alluxio fsadmin report 从控制台收集类似信息。 Web 界面和命令行输出都包含用于验证是否有任何节点停止服务以及最后已知心跳时间的指标。

短路操作是否有效?

如果计算应用程序与 Alluxio worker 在同一地点运行,请检查该应用程序是否正在与其本地 Alluxio worker 执行短路读写。 在应用程序运行时监控 cluster.BytesReadRemoteThroughput 和 cluster.BytesReadLocalThroughput 的指标值(指标可以通过 alluxio fsadmin 报告指标查看)。 如果本地吞吐量为零或明显低于远程 alluxio 读取吞吐量,则计算应用程序可能没有与本地 Alluxio worker 交互。 Alluxio 客户端使用主机名匹配来确定本地 Alluxio worker 是否存在。 检查客户端和工作人员是否使用相同的主机名字符串。 配置 alluxio.user.hostname 和 alluxio.worker.hostname 分别设置客户端和工作主机名。

注意:为了检索短路 IO 的指标,需要通过在 alluxio-site.properties 或相应的应用程序配置中设置 alluxio.user.metrics.collection.enabled=true 来启用客户端指标收集。

数据是否在 Alluxio workers 之间均匀分布?

默认情况下,Alluxio 客户端将使用 LocalFirstPolicy 将数据写入其本地 Alluxio worker。 这对于同时从多个节点写入数据的应用程序是有效的。 在所有数据都从单个节点写入的场景中,它的本地 worker 将被填满,而剩余的 worker 则为空。 请参阅此页面以讨论不同的位置策略以及如何配置它们。

用户日志中是否有包含“DeadlineExceededException”的错误消息?

这可能表明客户端在与 Alluxio worker 通信时超时。 要增加超时,请配置 alluxio.user.streaming.data.timeout,默认值为 30 秒。

如果写操作超时,配置alluxio.user.streaming.writer.close.timeout,默认为30m。 这在将大文件写入具有慢速网络连接的对象存储时尤为重要。 关闭文件后会立即上传整个对象。

还有一些罕见的情况,在基于 linux NUMA 的系统上,Alluxio worker 可能会以零星的方式运行,导致由于内核的 vm.zone_reclaim_mode 行为而导致暂停或不可用。 对于 NUMA 系统,建议通过在 /etc/sysctl.conf 或 Alluxio worker 上的类似配置文件中设置 vm.zone_reclaim_mode=0 来禁用区域回收。

是否有频繁的 JVM GC 事件?

master 或 worker JVM 上频繁且长时间的 GC 操作会大大减慢进程。 这可以通过为 GC 事件添加日志记录来识别; 将以下内容附加到 conf/allulxio-env.sh:

代码语言:javascript复制
ALLUXIO_JAVA_OPTS=" -XX: PrintGCDetails -XX: PrintTenuringDistribution -XX: PrintGCTimeStamps"

重启 Alluxio 服务器并检查 {ALLUXIO_HOME}/logs/master.out 或 {ALLUXIO_HOME}/logs/worker.out 中的输出,分别用于 master 和 worker。

还要检查指标系统,以便更好地了解 Alluxio 服务的执行情况。

一般调整

JVM监控

为了检测长时间的 GC 暂停,Alluxio 管理员可以为 master 设置 alluxio.master.jvm.monitor.enabled=true 或为 worker 设置 alluxio.worker.jvm.monitor.enabled=true。 它们在 Alluxio 2.4.0 及更新版本中默认启用。 这将触发一个监视线程,该线程定期测量两次 GC 暂停之间的延迟。 较长的延迟可能表明该进程正在花费大量时间进行垃圾收集或执行其他 JVM 安全点操作。 以下参数调整监视线程的行为:

Property

Default

Description

alluxio.jvm.monitor.warn.threshold

10sec

Delay required to log at WARN level

alluxio.jvm.monitor.info.threshold

1sec

Delay required to log at INFO level

alluxio.jvm.monitor.sleep.interval

1sec

The time for the JVM monitor thread to sleep

提高冷读性能

当应用程序直接从 UFS 读取时,多个客户端可能会尝试同时读取输入数据的同一部分。 例如,在 SparkSQL 查询开始时,所有 Spark 执行程序都将读取相同的parquet footer metadata。 这可能会导致 Alluxio 在每个节点上缓存相同的块,这会浪费 UFS 带宽和 Alluxio 存储容量。

避免这种情况的一种方法是通过指定以下配置属性来应用确定性哈希策略:

代码语言:javascript复制
alluxio.user.ufs.block.read.location.policy=alluxio.client.block.policy.DeterministicHashPolicy

这将导致 Alluxio 选择一个随机的 worker 从 UFS 读取给定的块,并导致任何其他请求相同块的客户端改为从选定的 worker 读取。 要增加允许同时从 UFS 读取同一块的工作线程数,请将以下配置属性更新为大于默认值 1 的值:

代码语言:javascript复制
alluxio.user.ufs.block.read.location.policy.deterministic.hash.shards=3

将其设置为 3 意味着将有 3 个 Alluxio worker 负责读取特定的 UFS 块,所有客户端将从这 3 个 worker 中的一个读取该 UFS 块。

缓存命中率

在 Alluxio 2.6 之后的版本中,我们包含了一个额外的指标 Cluster.CacheHitRate,它表示缓存命中率。 这里的缓存命中率是指Alluxio存储中已访问的数据所占的百分比。 如果命中率下降,请考虑增加高速缓存大小或检查最近的访问模式以了解为什么数据访问会转到 uf。

Master调优

Journal性能调优

Property

Default

Description

alluxio.master.journal.flush.batch.time

5ms

Time to wait for batching journal writes

alluxio.master.journal.flush.timeout

5min

The amount of time to retry journal writes before giving up and shutting down the master

增加批处理时间可以提高更新/写入 RPC 的主吞吐量,但也可能增加这些更新/写入 RPC 的延迟。 为 alluxio.master.journal.flush.timeout 设置更大的超时值有助于在日志写入位置长时间不可用时保持 master 活动。

嵌入的Journal写入性能

使用嵌入式日志时,在提交 Alluxio 中的每个更新操作之前,必须在所有 master 的预写日志(WAL)中写入与该操作对应的日志条目并将其刷新到磁盘。 如果 WAL 位于其他进程经常访问的磁盘上,则 Alluxio 中更新操作的性能可能会受到影响。 例如,如果 WAL 与基本日志记录操作共享一个磁盘,则可能会出现这种情况。

为了获得最佳性能,将磁盘专用于日志可能很有用。 日记文件夹的位置可以通过属性键 alluxio.master.journal.folder 来设置。

或者,通过将属性键 alluxio.master.embedded.journal.unsafe.flush.enabled 设置为 true,操作将在不等待刷新到磁盘完成的情况下提交。

警告:如果一半或更多主节点发生故障,启用此属性可能会导致 Alluxio 主节点上的元数据丢失。

Journal垃圾回收

Property

Default

Description

alluxio.master.journal.checkpoint.period.entries

2000000

The number of journal entries to write before creating a new journal checkpoint

日志检查点的创建成本很高,但通过减少主服务器在启动期间需要处理的日志条目的数量来减少启动时间。 如果启动时间太长,请考虑降低此值,以便更频繁地发生检查点。

UFS 块位置缓存

Alluxio 客户端提供块位置,类似于 HDFS 客户端。 如果文件块未存储在 Alluxio 中,Alluxio 将查询 UFS 以获取其块位置,这需要额外的 RPC。 通过缓存 UFS 块位置可以避免这种额外开销。 这个缓存的大小由 alluxio.master.ufs.block.location.cache.capacity 的值决定。 如果该值设置为 0,则禁用缓存。

增加缓存大小将允许 Alluxio master 存储更多的 UFS 块位置,从而为不在 Alluxio 存储中的文件带来更大的元数据吞吐量; 但是请注意,增加此值将导致更高的 JVM 堆利用率。

UFS 路径缓存

当 Alluxio 将 UFS 挂载到 Alluxio 命名空间中的路径时,Alluxio master 会在其命名空间上维护元数据。 UFS 元数据仅在客户端访问路径时被拉取。 当客户端访问 Alluxio 中不存在的路径时,Alluxio 可能会查询 UFS 以加载 UFS 元数据。 加载缺失路径有 3 个选项:NEVER、ONCE、ALWAYS。

ALWAYS 将始终检查 UFS 以获取给定路径的最新状态,ONCE 将使用仅扫描每个目录一次的默认行为,并且 NEVER 将永远不会查询 UFS,从而完全阻止 Alluxio 扫描新文件。

Alluxio master 维护一个缓存来跟踪之前加载过哪些 UFS 路径,以近似于 ONCE 行为。 参数 alluxio.master.ufs.path.cache.capacity 控制要存储在缓存中的路径数。 较大的缓存大小将消耗更多内存,但会更好地接近 ONCE 行为。 Alluxio master 异步维护 UFS 路径缓存。 Alluxio 使用线程池异步处理路径,其大小由 alluxio.master.ufs.path.cache.threads 控制。 增加线程数可以减少 UFS 路径缓存的陈旧性,但可能会通过增加 Alluxio master 上的工作以及消耗 UFS 带宽来影响性能。 如果将其设置为 0,则禁用缓存并且 ONCE 设置的行为与 ALWAYS 设置相同。

元数据同步

如果 UFS 上的内容在没有经过 Alluxio 的情况下被修改,Alluxio 需要将其元数据与 UFS 同步以反映 Alluxio 命名空间中的这些更改。 元数据同步的成本与正在同步的目录中的文件数量成线性关系。 如果元数据同步操作在大型目录上频繁发生,则可以分配更多线程来加速此过程。 两个配置在这里是相关的。

alluxio.master.metadata.sync.concurrency.level 控制在单个同步操作中使用的并发性。 在主节点上将其调整为 1 到 2 倍的虚拟核心数,以加快元数据同步的速度。

alluxio.master.metadata.sync.executor.pool.size 控制执行同步操作的线程数。 这默认为系统中的虚拟核心数,但如果我们期望有许多并发同步操作,可以将虚拟核心数调整为 2 倍或 4 倍。

worker调优

块读取线程池大小

alluxio.worker.network.block.reader.threads.max 属性配置用于处理块读取请求的最大线程数。 如果您在读取文件时遇到连接被拒绝错误,则应增加此值。

异步块缓存

当 worker 从块的一部分请求数据时,worker 会读取请求的数据,并立即将请求的数据返回给客户端。 worker 将异步地继续读取块的剩余部分,而不会阻塞客户端请求。

用于完成读取部分块的异步线程数由 alluxio.worker.network.async.cache.manager.threads.max 属性设置。 当需要同时异步缓存大量数据时,增加此值可能有助于处理更高的工作负载。 这在缓存的文件相对较小 (> 10MB) 的情况下最有效。 但是,请谨慎增加此数量,因为随着数量的增加,它会消耗工作节点上更多的 CPU 资源。

另一个与异步缓存相关的重要属性是 alluxio.worker.network.async.cache.manager.queue.max。 当异步缓存流量突然激增,Alluxio 无法再容纳队列中的所有请求时,它会开始丢弃一些异步缓存请求,因为异步缓存严格来说是一种性能优化。 如果 Alluxio 丢弃了许多异步缓存请求,请增加此值。 监控 Worker.AsyncCacheRequests 和 Worker.AsyncCacheSucceededBlocks 以查看缓存的块数是否符合预期。

UFS InStream 缓存大小

Alluxio worker 使用由参数 alluxio.worker.ufs.instream.cache.max.size 控制的 UFS 开放输入流池。 较大的数字会减少向 UFS 打开新流的开销。 但是,它也会给 UFS 带来更大的负载。 HDFS作为UFS,该参数根据dfs.datanode.handler.count设置。 例如,如果 Alluxio worker 的数量与 HDFS 数据节点的数量相匹配,则在假设工作负载 均匀分布在 Alluxio worker 上。

作业服务调优

工作服务能力

作业服务限制当前运行的作业总数以控制其资源使用。 请注意,单个 CLI 命令(例如 distributedLoad)可以触发创建多个作业,每个文件一个。 如果作业倾向于大批量创建,请考虑将 alluxio.job.master.job.capacity 增加到比默认 100K 更大的值。 如果作业服务容量不足,作业提交将被拒绝。

有一些配置可以控制 DistributedLoad 等命令的容量和并行度。 有关详细信息,请参阅 CLI 文档。

作业服务吞吐量

当有很多并发作业在运行,并且需要更高的吞吐量时,可以考虑增加 alluxio.job.worker.threadpool.size 配置。 这允许每个作业工作者运行更多的并行线程。 缺点是它会竞争工作机器上的资源。 如果大多数作业仅在非高峰时段运行,建议使用 2 倍的虚拟核心数;如果作业在所有时间运行,建议使用 1/2 到 1 倍的虚拟核心数。

客户端调优

被动缓存

被动缓存会导致 Alluxio worker 缓存另一个已缓存在单独 worker 上的数据副本。 通过设置配置属性禁用被动缓存:

代码语言:javascript复制
alluxio.user.file.passive.cache.enabled=false

启用后,相同的数据块可用于多个工作人员,从而减少了唯一数据的可用存储容量。 禁用被动缓存对于没有位置概念且数据集比单个 Alluxio worker 的容量大的工作负载很重要。

计算框架的优化提交

通过 Alluxio 使用优化的提交运行可以使计算作业的整体运行时间提高一个数量级。

利用 Hadoop MapReduce 提交者模式(即 Spark、Hive)的计算框架并不是为与提供缓慢重命名的存储(主要是对象存储)交互而设计的。 这在使用 S3 上的 Spark 或 Ceph 上的 Hive 等堆栈时最为常见。

Hadoop MapReduce 提交者利用重命名将数据从暂存目录(通常是 output/_temporary)提交到最终输出目录(即输出)。 使用 CACHE_THROUGH 或 THROUGH 写入数据时,此协议转换为以下内容:

  1. 将临时数据写入 Alluxio 和 Object Store
    1. 数据快速写入Alluxio存储
    2. 数据缓慢写入对象存储
  2. 将临时数据重命名为最终输出位置
    1. 在 Alluxio 中重命名很快,因为它是一个元数据操作
    2. 对象存储中的重命名很慢,因为它是复制和删除
  3. 作业完成给用户

当运行具有大量或大输出文件的作业时,对象存储的开销支配着工作负载的运行时间。

Alluxio 提供了一种方法,只产生在关键路径上将数据写入 Alluxio(快速)的成本。 用户应该在计算框架中配置以下 Alluxio 属性:

代码语言:javascript复制
# Writes data only to Alluxio before returning a successful write
alluxio.user.file.writetype.default=ASYNC_THROUGH
# Does not persist the data automatically to the underlying storage, this is important because
# only the final committed data is necessary to persist
alluxio.user.file.persistence.initial.wait.time=-1
# Hints that Alluxio should treat renaming as committing data and trigger a persist operation
alluxio.user.file.persist.on.rename=true
# Determines the number of copies in Alluxio when files are not yet persisted, increase this to
# a larger number to ensure fault tolerance in case of Alluxio worker failures
alluxio.user.file.replication.durable=1
# Blacklists persisting files which contain the string "_temporary" anywhere in their path
alluxio.master.persistence.blacklist=_temporary

使用此配置,协议将转换为以下内容:

  1. 将临时数据写入 Alluxio
    1. 数据快速写入Alluxio存储
  2. 将临时数据重命名为最终输出位置
    1. 在 Alluxio 中重命名很快,因为它是一个元数据操作
    2. 异步持久化任务启动
  3. 作业完成给用户
  4. 将最终输出异步写入对象存储
    1. 数据缓慢写入对象存储

总的来说,避免了对象存储中的复制和删除操作,并且将写入对象存储的缓慢部分移出了关键路径。

在某些情况下,计算框架的提交协议涉及多个重命名或临时文件。 Alluxio 提供了一种机制,通过将与临时文件关联的一组字符串列入黑名单来防止文件被持久化。 任何具有任何已配置字符串作为其路径一部分的文件都不会被考虑保留。

例如,如果

代码语言:javascript复制
alluxio.master.persistence.blacklist=.staging,_temporary

/data/_temporary/part-00001、/data/temporary.staging 等文件不会被考虑保留。 这是可行的,因为最终这些临时文件将被删除或重命名为永久文件。 因为设置了 alluxio.user.file.persist.on.rename=true ,文件在重命名时将再次考虑持久化。 请注意,重命名后保留对目录和文件都有效 – 如果使用重命名后保留选项重命名顶级目录,则顶级目录下的任何文件都将被视为持久性。

常见性能问题

本部分列出了一组常见的性能问题以及可能的原因和诊断步骤。 当您遇到性能问题时,这是一个很好的起点,如果您的症状与此处描述的症状相符,可能会很快得到答案。

慢查询/整体性能

观察到异常大的 Cluster.BytesReadUfs 指标。

当 Alluxio 将数据转到 UFS 时,它会牺牲性能并产生额外的成本。 这通常是最大的危险信号。

原因:这有很多可能的原因。 这是一个部分列表,用于检查它是否是问题的根本原因。

  1. 缓存空间不足
代码语言:txt复制
1. 检查驱逐统计数据 Worker.BlocksEvictionRate
2. 检查worker容量使用命令alluxio fsadmin report capacity访问模式真的是对抗性的
代码语言:txt复制
1. 检查驱逐统计数据 Worker.BlocksEvictionRate固定的文件和目录太多
代码语言:txt复制
1. 检查固定文件同一块的副本太多
代码语言:txt复制
1. 减少文件的 maxReplication异步缓存请求被丢弃或进展太慢
代码语言:txt复制
1. 调查异步缓存统计信息
2. Worker.AsyncCacheRequests vs Worker.AsyncCacheCompleted 如果需要,增加alluxio.worker.network.async.cache.manager.threads.max 如果请求被丢弃,增加alluxio.worker.network.async.cache.manager.queue.max不平衡的workers ,您所有的数据访问可能都由一小组工作人员进行。 使用 webui 或 alluxio fsadmin 命令检查 worker 容量。

对 Alluxio 的读/写速度慢

这由 Alluxio 中的读/写吞吐量指标指示,或者通常由用户报告。 原因:

  1. 客户端rpc线程设置
    1. alluxio.user.network.netty.worker.threads
  2. worker rpc 线程最大值
代码语言:txt复制
1.  alluxio.worker.network.block.reader.threads.max
代码语言:txt复制
2.  alluxio.worker.network.block.writer.threads.max 这两个设置控制了读写线程的并发级别。
代码语言:txt复制
3.  alluxio.worker.remote.io.slow.threshold 此设置控制远程 io 何时被视为缓慢。 如果远程 io 比这慢,请检查 worker 日志中的消息
  1. worker超时
    1. 检查客户端日志是否有任何工人超时并检查工人日志是否有任何死亡工人

元数据同步缓慢

可能的原因:

  1. 同步频率太高,文件太多
    1. alluxio.user.file.metadata.sync.interval控制元数据同步的频率。频繁的同步可能会导致额外的ufs调用,并降低系统性能。
    2. 同步缓慢也可能是由于没有足够的同步线程来调整
      1. allixio.master.metadata.sync.concurrenty.level
      2. allixio.master.metadata.sync.executor.pool.size
      3. allixio.master.metadata.sync.ufs.prefetch.pool.size

缓慢的 distributedLoad / distCp / async persist (Job service jobs)

  1. 使用 jps 确保 job master 和 job worker 进程正在运行
  2. alluxio jobs ls 查看是否有活跃的工作
  3. 检查主日志以查看是否触发了作业
  4. 检查我们是否达到工作服务容量,必要时增加 alluxio.job.master.job.capacity
  5. 调整 alluxio.job.worker.threadpool.size 以增加并发性(这可能会影响 worker 性能)

Alluxio进程的OOM

Alluxio 进程可以被系统 OOM 杀手杀死并静静地死去

检查 dmesg -T | egrep -i ‘终止进程’

这将显示哪个进程(如果有)被 OOM 杀手杀死如果确认 OOM 问题,首先增加 xmx,相关进程的directmemory 设置

有时日志会显示Out Of Memory异常,这是Java报OOM。

这通常是由于系统资源不足引起的,例如 ulimit、线程堆栈空间等。

0 0 投票数

文章评分

本文为从大数据到人工智能博主「xiaozhch5」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://cloud.tencent.com/developer/article/2256889

0 人点赞