缓存能力

最后更新时间:2021-07-16 11:43:25

    缓存能力概述

    GooseFS 基于开源 Alluxio 的架构,提供强大的分布式 Cache 能力,能够帮助用户统一跨各种平台用户数据的同时,还有助于为用户提升总体 I/O 吞吐量。

    主要通过以下两套方式:

    • GooseFS NameSpace 远端存储: NS 存储空间底座来自于外部存储,可以跨越 COSN 和 HDFS,连接一个或者多个 NS 到同一个底层存储,可以持久化海量数据。选用 COSN 的存算分离方案,GooseFS NameSpace 借助 COSN 可以给大数据存储提供弹性扩展和高可用能力。
    • GooseFS 本地 Cache 存储:GooseFS 通过 master 和 worker 提供的分布式 Cache 能力,将应用层产生的数据持久化在应用节点本地的内存和磁盘上,主要存储热数据和暂态数据。每个本地存储节点都可由用户配置,NameSpace 对接的远端持久化层也会经过同一个 client 服务用户的读取操作。

    用户可以操作 Cache Policy,决定读写模式中使用本地 Cache 存储和 NameSpace 远端存储。

    GooseFS 提供相同的本地 Cache 和远端 NameSpace 整合的能力,帮助用户全面实现存储分离的统一方案,同时建立应用节点的数据亲缘性。

    GooseFS 缓存配置

    用户可以进入 goosefs-site.properties 文件中查看 GooseFS 缓存配置情况。目前GooseFS的缓存设置可以从缓存层级、缓存淘汰策略等方面了解,缓存层级方面主要有单层存储和多层存储两种,缓存淘汰策略主要区分为 LRU 和 LRFU 两种。以下进行详细介绍。

    1. 缓存层级

    GooseFS 提供单层存储和多层存储两种缓存层级。单层存储只使用一种存储介质,多层存储使用多种存储,可以根据业务负载情况来决定使用何种存储介质,以提供匹配的 I/O 性能。GooseFS 默认配置为单层存储,在多层存储的场景下,缓存淘汰会带来较多的性能开销,因此推荐使用单层存储。根据 I/O 性能的高低,一般可以选用 MEM(内存)、SSD(固态存储)和 HDD(硬盘存储)作为存储介质。

    通过修改 goosefs-site.properties 配置文件中的 levels 参数可以修改缓存层级,入参为 1 时代表只使用单层存储,入参为 3 代表使用三层存储:

    goosefs.worker.tieredstore.levels=1
    

    通过修改 goosefs-site.properties 配置文件中的 alias 参数可以修改缓存层对应的存储介质:

    goosefs.worker.tieredstore.level{x}.alias=MEM
    
    注意:

    level{x} 代表第几层存储,例如 level0 代表单层存储。

    1.1 单层存储

    单层存储模式下,常用的系统配置项如下:

    goosefs.worker.tieredstore.levels=1
    goosefs.worker.tieredstore.level0.alias=HDD
    goosefs.worker.ramdisk.size=16GB
    goosefs.worker.memory.size=100GB
    goosefs.worker.tieredstore.level0.dirs.path=/data/GooseFSWorker,/data1/GooseFSWorker,/data2/GooseFSWorker,/data3/GooseFSWorker,/data4/GooseFSWorker
    goosefs.worker.tieredstore.level0.dirs.mediumtype=MEM,MEM,MEM,SSD,SSD
    goosefs.worker.tieredstore.level0.dirs.quota=16GB,16GB,16GB,100GB,100GB
    

    以下逐项介绍配置项内容。

    • ramdisk.size:该配置项用于指定 worker 节点占用内存的大小。ramdisk 的容量必须比 memory 小。设置后 GooseFS 会为每个 worker 节点分配指定大小的内存空间,并消耗系统总内存。
    • memory.size:该配置项用于指定 GooseFS 系统总内存,设置后 GooseFS 将会自动占用指定大小的存储介质,实际物理存储空间必须比 memory 数值大。
    • dirs.path:该配置项用于指定目录,由 GooseFS 为指定目录分配存储介质,需要结合 dirs.mediumtype 使用,如上示例展示将 /data/GooseFSWorker 挂载到 MEM 存储介质上,将/data4/GooseFSWorker 挂载到 SSD 存储介质上。需要注意,每个目录的顺序需要和存储介质的顺序一一匹配。
    • dirs.mediumtype:该配置项用于指定存储介质,由 GooseFS 为指定目录分配存储介质,需要结合 dirs.path 使用。默认可选的存储介质包括 MEM,SSD,如果挂载了其他存储介质,如 HDD,可按需修改配置。
    • dirs.quota:改配置项用于指定每个目录的预置空间,配置后由 GooseFS 为指定目录分配好空间,需要和目录的顺序一一对应。如上示例展示了需要为 /data/GooseFSWorker,/data1/GooseFSWorker,/data2/GooseFSWorker 等目录分配 16GB MEM 空间,为 /data3/GooseFSWorker,/data4/GooseFSWorker 目录分配 100GB SSD 空间。

    1.2 分层存储

    分层存储模式下,数据块的读写模式与单层存储的读写模式存在差异。单层存储模式下数据会直接从一种存储介质中读写,多层存储模式下数据会默认优先写入最顶层存储介质,读取的时候则需要将数据先挪到最顶层存储介质。具体地:

    • 数据写入:新的数据块会被默认写入最顶层的存储介质;如果最顶层存储介质的存储空间已经满了,GooseFS 会把数据顺位存储到下一层的存储介质中;如果所有存储介质都已经存满数据,那么 GooseFS 会按照用户指定的缓存淘汰策略淘汰过期数据;如果过期数据无法淘汰,并且所有可用存储空间已满,则无法写入数据。
    • 数据读取:多层存储模式下,会将冷数据透明地转储到更低层次的存储介质中,读取数据会将数据加热并放置到顶层存储中。
    注意:

    • 在既定的淘汰策略下,GooseFS 会按照指定的释放空间来清理一定量的数据,该参数可以通过 goosefs.worker.tieredstore.free.ahead.bytes 指定,默认值为0。
    • 分层存储模式下,读取数据时可能会频繁将数据从低层存储介质转储到顶层存储介质中,进而导致频繁的缓存淘汰情况,对性能带来一定损耗,一般情况下,推荐使用单层存储

    分层存储模式下,常用的系统配置项如下:

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

    其中,x 代表缓存层级,一般而言可以设置 3 层存储,分别对应 MEM,SSD,HDD等存储介质。以 2 层存储,存储介质分别为 MEM,SSD,每一层分配100GB存储为例,对应的配置信息如下:

    goosefs.worker.tieredstore.levels=2
    goosefs.worker.tieredstore.level0.alias=MEM
    goosefs.worker.tieredstore.level0.dirs.path=/data/GooseFSWorker
    goosefs.worker.tieredstore.level0.dirs.mediumtype=MEM
    goosefs.worker.tieredstore.level0.dirs.quota=100GB
    goosefs.worker.tieredstore.level1.alias=SSD
    goosefs.worker.tieredstore.level1.dirs.path=/data1/GooseFSWorker
    goosefs.worker.tieredstore.level1.dirs.mediumtype=SSD
    goosefs.worker.tieredstore.level1.dirs.quota=100GB
    

    GooseFS 支持配置多层存储,层数没有限制,但是每一层的命名(alias)均需要保证唯一性。一般来说,提供 3 层缓存,每一层分别对应 MEM,SSD,HDD就起到较好的分层效果。

    2. 缓存淘汰策略

    GooseFS 提供了两种缓存淘汰策略:

    • LRUAnnotator:按照近期使用次数最少(least-recently-used)的顺序淘汰缓存,是 GooseFS 的默认策略。
    • LRFUAnnotator:按照近期使用次数最少(least-recently-used)和近期使用频次最少(least-frequently-used)的顺序淘汰缓存,通过权重配置 goosefs.worker.block.annotator.lrfu.step.factor 和 goosefs.worker.block.annotator.lrfu.attenuation.factor 来调整两种策略在淘汰过程中起的作用。
      • 如果将 least-recently-used 的权重调整至最大,那么该策略的表现与 LRUAnnotator一致。

    可以在 goosefs.worker.block.annotator.class 这一配置项中配置缓存淘汰策略,配置时需要正确指定策略名称:

    goosefs.worker.block.annotator.LRUAnnotator
    goosefs.worker.block.annotator.LRFUAnnotator
    

    数据生命周期管理

    这里的生命周期是指在 GooseFS 中的数据生命周期,而不是远端存储系统 UFS 的,生命周期管理主要有如下四种操作:

    • free:此操作用于从 GooseFS 中删除对应目录或者文件的数据(不会删除 UFS 中的对应数据),此类操作主要是用来释放 GooseFS 的缓存空间,供其他更热的数据使用。
    • load:此操作用于将 UFS 对应目录或者文件的数据加载到 GooseFS 中,此类操作主要用于冷数据转热,从而提高 I/O 性能。
    • persist:此操作用于将 GooseFS 内的数据写入到 UFS 存储中,此类操作主要用于持久化数据,从而避免数据丢失。
    • TTL(Time to Live):TTL 属性主要用于设置目录或者文件在 GooseFS 中的生命周期,在超过其生命周期后,会从 GooseFS 和 UFS 中删除。通过配置,也可支持仅删除 GooseFs 数据或仅释放磁盘空间。

    1. 从 GooseFS 中释放数据

    通过 free 指令可以从 GooseFS 中释放数据,如下示例展示了释放数据后,GooseFS 中数据的状态变成 0%:

    $ goosefs fs free /data/test.txt
    /data/test.txt was successfully freed from GooseFS space.
    $ goosefs fs ls /data/test.txt
    -rw-rw-rw-  hadoop         hadoop                      14       PERSISTED 03-11-2021 11:46:15:000 0% /data/test.txt
    

    示例中的 /data/test.txt 可以是任何合法的 GooseFS 文件路径,如果数据存储于远端存储 UFS 中,则可以通过 load 指令重新加载。

    注意:

    一般而言,推荐通过配置缓存策略自动清理 GooseFS 中的历史数据。

    2. 往 GooseFS 中加载数据

    通过 load 指令可以从 GooseFS 中加在数据,如下示例展示了释放数据后,GooseFS 中数据的状态变成 100% :

    $ goosefs fs load /data/test.txt
    /data/test.txt loaded
    $ goosefs fs ls /data/test.txt
    -rw-rw-rw-  hadoop         hadoop                      14       PERSISTED 03-11-2021 11:46:15:000 100% /data/test.txt
    

    示例中的 /data/test.txt 可以是任何合法的 GooseFS 文件路径。如果是从本地文件系统中加载数据,则需要使用 copyFromLocal 指令,需要注意的是,从本地文件系统中加载数据的操作并不会将数据持久化到远端存储 UFS 中。在默认情况下, GooseFS 能在首次访问文件时自动加载数据到 GooseFS 到缓存中,因此一般无需使用该指令加载数据;但如果业务需要提前加载数据到缓存中,可以通过该指令加载。

    3. 在 GooseFS 中持久化数据

    通过 persit 指令可以将数据持久化到远端存储系统 UFS 中:

    $ goosefs fs persist /data/test.txt
    $ goosefs fs ls /data/test.txt
    -rw-rw-rw-  hadoop         hadoop                      14       PERSISTED 03-11-2021 11:46:15:000 100% /data/test.txt
    

    示例中的 /data/test.txt 可以是任何合法的 GooseFS 文件路径。推荐通过缓存策略配置来自动执行持久化的操作。

    4. 设置数据 TTL 属性

    GooseFS 支持为命名空间中的任意文件或者目录设置 TTL 属性。该属性可以保证业务数据可以按照指定的时间周期定期删除,为新文件释放空间,保证本地磁盘空间的有效利用。 GooseFS 文件和目录的 TTL 属性可以作为文件元数据的一部分,可以保证在集群重启后 TTL 属性依然生效,后端线程的定期巡检程序会检查这些 TTL 属性并自动清理过期文件。

    定期巡检程序的巡检周期和巡检类型可以在 goosefs-site.preperties 中设置,以下示例将巡检周期设置为 10 分钟,巡检类型设置为 FREE :

    goosefs.master.ttl.checker.interval=10m
    goosefs.user.file.create.ttl.action=FREE
    

    设置完毕后,GooseFS 后台线程会每隔 10 分钟巡检一遍,当次巡检周期内发现的过期文件会在下一次巡检周期过完后释放缓存资源。如 00:00:00 进行了第一次巡检发现一批过期文件,这批文件缓存会在 00:10:00 清除。

    注意:

    默认情况下该入参单位为毫秒(ms),可以在入参时指定好检测时间周期的单位,如秒(s),分钟(m),小时(h)等,更多说明可以查看配置说明的介绍。

    数据复制管理

    数据复制主要分为被动复制和主动复制两种形式。

    1. 被动复制

    GooseFS中的每个文件都包含一个或多个分布在集群中存储的存储块,默认情况下 GooseFS 可以根据负载和容量情况自动调整数据分块的复制级别。被动复制会发生在以下场景:

    • 多个客户端同时读取相同的块,会导致多个 block 同时存在在不同的 worker 上。
    • 当开启优先本地读时,数据不在本地,则会发起 remote read,并保存在本地 worker 上。
    • 当被动复制产生的副本数大于设定的副本数目时,其会异步的去删除多余的副本。以上过程对用户完全透明。

    2. 主动复制

    主动复制是通过设置文件的副本数目实现的,对于不满足设定副本数的 block,其会异步的补足,对于超过设定副本数的 block,其会删除多余的副本。具体的,可以通过如下指令调整主动复制的级别:

    $ goosefs fs setReplication  [-R] [--max | --min ] <path>
    

    相关参数说明如下:

    • max:指定文件的最大副本数,默认值为 -1,表示不设置上限;如果设置为 0 代表不在 GooseFS 中存储指定文件的冷数据。一般设置为正整数,设置后 GooseFS 会检查文件副本数量并删除多余的副本。
    • min:指定文件的最小副本数,默认值为0,代表 GooseFS 会在数据变冷后删除该数据不留存任何副本。一般设置为正整数,并且需要小于 max 值,设置后 GooseFS 会检查文件副本数量,如果副本数量比最小值小会自动补齐副本数。
    • path:指定的文件名,可以为目录或者具体的文件路径。
    • R:如果 path 中入参为目录,则指定 -R 可以按照指定的最小副本数和最大副本数,重复递归复制指定目录下的所有文件和子目录。

    如果需要查看指定文件的复制情况,可以通过 stat 指令查看,如下示例展示 /data/test.txt 这个文件的最大副本数为 -1,意味着该文件变冷后会被过期删除:

    $ goosefs fs stat /data/test.txt
    /data/test.txt is a file path.
    FileInfo{fileId=50331647, fileIdentifier=null, name=test.txt, path=/data/test.txt, ufsPath=hdfs://172.16.16.16:4007/data/test.txt, length=0, blockSizeBytes=134217728, creationTimeMs=1618193473555, completed=true, folder=false, pinned=false, pinnedlocation=[], cacheable=true, persisted=true, blockIds=[], inMemoryPercentage=100, lastModificationTimesMs=1616763603692, ttl=-1, lastAccessTimesMs=1616763603692, ttlAction=DELETE, owner=hadoop, group=supergroup, mode=420, persistenceState=PERSISTED, mountPoint=false, replicationMax=-1, replicationMin=0, fileBlockInfos=[], mountId=1, inGooseFSPercentage=100, ufsFingerprint=TYPE|FILE UFS|hdfs OWNER|hadoop GROUP|supergroup MODE|420 CONTENT_HASH|(len:0,_modtime:1616763603692) , acl=user::rw-,group::r--,other::r--, defaultAcl=}
    This file does not contain any blocks.
    

    查看缓存用量

    GooseFS 会记录本地缓存的容量和使用情况,可以通过如下指令查看 GooseFS 的运行情况,针对性地管理和维护本地缓存。

    • 查看 GooseFS 正在使用的缓存,单位为字节:
    $ goosefs fs getUsedBytes
    Used Bytes: 0
    
    • 查看 GooseFS 总缓存容量,单位为字节:
    $ goosefs fs getCapacityBytes
    Capacity Bytes: 1610612736000
    
    • 查看 GooseFS 的缓存使用报告:
    $ goosefs fsadmin report
    GooseFS cluster summary: 
      Master Address: 172.16.16.16:19998
      Web Port: 19999
      Rpc Port: 19998
      Started: 04-12-2021 10:52:05:255
      Uptime: 0 day(s), 1 hour(s), 28 minute(s), and 57 second(s)
      Version: 2.5.0-SNAPSHOT
      Safe Mode: false
      Zookeeper Enabled: false
      Live Workers: 3
      Lost Workers: 0
      Total Capacity: 1500.00GB
          Tier: HDD  Size: 1500.00GB
      Used Capacity: 0B
          Tier: HDD  Size: 0B
      Free Capacity: 1500.00GB