Alluxio-基于内存的虚拟分布式存储系统

什么是Alluxio
  1. Alluxio 是世界上第一个虚拟的分布式存储系统,它为计算框架和存储系统构建了桥梁,使计算框架能够通过一个公共接口连接到多个独立的存储系统,使计算与存储隔离。 Alluxio 是内存为中心的架构,以内存速度统一了数据访问速度,使得数据的访问速度能比现有方案快几个数量级,为大数据软件栈带来了显著的性能提升。
  2. 在大数据生态系统中,Alluxio 位于数据驱动框架或应用(如 Apache SparkPrestoTensorflowApache HBaseApache Hive Apache Flink)和各种持久化存储系统(如 Amazon S3Google Cloud StorageOpenStack SwiftGlusterFSHDFSIBM CleversafeEMC ECSCephNFS Alibaba OSS)之间,Alluxio 统一了存储在这些不同存储系统中的数据,为其上层数据框架提供统一的客户端API和全局命名空间。

元数据同步

Alluxio为Spark或Presto等应用程序提供分布式数据访问层,以通过统一文件系统命名空间中的单一API访问不同的底层文件系统(或UFS)。如果用户只通过Alluxio与UFS中的文件进行交互,由于Alluxio保存了客户端对UFS所做的任何更改,因此它将Alluxio命名空间与UFS命名空间保持同步(参见下图)
但是,如果在不通过Alluxio的情况下更改UFS中的文件,则UFS命名空间和Alluxio命名空间可能会不同步。发生这种情况时,需要UFS元数据同步操作来同步两个命名空间(如右图所示)。

alluxio知识点整理 - 图1

在Alluxio 2.0中,有两种方法可以使Alluxio和UFS之间的元数据保持同步。

  1. 按需同步
    Alluxio自动缓存来自UFS的元数据信息,使后续的元数据操作(如listStatus(或ls))不需要访问UFS。这一技术减少了部分元数据操作的延迟。 但是,有时候底层UFS的元数据可能会在绕过Alluxio的情况下发生变化。此时,Alluxio需要使此缓存失效。从版本1.7.0开始,Alluxio提供了一个选项 alluxio.user.file.metadata.sync.interval,允许用户控制元数据缓存刷新的频率。只要客户端发出元数据操作(例如listStatus),它就可以将间隔指定为-1,0或固定时间值。
    当它设置为-1时,Alluxio永远不会从UFS获取元数据信息。当它设置为0时,它总是从UFS获取元数据信息。当它被设置为固定时间值时,如果在过去该时间段内Alluxio没有执行该操作,它将从UFS获取元数据信息。
    该参数选项可以直接配置到alluxio-site.properties配置文件中,此时底层UFS元数据变化时会根据时间值自动刷新Alluxio元数据,还可以手动刷新指定目录一次,执行如下命令:
    #设置alluxio总是从UFS获取元数据信息
    alluxio fs ls -R -Dalluxio.user.file.metadata.sync.interval=0 /dir
    


需要注意的一点是,除非有对该UFS的客户端请求,否则Alluxio系统永远不会与UFS同步。这可能会导致部分问题,因为特定客户端第一次访问UFS时,访问UFS的额外成本会导致客户端请求减慢。因此,Alluxio需要一种在后台同步Alluxio命名空间和UFS命名空间,或者同步Active UFS的新机制。

  1. 主动同步
    Alluxio 2.0预览版支持新功能“Active UFS Sync”。它允许用户以有规律的间隔指定要在Alluxio命名空间和UFS命名空间之间同步的目录,并使用多个参数来微调该同步行为。目前,仅在Alluxio和HDFS 2.7或更高版本之间支持Active UFS Sync。要使用此功能,运行Alluxio的用户必须是HDFS管理员用户,才能自动监听HDFS提供的事件流。具体命令介绍如下:
    在指定目录开启主动同步
    alluxio fs startSync /syncedDir
    


停止目录上的活动同步

alluxio fs stopSync /syncedDir


请注意,在Master重启之间会记住活动同步下的目录列表。您可以使用getSyncPathList命令检查哪些目录处于活动同步状态。

alluxio fs getSyncPathList
  1. 优化活动UFS同步行为
    同步间隔:用户可以通过更改alluxio.master.activesync.interval选项来控制活动同步间隔,默认值为30秒。
    安静时段:当要同步的目录受到大量修改,并与UFS进行大量RPC通信,为了不增加UFS的工作负载,主动UFS同步尝试仅在UFS被认为处于安静时段时进行同步。
    alluxio.master.activesync.maxactivity
    Activity是一种基于目录中多个事件的指数移动平均值的启发式算法。此配置项表示HDFS的修改事件数目的指数移动平均值最大达到多大时停止元数据同步,UFS目录中被视为“安静”的最大活动数。例如,如果目录在过去三个时间间隔内有100,10,1事件,则它的活动值将是100/10 * 10 + 10/10 + 1 = 3。在实际使用场景中,应预先考虑到可能的HDFS操作,并根据实际情况设定;
    alluxio.master.activesync.maxage
    此配置项是在同步UFS和Alluxio空间之前我们将等待的最大间隔数。
    为防止alluxio.master.activesync.maxactivity配置项导致很长时间内都没有元数据自动同步,元数据可能会在Alluxio命名空间中变得陈旧,可增加此配置项来进行限制。设置最大等待间隔时间,如果它是“安静”的,或者它已经很长时间(一个长于最大年龄的时间段)没有同步,系统保证我们将开始同步目录。
    元数据缓存(持久化存储)


此处的元数据是指Alluxio中master所管理的所有元数据,不仅包括UFS元数据,还有Alluxio自身存储的ACL相关数据等等。这些数据默认存储在内存中,如果master因为某些原因宕机,元数据就会丢失,即使master恢复也可能出现元数据丢失导致的数据访问报错。针对此问题,Alluxio在2.0版本开始支持了将元数据存储在RocksDB的配置项:

alluxio.master.metastore=ROCKS #默认为HEAD,即存储在内存中


配置为ROCKS后,所有元数据将存储于RocksDB数据库中,重启master也不会丢失。由于Alluxio中数据的ACL继承于UFS,如果UFS不支持ACL配置则需要用户自己设置目录权限组,使得一旦元数据丢失则会产生很大的运维成本,此时将元数据配置为RocksDB存储就可应对这种情况。
Alluxio也支持内存和RocksDB两种存储方式之间的切换,比如Alluxio集群部署时没有配置RocksDB元数据存储,使用一段时间后想要切换为RocksDB时,则需要进行切换。Alluxio给出的步骤为:

1. 日志备份,以便恢复元数据,备份地址由alluxio.master.backup.directory配置项决定
    alluxio fsadmin backup  
2. 修改alluxio-site.properties配置文件:
    alluxio.master.metastore=ROCKS
3. 关闭master,然后执行日志格式化(格式化日志将会删除Alluxio所有元数据)
    ./alluxio-stop.sh masters
    alluxio formatMasters
4. 从备份启动master,<backup_uri> 应该是对所有主机都可用的完整URI路径, e.g. hdfs://[namenodeserver]:[namenodeport]/alluxio_backups/alluxio-journal-YYYY-MM-DD-timestamp.gz
    ./alluxio-start.sh -i <backup_uri> masters


备份文件存放在HDFS文件系统中,则需要目录有alluxio启动用户的权限(这里是hadoop用户)

如果恢复成功,您应该会在master节点主日志中看到一行日志消息

INFO AlluxioMasterProcess - Restored 57 entries from backup


Alluxio对于RocksDB中的元数据也采用了分级缓存的策略,访问频率相对较高的元数据将存储在内存Cache中,其他冷数据将存储在RocksDB中。就inode元数据来说,每1千万个inode将占用约1GB的存储空间,为节约元数据对内存的空间占用,Alluxio引入了数个配置项来优化元数据的存储。
元数据存储配置项如下:
alluxio.master.metastore.dir
默认为$ALLUXIO_HOME/metastore,表示RocksDB数据的存储目录。
alluxio.master.metastore.inode.cache.max.size
默认10000000,表示内存Cache存储的最大inode数量,默认10000000即表示占用1GB空间。
alluxio.master.metastore.inode.cache.evict.batch.size
默认为1000,表示达到缓存替换阈值时,默认每次缓存替换内存Cache中的1000个inode。
alluxio.master.metastore.inode.cache.high.water.mark.ratio
默认0.85,表示内存Cache空间使用了85%时,达到缓存替换阈值,开始进行缓存替换。
alluxio.master.metastore.inode.cache.low.water.mark.ratio
默认为0.8,表示当缓存替换使得内存Cache空间占用比例小于80%时,停止缓存替换。

ACL访问权限控制


Alluxio中数据的ACL继承于UFS,如果UFS不支持ACL配置则需要通过Alluxio来设置目录访问权限。

# 给/path/to/data路径(-R表示同时递归更改子目录及文件)增加hadoop用户组的所有rwx权限
alluxio fs setfacl [-R] -m 'group:hadoop:rwx' /path/to/data
# 给/path/to/data路径增加netease用户的所有rwx默认权限(仅增加默认权限,不改变现有ACL,新建的子目录及文件会继承默认权限)
alluxio fs setfacl -d -m 'user:netease:rwx' /path/to/data
# 给/path/to/data路径及其子目录递归增加hadoop用户组的r-x权限(仅对目录生效,对文件不生效)
alluxio fs setfacl -R -d -m 'group:hadoop:r-x' /path/to/data
# 查看某个目录的ACL
alluxio fs getfacl /path/to/data

Alluxio层次化存储
  1. 分层存储的类别
    MEM (内存)、SSD (固态硬盘)、HDD (硬盘驱动器)

  2. 缓存配置说明
    alluxio.worker.block.annotator.class
    表示当某个缓存层(MEM/SSD/HDD)空间不足时,采用哪种缓存数据块替换策略。
    #以下选项适用于Alluxio 2.3.0及以上版本

    1. alluxio.worker.block.annotator.LRUAnnotator(默认值)
      最近最少使用替换策略,将选取最近最少访问的数据块进行替换。

    2. alluxio.worker.block.annotator.LRFUAnnotator
      最近最不经常使用与LRU的混合策略,有两个配置项可对此进行相关参数调整:
      a. alluxio.worker.block.annotator.lrfu.step.factor
      LRFU的权重参数,取值[0, 1],靠近0时将接近LFU策略,靠近1时将接近LRU策略;
      b. alluxio.worker.block.annotator.lrfu.attenuation.factor
      衰减因子,取值[2, +∞),控制块替换的顺序;

  1. alluxio.worker.block.allocator.MaxFreeAllocator(默认值)
    返回具有最大可用空间比例的目录,而且总是返回最高存储层

  2. alluxio.worker.block.allocator.GreedyAllocator
    直接返回第一个符合写入数据块大小的目录

  3. alluxio.worker.block.allocator.RoundRobinAllocator
    先从最高层开始,最高层的每个目录轮流进行数据块的写入,如果空间不足,则顺延到下一缓存层

alluxio运维命令:

#加载数据到缓存中
alluxio fs distributedLoad /alluxio目录
#查看alluxio活动master
alluxio fs leader