Alluxio数据block移动逻辑分析

背景简介

目前,线上alluxio集群出现了部分worker容量占用过高的问题,分析日志发现,有如下几个异常点:

  1. 由于block状态异常,无法对该block进行移动
  1. 部分临时文件被pin在内存中,处于pin状态的block无法被移动

  2. worker上某层缓存容量不足以进行block移动

  1. Alluxio内部逻辑限制了block移动时不可以触发block换出到底层(HDFS或S3)逻辑

其中,异常1-3均为block移动受限,导致如果不进行手动数据清理,这些block将一直占用worker的存储空间。异常1的可能原因是BlockMeta丢失,或block处于写入未完成的状态,即元数据不完整。无论是哪个情况,只要是block元数据不完整,Alluxio均会将其判断为写入不完全的block,禁止进行移动;异常2的原因目前来看可能是客户端暂时覆盖了Alluxio的writetype为ASYNC_THROUGH,导致文件在写入时会被标记为PinOnCreate,这样文件在写入后会被pin在缓存上,如下图所示。

异常3出现的频率相对较高,此操作为数据块的位置交换,当某层容量不足时,交换操作会失败,同时会提交一个容量释放任务;异常4是Alluxio内部的逻辑限制,与异常3有一定相关度,从设计上看是Alluxio把空间释放交给了容量释放的任务来进行,而不是在block交换过程中进行缓存换出(block eviction,块驱逐)。

Block移动逻辑分析

涉及block移动的调用逻辑可大致如下图所示,下面分别进行介绍。

Alluxio通过特定的block移动管理线程进行block管理,线程数可通过alluxio.worker.management.task.thread.count配置进行调整,默认值为节点上的CPU核数。所有线程启动后,每隔固定的时间(可由alluxio.worker.management.load.detection.cool.down.time进行配置,默认10s)会通过图中上中黄色的TierManagementTaskProvider类获取下次要执行的task,每个task可能为以下四种之一:

  1. Block对齐:为确保当前的Block顺序(从顶层到底层)符合配置的LRU或LFU策略,当出现顺序不正确时需进行Block对齐任务,交换两个block的位置,可由alluxio.worker.management.tier.align.enabled配置控制是否开启Block对齐任务;
  2. 冷数据升级(冷数据向高缓存层升级):当相对靠上的缓存层有较多的可用空间时,会启动冷数据升级任务,期间将会向被升级的缓存层持续移动Block,直到该层容量占比达到alluxio.worker.management.tier.promote.quota.percent配置的值(默认90)时停止,可由alluxio.worker.management.tier.promote.enabled配置控制是否开启冷数据升级;
  3. 空间释放:当Block对齐任务由于空间不足执行失败时,会将一个空间释放的标志位置为true,当管理线程检测到标志位变为true时,会开启空间释放任务。Alluxio中默认会对每一个缓存层配置一个保留区,保留区正常不会写入数据,默认为1G,可通过alluxio.worker.management.tier.align.reserved.bytes配置大小,由于Alluxio的block大小可变,不同大小的block进行交换时就可能会占用保留区的空间。空间释放任务,会释放保留区中已经使用的部分,另外,还会释放与在上层缓存中已释放的空间相同大小的空间,确保block移动不会失败。可通过alluxio.worker.management.tier.swap.restore.enabled配置控制是否开启;
  4. 空任务:不进行任何操作;

管理线程获取任务时,会根据各个条件进行多次判断,最终确定要进行的任务属于哪一种。首先进行空间释放标志位判断,如果为true,则返回空间释放任务;然后从顶层缓存开始逐两层进行遍历,先判断是否有block需要进行移动以保障LRU/LFU的顺序,后判断是否相对上层的缓存中是否有足够的空间用来进行冷数据升级,符合任意一种情况则直接返回该类型的任务。如图中紫色部分的AbstractBlockManagementTask类所示,其中有几个成员变量为任务执行中的关键变量,包括保存当前层中block映射关系的mBlockStore、保存block元数据的mMetadataManager、保存目前可供驱逐的block的视图对象mEvictorView、检测某worker上用户行为负载的loadTracker(用于帮助确定何时执行任务)等等。

任务获取后,由图中左上绿色ManagementTaskCoordinator类进行执行,执行过程中会多次与负责管理某一缓存层中所有block的TieredBlockStore类进行交互,通过BlockTransferExecutor类中的executeTransferPartition方法实现。根据不同任务类型,会有不同的执行计划,执行计划中包括了需要移动的block的当前位置、目标位置、移动选项等信息。如图中右侧橘黄色所示的AllocateOptions类,其中定义了不同操作需要的不同选项:

  1. 是否强制执行:表示是否强制使用一般不可用的空间,如保留区、或驱逐其他block;
  2. 是否允许block驱逐:表示如果需要,则将block驱逐出Alluxio缓存;
  3. 是否使用保留区空间:表示如果需要,则占用保留区空间;

不同操作定义的选项如下表所示(0表示false,1表示true):

操作名称强制执行块驱逐使用保留区
创建block010
分配空间110
缓存间block移动101
block移动(客户端请求)110

可以看到,所有类型的操作均需要新的存储空间,用来存储被操作的block以及临时block,Alluxio在移动一个block时,会先在目标层创建一个临时block,然后将该block放到目标worker的目标目录下,再删除原block和临时block。因此block管理线程的block对齐和冷数据升级任务均调用了TieredBlockStore类下面的moveBlock方法,如图中黄色部分所示,经过多层调用最终调用了BlockHeartbeatReporter类下的removeBlockFromAddedBlocks方法。如果被操作的block处于被pin住的状态,则无法进行任何操作。需注意的是,如果被操作的block元数据丢失,即blockMeta不可用,或处于未写入完成的block,会无法进行移动/删除等操作(图中黄色部分加粗的方法),并抛出InvalidBlockStateException异常,报错可能如下图所示:

空间释放任务与其他两个任务不同,直接调用了TieredBlockStore的removeBlock方法删除指定id的block,会从缓存上删除block和对应的blockMeta元数据,如果blockMeta不可用,也会报类似Cannot xxx uncommitted block的错误。

除block管理线程定时进行的移动任务外,还有其他请求也会触发block移动的逻辑,如图上中间部分蓝色表示的DefaultBlockWorker类,包括三种情况:1)写入的新block;2)读取到不在Alluxio中的block;3)读取到在Alluxio中但不在最顶层的block;其中1)和2)需要在Alluxio中申请空间并创建新的block,并且如果alluxio.user.file.readtype.default配置被指定为CACHE,则会在读取不在Alluxio中的数据时将其移动到最高层,如果配置为CACHE_PROMOTE,则会在3)的情况下也把block移动到最顶层。另外,job_worker中的block复制任务也会通过创建block的方式写入新block。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值