Alluxio 是世界上第一个虚拟的分布式存储系统,它为计算框架和存储系统构建了桥梁,使计算框架能够通过一个公共接口连接到多个独立的存储系统,使计算与存储隔离。 Alluxio 是内存为中心的架构,以内存速度统一了数据访问速度,使得数据的访问速度能比现有方案快几个数量级,为大数据软件栈带来了显著的性能提升
在大数据生态系统中,Alluxio 位于数据驱动框架或应用(如 Apache Spark、Presto、Tensorflow、Apache HBase、Apache Hive 或 Apache Flink)和各种持久化存储系统(如 Amazon S3、Google Cloud Storage、OpenStack Swift、GlusterFS、HDFS、IBM Cleversafe、EMC ECS、Ceph、NFS 和 Alibaba OSS)之间,Alluxio 统一了存储在这些不同存储系统中的数据,为其上层数据框架提供统一的客户端API和全局命名空间
为了方便大家可以持续跟进Alluxio发展动态,这里给出两条跟进Alluxio最新发展和动态的途径:
Alluxio官方文档
Alluxio知乎专栏
Alluxio优势
Alluxio的特征:
对Alluxio的优势和特征进行了概括 点击可进入官网介绍
超大规模工作负载:支持超大规模工作负载并具有HA高可用性
灵活的API :计算框架可使用HDFS、S3、Java、RESTful或POSIX为基础的API来访问Alluxio
智能数据缓存和分层 : 使用包括内存在内的本地存储,来充当分布式缓存,很大程度上改善I/O性能,且缓存对用户透明
存储系统接口 : 通过一系列接口集成HDFS,S3,Azure Blob Store,Google Cloud Store等存储系统
统一全局命名空间 : 多个存储系统安装到一个统一的名称空间中,不需要创建永久数据副本,方便管理多数据源
安全性 : 通过内置审核、基于角色的访问控制、LDAP、活动目录和加密通信,提供数据保护
监控和管理 : 提供了用户友好的Web界面和命令行工具,允许用户监控和管理集群
分层次的本地性 : 将更多的读写安排在本地,实现成本和性能的优化
Alluxio的应用场景
Alluxio 的落地非常依赖场景,否则优化效果并不明显(无法发挥内存读取的优势)
1.计算应用需要反复访问远程云端或机房的数据(存储计算分离)
2.混合云,计算与存储分离,异构的数据存储带来的系统耦合(Alluxio提供统一命名空间,统一访问接口)
3.多个独立的大数据应用(比如不同的Spark Job)需要高速有效的共享数据(数据并发访问)
4.计算框架所在机器内存占用较高,GC频繁,或者任务失败率较高,Alluxio通过数据的OffHeap来减少GC开销
5.有明显热表/热数据,相同数据被单应用多次访问
6.需要加速人工智能云上分析(如TensorFlow本地训练,可通过FUSE挂载Alluxio FS到本地)
我也做了很多Allxuio的性能测试工作,效果都不是很理想,有幸与Alluxio PMC范斌和李浩源交流了测试结果不如人意的原因,大佬是这么说的:”如果HDFS本身已经和Spark和Hive共置了,那么这个场景并不算Alluxio的目标场景。计算和存储分离的情况下才会有明显效果,否则通常是HDFS已经成为瓶颈时才会有帮助。“
还有,如果HDFS部署在计算框架本地,作业的输入数据可能会存在于系统的高速缓存区,则Alluxio对数据加速也并不明显。
所以:应用场景很关键,新技术产生时,一定要了解其应用场景和原理并经过考虑之后再做一些性能测试之类的后续工作!
官方介绍的Alluxio应用场景
如图,一个完整的Alluxio集群部署在逻辑上包括master、worker、client及底层存储(UFS)。master和worker进程通常由集群管理员维护和管理,它们通过RPC通信相互协作,从而构成了Alluxio服务端。而应用程序则通过Alluxio Client来和Alluxio服务交互,读写数据或操作文件、目录。
Alluxio核心组件
Alluxio使用了单Master和多Worker的架构,Master和Worker一起组成了Alluxio的服务端,它们是系统管理员维护和管理的组件,Client通常是应用程序,如Spark或MapReduce作业,或者Alluxio的命令行用户。Alluxio用户一般只与Alluxio的Client组件进行交互。
Master: 负责管理整个集群的全局元数据并响应Client对文件系统的请求。在Alluxio文件系统内部,每一个文件被划分为一个或多个数据块(block),并以数据块为单位存储在Worker中。Master节点负责管理文件系统的元数据(如文件系统的inode树、文件到数据块的映射)、数据块的元数据(如block到Worker的位置映射),以及Worker元数据(如集群当中每个Worker的状态)。所有Worker定期向Master发送心跳消息汇报自己状态,以维持参与服务的资格。Master通常不主动与其他组件通信,只通过RPC服务被动响应请求,同时Master还负责实时记录文件系统的日志(Journal),以保证集群重启之后可以准确恢复文件系统的状态。Master分为Primary Master和Secondary Master,Secondary Master需要将文件系统日志写入持久化存储,从而实现在多Master(HA模式下)间共享日志,实现Master主从切换时可以恢复Master的状态信息。Alluxio集群中可以有多个Secondary Master,每个Secondary Master定期压缩文件系统日志并生成Checkpoint以便快速恢复,并在切换成Primary Master时读取之前Primary Master写入的日志。Secondary Master不处理任何Alluxio组件的任何请求。
Worker: Alluxio Master只负责响应Client对文件系统元数据的操作,而具体文件数据传输的任务由Worker负责,如图,每个Worker负责管理分配给Alluxio的本地存储资源(如RAM,SSD,HDD),记录所有被管理的数据块的元数据,并根据Client对数据块的读写请求做出响应。Worker会把新的数据存储在本地存储,并响应未来的Client读请求,Client未命中本地资源时也可能从底层持久化存储系统中读数据并缓存至Worker本地。
Worker代替Client在持久化存储上操作数据有两个好处:1.底层读取的数据可直接存储在Worker中,可立即供其他Client使用 2.Alluxio Worker的存在让Client不依赖底层存储的连接器,更加轻量化。
Alluxio采取可配置的缓存策略,Worker空间满了的时候添加新数据块需要替换已有数据块,缓存策略来决定保留哪些数据块。
Client: 允许分析和AI/ML应用程序与Alluxio连接和交互,它发起与Master的通信,执行元数据操作,并从Worker读取和写入存储在Alluxio中的数据。它提供了Java的本机文件系统API,支持多种客户端语言包括REST,Go,Python等,而且还兼容HDFS和Amazon S3的API。
可以把Client理解为一个库,它实现了文件系统的接口,根据用户请求调用Alluxio服务,客户端被编译为alluxio-2.0.1-client.jar文件,它应当位于JVM类路径上,才能正常运行。
当Client和Worker在同一节点时,客户端对本地缓存数据的读写请求可以绕过RPC接口,使本地文件系统可以直接访问Worker所管理的数据,这种情况被称为短路写,速度比较快,如果该节点没有Worker在运行,则Client的读写需要通过网络访问其他节点上的Worker,速度受网络宽带的限制。
Alluxio读写场景与参数
Alluxio的分层存储
概念: Alluxio workers节点使用包括内存在内的本地存储来充当分布式缓冲缓存区,可以很大程度上改善I/O性能。每个Alluxio节点管理的存储数量和类型由用户配置,Alluxio还支持层次化存储,让数据存储获得类似于L1/L2 cpu缓存的优化。多层存储设置:
alluxio.worker.tieredstore.levels=2 # 最大存储级数 在Alluxio中配置了两级存储
alluxio.worker.tieredstore.level0.alias=MEM # alluxio.worker.tieredstore.level0.alias=MEM 配置了首层(顶层)是内存存储层
alluxio.worker.tieredstore.level0.dirs.path=/mnt/ramdisk # 设置了ramdisk的配额是100GB
alluxio.worker.tieredstore.level0.dirs.quota=100GB
alluxio.worker.tieredstore.level0.watermark.high.ratio=0.9 # 回收策略的高水位
alluxio.worker.tieredstore.level0.watermark.low.ratio=0.7
alluxio.worker.tieredstore.level1.alias=HDD # 配置了第二层是硬盘层
alluxio.worker.tieredstore.level1.dirs.path=/mnt/hdd1,/mnt/hdd2,/mnt/hdd3 # 定义了第二层3个文件路径各自的配额
alluxio.worker.tieredstore.level1.dirs.quota=2TB,5TB,500GB
alluxio.worker.tieredstore.level1.watermark.high.ratio=0.9
alluxio.worker.tieredstore.level1.watermark.low.ratio=0.7
Alluxio缓存回收策略
缓存回收: Alluxio中的数据是动态变化的,存储空间不足时会为新数据腾出空间
Alluxio异步缓存策略
Alluxio元数据
Alluxio元数据的存储
在Alluxio新的2.x版本中,对元数据存储做了优化,使其能应对数以亿级的元数据存储。
首先,文件系统是INode-Tree组成的,即文件目录树,Alluxio Master管理多个底层存储系统的元数据,每个文件目录都是INode-Tree的节点,在Java对象中,可能一个目录信息本身占用空间不大,但映射在JavaHeap内存中,算上附加信息,每个文件大概要有1KB左右的元数据,如果有十亿个文件和路径,则要有约1TB的堆内存来存储元数据,完全是不现实的。
所以,为了方便管理元数据,减小因为元数据过多对Master性能造成的影响,Alluxio的元数据通过RocksDB键值数据库来管理元数据,Master会Cache常用数据的元数据,而大部分元数据则存在RocksDB中,这样大大减小了Master Heap的压力,降低OOM可能性,使Alluxio可以同时管理多个存储系统的元数据。
通过RocksDB的行锁,也可以方便高并发的操作Alluxio元数据。
高可用过程中,INode-Tree是进程中的资源,不共享,如果ActiveMaster挂掉,StandByMaster节点可以从Journal持久日志(位于持久化存储中如HDFS)恢复状态。
这样会依赖持久存储(如HDFS)的健康状况,如果持久存储服务宕机,Journal日志也不能写,Alluxio高可用服务就会受到影响。
所以,Alluxio通过Raft算法保证元数据的完整性,即使宕机,也不会丢失已经提交的元数据。
Alluxio元数据一致性
Alluxio RPC
Alluxio 1.x中
Master RPC using Thrift(元数据操作)
Workers RPC using Netty(数据操作)
而新的Alluxio 2.x中
使用gRPC保证高吞吐,方便代码维护
Alluxio的Metrics
度量指标信息可以让用户深入了解集群上运行的任务,是监控和调试的宝贵资源。
Alluxio的度量指标信息被分配到各种相关Alluxio组件的实例中。每个实例中,用户可以配置一组度量指标槽,来决定报告哪些度量指标信息。现支持Master进程,Worker进程和Client进程的度量指标 。
度量指标的sink
参数为alluxio.metrics.sink.xxx
ConsoleSink: 输出控制台的度量值。
CsvSink: 每隔一段时间将度量指标信息导出到CSV文件中。
JmxSink: 查看JMX控制台中注册的度量信息。
GraphiteSink: 给Graphite服务器发送度量信息。
MetricsServlet: 添加Web UI中的servlet,作为JSON数据来为度量指标数据服务。
可选度量的配置
Master的Metrics 配置方法 master.* 例如:master.CapacityTotal
常规信息
CapacityTotal: 文件系统总容量(以字节为单位)。
CapacityUsed: 文件系统中已使用的容量(以字节为单位)。
CapacityFree: 文件系统中未使用的容量(以字节为单位)。
PathsTotal: 文件系统中文件和目录的数目。
UnderFsCapacityTotal: 底层文件系统总容量(以字节为单位)。
UnderFsCapacityUsed: 底层文件系统中已使用的容量(以字节为单位)。
UnderFsCapacityFree: 底层文件系统中未使用的容量(以字节为单位)。
Workers: Worker的数目。
逻辑操作
DirectoriesCreated: 创建的目录数目。
FileBlockInfosGot: 被检索的文件块数目。
FileInfosGot: 被检索的文件数目。
FilesCompleted: 完成的文件数目。
FilesCreated: 创建的文件数目。
FilesFreed: 释放掉的文件数目。
FilesPersisted: 持久化的文件数目。
FilesPinned: 被固定的文件数目。
NewBlocksGot: 获得的新数据块数目。
PathsDeleted: 删除的文件和目录数目。
PathsMounted: 挂载的路径数目。
PathsRenamed: 重命名的文件和目录数目。
PathsUnmounted: 未被挂载的路径数目。
RPC调用
CompleteFileOps: CompleteFile操作的数目。
CreateDirectoryOps: CreateDirectory操作的数目。
CreateFileOps: CreateFile操作的数目。
DeletePathOps: DeletePath操作的数目。
FreeFileOps: FreeFile操作的数目。
GetFileBlockInfoOps: GetFileBlockInfo操作的数目。
GetFileInfoOps: GetFileInfo操作的数目。
GetNewBlockOps: GetNewBlock操作的数目。
MountOps: Mount操作的数目。
RenamePathOps: RenamePath操作的数目。
SetStateOps: SetState操作的数目。
UnmountOps: Unmount操作的数目。
Worker的Metrics 配置方法 192_168_1_1.* 例如:192_168_1_1.CapacityTotal
常规信息
CapacityTotal: 该Worker的总容量(以字节为单位)。
CapacityUsed: 该Worker已使用的容量(以字节为单位)。
CapacityFree: 该Worker未使用的容量(以字节为单位)。
逻辑操作
BlocksAccessed: 访问的数据块数目。
BlocksCached: 被缓存的数据块数目。
BlocksCanceled: 被取消的数据块数目。
BlocksDeleted: 被删除的数据块数目。
BlocksEvicted: 被替换的数据块数目。
BlocksPromoted: 被提升到内存的数据块数目。
BytesReadAlluxio: 通过该worker从Alluxio存储读取的数据量,单位为byte。其中不包括UFS读。
BytesWrittenAlluxio: 通过该worker写到Alluxio存储的数据量,单位为byte。其中不包括UTF写。
BytesReadUfs-UFS:${UFS}: 通过该worker从指定UFS读取的数据量,单位为byte。
BytesWrittenUfs-UFS:${UFS}: 通过该worker写到指定UFS的数据量,单位为byte。
Client的Metrics 配置方法 client.* 例如:clien.BytesReadRemote
常规信息
NettyConnectionOpen: 当前Netty网络连接的数目。
逻辑操作
BytesReadRemote: 远程读取的字节数目。
BytesWrittenRemote: 远程写入的字节数目。
BytesReadUfs: 从ufs中读取的字节数目。
BytesWrittenUfs: 写入ufs的字节数目。
配置示例
vim metrics.properties
# List of available sinks and their properties.
alluxio.metrics.sink.ConsoleSink
alluxio.metrics.sink.CsvSink
alluxio.metrics.sink.JmxSink
alluxio.metrics.sink.MetricsServlet
alluxio.metrics.sink.PrometheusMetricsServlet
alluxio.metrics.sink.GraphiteSink
master.GetFileBlockInfoOps
master.GetNewBlockOps
master.FreeFileOps
192_168_1_101.BytesReadAlluxio
192_168_1_101.BytesWrittenAlluxio
192_168_1_101.BlocksAccessed
192_168_1_101.BlocksCached
192_168_1_101.BlocksCanceled
192_168_1_101.BlocksDeleted
192_168_1_101.BlocksEvicted
192_168_1_101.BlocksPromoted
192_168_1_102.BytesReadAlluxio
192_168_1_102.BytesWrittenAlluxio
192_168_1_102.BlocksAccessed
192_168_1_102.BlocksCached
192_168_1_102.BlocksCanceled
192_168_1_102.BlocksDeleted
192_168_1_102.BlocksEvicted
192_168_1_102.BlocksPromoted
192_168_1_103.BytesReadAlluxio
192_168_1_103.BytesWrittenAlluxio
192_168_1_103.BlocksAccessed
192_168_1_103.BlocksCached
192_168_1_103.BlocksCanceled
192_168_1_103.BlocksDeleted
192_168_1_103.BlocksEvicted
192_168_1_103.BlocksPromoted
然后访问 http://192.168.1.101:19999/metrics/json/ 可得到监控信息
喜欢看源码的小伙伴可以戳这里哟->Alluxio源码入口
Alluixo审计日志
Alluxio提供审计日志来方便管理员可以追踪用户对元数据的访问操作。
开启审计日志: 讲JVM参数alluxio.master.audit.logging.enabled设为true
审计日志包含如下条目:
key | desc |
---|---|
succeeded | 如果命令成功运行,值为true。在命令成功运行前,该命令必须是被允许的。 |
allowed | 如果命令是被允许的,值为true。即使一条命令是被允许的它也可能运行失败。 |
ugi | 用户组信息,包括用户名,主要组,认证类型。 |
ip | 客户端IP地址。 |
cmd | 用户运行的命令。 |
src | 源文件或目录地址。 |
dst | 目标文件或目录的地址。如果不适用,值为空。 |
perm | user:group:mask,如果不适用值为空。 |
准备工作
1.下载Alluxio压缩包并上传到NN所在集群
2.解压并进入安装目录
tar -zxvf alluxio-2.0.1-bin.tar.gz -C /opt/module/
mv /opt/module/alluxio-2.0.1 /opt/module/alluxio
cd /opt/module/alluxio
cp conf/alluxio-site.properties.template conf/alluxio-site.properties
cp conf/alluxio-env.sh.template conf/alluxio-env.sh
常规集群参数配置
常规非高可用集群配置,针对1.x和2.x版本通用
conf/alluxio-env.sh
vim conf/alluxio-env.sh
ALLUXIO_HOME=/opt/module/alluxio-2.0.1
ALLUXIO_LOGS_DIR=/opt/module/alluxio-2.1.0/logs
ALLUXIO_MASTER_HOSTNAME=hadoop101
ALLUXIO_RAM_FOLDER=/mnt/ramdisk
ALLUXIO_UNDERFS_ADDRESS=hdfs://hadoop101:9000/alluxio
ALLUXIO_WORKER_MEMORY_SIZE=512MB
JAVA_HOME=/opt/module/jdk1.8.0_161
# 设置ALLUXIO_MASTER_JAVA_OPTS作用于master JVM
# 设置ALLUXIO_WORKER_JAVA_OPTS作用于worker JVM
# 以及ALLUXIO_JAVA_OPTS同时作用于master以及worker JVM
# 增加worker JVM GC事件的logging, 输出写至worker节点的logs/worker.out文件中
ALLUXIO_WORKER_JAVA_OPTS=" -XX:+PrintGCDetails -XX:+PrintTenuringDistribution -XX:+PrintGCTimestamps"
# 设置master JVM的的heap size
ALLUXIO_MASTER_JAVA_OPTS=" -Xms2048M -Xmx4096M"
conf/alluxio-site.properties
vim conf/alluxio-site.properties
# Common properties
alluxio.master.hostname=hadoop101
alluxio.master.mount.table.root.ufs=hdfs://192.168.1.101:9000/alluxio
alluxio.underfs.hdfs.configuration=/opt/module/hadoop-2.7.2/etc/hadoop/core-site.xml:/opt/module/hadoop-2.7.2/etc/hadoop/hdfs-site.xml
# Worker properties
alluxio.worker.memory.size=512MB
alluxio.worker.tieredstore.levels=1
alluxio.worker.tieredstore.level0.alias=MEM
alluxio.worker.tieredstore.level0.dirs.path=/mnt/ramdisk
vim conf/masters
hadoop101
vim conf/workers
hadoop102
hadoop103
scp -r /opt/module/alluxio/ root@hadoop102:/opt/module/
scp -r /opt/module/alluxio/ root@hadoop103:/opt/module/
# 打开Alluxio服务
alluxio format
alluxio-start.sh master
alluxio-start.sh workers NoMount
或直接 alluxio-start.sh all
访问Master节点的WEB UI: hadoop101:19999
访问Worker节点的WEB UI: hadoop102:30000
#测试部署是否成功
bin/alluxio runTests # 如果出现Passed the test则说明部署成功
bin/alluxio-stop.sh all # 关闭集群
出现类似以下界面即为部署成功
此时可以通过命令alluxio fsdamin report来查看集群状态
高可用集群参数配置
高可用(HA)通过支持同时运行多个master来保证服务的高可用性,多个master中有一个master被选为primary master作为所有worker和client的通信首选,其余master为备选状态(StandBy),它们通过和primary master共享日志来维护同样的文件系统元数据,并在primary master失效时迅速接替其工作(master主从切换过程中,客户端可能会出现短暂的延迟或瞬态错误)
搭建高可用集群前的准备:
①确保Zookeeper服务已经运行
②一个单独安装的可靠的共享日志存储系统(可用HDFS或S3等系统)
③这个配置针对Alluxio 2.x版本,不适用于1.x版本
④需要事先创建好ramdisk挂载目录
注意去掉中文注释 否则会报错
在所有机器上配置env.sh
vim alluxio-env.sh
ALLUXIO_HOME=/opt/alluxio
ALLUXIO_LOGS_DIR=/opt/alluxio/logs
ALLUXIO_RAM_FOLDER=/mnt/ramdisk
JAVA_HOME=/opt/module/jdk1.8.0_161
# 设置ALLUXIO_MASTER_JAVA_OPTS作用于master JVM
# 设置ALLUXIO_WORKER_JAVA_OPTS作用于worker JVM
# 以及ALLUXIO_JAVA_OPTS同时作用于master以及worker JVM
# 增加worker JVM GC事件的logging, 输出写至worker节点的logs/worker.out文件中
ALLUXIO_WORKER_JAVA_OPTS=" -XX:+PrintGCDetails -XX:+PrintTenuringDistribution -XX:+PrintGCTimestamps"
# 设置master JVM的的heap size
ALLUXIO_MASTER_JAVA_OPTS=" -Xms2048M -Xmx4096M"
在101机器上配置Master和Worker
vim alluxio-site.properties
# 192.168.1.101 Master Worker
# Common properties
alluxio.master.hostname=192.168.1.101 # 要写其他机器能识别的地址而非localhost等
alluxio.underfs.hdfs.configuration=/opt/module/hadoop-2.7.2/etc/hadoop/core-site.xml:/opt/module/hadoop-2.7.2/etc/hadoop/hdfs-site.xml # 如果底层HDFS存储为高可用,则要写hdfs配置文件地址
alluxio.master.mount.table.root.ufs=hdfs://hadoop101:9000/ # 指向高可用或非高可用的HDFS地址(可以是根目录,也可以是某个文件夹)
# Worker properties
alluxio.worker.memory.size=512MB
alluxio.worker.tieredstore.levels=1
alluxio.worker.tieredstore.level0.alias=MEM
alluxio.worker.tieredstore.level0.dirs.path=/mnt/ramdisk
# HA properties
alluxio.zookeeper.enabled=true
alluxio.zookeeper.address=192.168.1.101:2181,192.168.1.102:2181,192.168.1.103:2181 # Zookeeper地址中间逗号隔开
alluxio.master.journal.type=UFS
alluxio.master.journal.folder=hdfs://192.168.1.101:9000/alluxio/journal # 回滚日志的地址,写入可靠的分布式HDFS
alluxio.worker.block.heartbeat.timeout.ms=300000
alluxio.zookeeper.session.timeout=120s
# User properties
alluxio.user.file.readtype.default=CACHE_PROMOTE
alluxio.user.file.writetype.default=ASYNC_THROUGH
alluxio.user.metrics.collection.enable=true
alluxio.master.metrics.time.series.interval=1000
# Security properties
alluxio.security.authorization.permission.enabled=true
alluxio.security.authentication.type=SIMPLE
alluxio.master.security.impersonation.hive.users=* # 可以模拟很多用户来实现权限控制
alluxio.master.security.impersonation.hive.groups=*
alluxio.master.security.impersonation.yarn.users=*
alluxio.master.security.impersonation.yarn.groups=*
alluxio.master.security.impersonation.hdfs.users=*
alluxio.master.security.impersonation.hdfs.groups=*
在102机器上配置Master和Worker
vim alluxio-site.properties
# 192.168.1.102 Master Worker
# Common properties
alluxio.master.hostname=192.168.1.102 # 要写其他机器能识别的地址而非localhost等
alluxio.underfs.hdfs.configuration=/opt/module/hadoop-2.7.2/etc/hadoop/core-site.xml:/opt/module/hadoop-2.7.2/etc/hadoop/hdfs-site.xml
alluxio.master.mount.table.root.ufs=hdfs://hadoop101:9000/
# Worker properties
alluxio.worker.memory.size=512MB
alluxio.worker.tieredstore.levels=1
alluxio.worker.tieredstore.level0.alias=MEM
alluxio.worker.tieredstore.level0.dirs.path=/mnt/ramdisk
# HA properties
alluxio.zookeeper.enabled=true
alluxio.zookeeper.address=192.168.1.101:2181,192.168.1.102:2181,192.168.1.103:2181
alluxio.master.journal.type=UFS
alluxio.master.journal.folder=hdfs://192.168.1.101:9000/alluxio/journal
alluxio.worker.block.heartbeat.timeout.ms=300000
alluxio.zookeeper.session.timeout=120s
# User properties
alluxio.user.file.readtype.default=CACHE_PROMOTE
alluxio.user.file.writetype.default=ASYNC_THROUGH
alluxio.user.metrics.collection.enable=true
alluxio.master.metrics.time.series.interval=1000
# Security properties
alluxio.security.authorization.permission.enabled=true
alluxio.security.authentication.type=SIMPLE
alluxio.master.security.impersonation.hive.users=*
alluxio.master.security.impersonation.hive.groups=*
alluxio.master.security.impersonation.yarn.users=*
alluxio.master.security.impersonation.yarn.groups=*
alluxio.master.security.impersonation.hdfs.users=*
alluxio.master.security.impersonation.hdfs.groups=*
在103机器上配置Worker
vim alluxio-site.properties
# 192.168.1.103 Worker
# Common properties
# Worker不需要写alluxio.master.hostname参数和alluxio.master.journal.folder参数
alluxio.underfs.hdfs.configuration=/opt/module/hadoop-2.7.2/etc/hadoop/core-site.xml:/opt/module/hadoop-2.7.2/etc/hadoop/hdfs-site.xml
alluxio.master.mount.table.root.ufs=hdfs://hadoop101:9000/
# Worker properties
alluxio.worker.memory.size=512MB
alluxio.worker.tieredstore.levels=1
alluxio.worker.tieredstore.level0.alias=MEM
alluxio.worker.tieredstore.level0.dirs.path=/mnt/ramdisk
# HA properties
alluxio.zookeeper.enabled=true
alluxio.zookeeper.address=192.168.1.101:2181,192.168.1.102:2181,192.168.1.103:2181
alluxio.worker.block.heartbeat.timeout.ms=300000
alluxio.zookeeper.session.timeout=120s
# User properties
alluxio.user.file.readtype.default=CACHE_PROMOTE
alluxio.user.file.writetype.default=ASYNC_THROUGH
alluxio.user.metrics.collection.enable=true
alluxio.master.metrics.time.series.interval=1000
# Security properties
alluxio.security.authorization.permission.enabled=true
alluxio.security.authentication.type=SIMPLE
alluxio.master.security.impersonation.hive.users=*
alluxio.master.security.impersonation.hive.groups=*
alluxio.master.security.impersonation.yarn.users=*
alluxio.master.security.impersonation.yarn.groups=*
alluxio.master.security.impersonation.hdfs.users=*
alluxio.master.security.impersonation.hdfs.groups=*
在所有机器上指定Master和Worker节点
vim masters
192.168.1.101
192.168.1.102
vim workers
192.168.1.101
192.168.1.102
192.168.1.103
# 测试部署是否成功
alluxio format
alluxio-start.sh all SudoMount
alluxio fsadmin report
alluxio runTests # 如果出现Passed the test则说明部署成功
# 测试高可用模式的自动故障处理: (假设此时hadoop101位primary master)
ssh hadoop101
jps | grep AlluxioMaster
kill -9
alluxio fs leader # 显示新的primary Master(可能需要等待一小段时间选举)
部署说明
配置这块踩了好多坑,终于,Alluxio基本服务部署完毕,一些关于优化和细节的参数在Alluxio原理部分中涉及到,也可查阅Alluxio配置参数大全
Alluxio2.1.0版本官方介绍说使用ASYNC_THROUGH进行写入时防止数据丢失,所以我这里设置了ASYNC_THROUGH异步写磁盘,既能保证写入速度,又能将文件持久化
之前配置Alluxio高可用,一直不稳定,心跳中断,Master和Worker掉线问题频发,Alluxio2.1版本官方说修复了各种心跳中断问题,当然Alluxio的高可用要求底层的Journal日志存储系统的稳定性很高,如果底层Journal存储系统不稳定(比如HDFS No More Good DataNode的情况),就会导致Master崩溃。
Alluxio命令速查表包括缓存载入,驻留,释放,数据生存时间等重要命令
Alluxio常用Shell命令速查表:
#文件基本操作
可以在执行命令时指定参数 方法: alluxio fs -D...指定参数 copyFromLocal ....
alluxio fs cat # 打开文件
alluxio fs ls [-d|-f|-p|-R|-h|--sort=option|-r] #查看目录
alluxio fs copyFromLocal [--thread ] [--buffersize ] # 从本地上传文件到Alluxio
alluxio fs copyToLocal [--buffersize ] #从Alluxio载文件到本地
alluxio fs count # 统计Alluxio目录的文件数,文件夹数和总大小
alluxio fs du [-h|-s|--memory] # 文件大小
alluxio fs cp [-R] [--buffersize ] #复制文件
alluxio fs mv # 移动文件
alluxio fs rm [-R] [-U] [--alluxioOnly] # 删除文件
alluxio fs mkdir [path2] ... [pathn] # 创建文件夹
alluxio fs touch #创建一个空文件
alluxio fs setTtl [--action delete|free]
上面的命令不能帮到你? 那就戳这里:
Alluxio命令使用示例
管理员命令使用示例
Alluxio master提供了Web界面以便用户管理
Alluxio master Web界面的默认端口是19999:访问 http://MASTER IP:19999 即可查看
Alluxio worker Web界面的默认端口是30000:访问 http://WORKER IP:30000 即可查看
WEB UI官方介绍很明确->戳这里:Alluxio Web UI
Alluxio+Hive
频繁使用的表存在Alluxio上,可通过内存读文件获得更高的吞吐量和更低的延迟
准备工作:
cd /opt/module/hive
vim conf/hive-env.sh
export HADOOP_HOME=/opt/module/hadoop-2.7.2
# 添加
export HIVE_AUX_JARS_PATH=$ALLUXIO_HOME/client:$HIVE_AUX_JARS_PATH
四种情况:
创建一个Hive表并指定其存储在Alluxio
bin/hive
create table alluxio_test(
id int,
name string,
color string
)
row format delimited fields terminated by '\t'
LOCATION "alluxio://hadoop101:19998/user/hive/warehouse/alluxio_test";
# 查看表位置
describe extended alluxio_test;
已存在HDFS的内部表
bin/hive
describe extended table_name; # 查看Hive表存储位置
alter table table_name set location "alluxio://hadoop101:19998/user/hive/warehouse/table_name"
describe extended table_name;
msck repair table table_name; # 确定alluxio对应位置存在表数据后修复Hive表元数据
第一次访问alluxio中的文件默认会被认为访问hdfs的文件,一旦数据被缓存在Alluxio中,之后的查询数据都会从Alluxio读取。
已存在HDFS的外部表
bin/hive
describe extended table_name;
# 将表数据改为Alluxio存储
alter table table_name set location "alluxio://hadoop101:19998/user/hive/warehouse/table_name"
describe extended table_name;
# 还原表数据到HDFS
alter table table_name set location "hdfs://hadoop101:9000/user/hive/warehouse/table_name"
describe extended table_name;
Hive使用Alluxio作为默认存储系统
vim conf/hive-site.xml
# 添加以下属性
fs.defaultFS
alluxio://hadoop101:19998
Hive Use Alluxio As Default FileSystem
# 对Hive指定的Alluxio配置属性,将它们添加到每个结点的Hadoop配置目录下core-site.xml中。例如,将alluxio.user.file.writetype.default 属性由默认的MUST_CACHE修改成CACHE_THROUGH:
alluxio.user.file.writetype.default
CACHE_THROUGH
# Alluxio中为Hive创建目录
alluxio fs mkdir /tmp
alluxio fs mkdir /user/hive/warehouse
alluxio fs chmod 775 /tmp
alluxio fs chmod 775 /user/hive/warehouse
# 检查Hive与Alluxio的集成情况
integration/checker/bin/alluxio-checker.sh -h # 查看该命令帮助
integration/checker/bin/alluxio-checker.sh hive -hiveurl [HIVE_URL]
排坑:
安全认证问题:
alluxio-site.properties中添加要模拟的用户:
alluxio.master.security.impersonation.hive.users=*
alluxio.master.security.impersonation.hive.groups=*
alluxio.master.security.impersonation.yarn.users=*
alluxio.master.security.impersonation.yarn.groups=*
Alluxio+Spark
Spark可以在进行简单配置后直接使用Alluxio作为数据访问层,Spark应用程序可以通过Alluxio透明地访问许多不同类型的持久化存储服务(例如,AWS S3 bucket、Azure Object Store buckets、远程部署的 HDFS 等)的数据,也可以透明地访问同一类型持久化存储服务不同实例中的数据。为了加快I/O性能,用户可以主动获取数据到Alluxio中或将数据透明地缓存到Alluxio中,尤其是在Spark部署位置与数据相距较远时特别有效。此外,通过将计算和物理存储解耦,Alluxio 能够有助于简化系统架构。当底层持久化存储中真实数据的路径对 Spark 隐藏时,对底层存储的更改可以独立于应用程序逻辑;同时Alluxio作为邻近计算的缓存,仍然可以给计算框架提供类似 Spark 数据本地性的特性。
spark.driver.extraJavaOptions -Dalluxio.zookeeper.address=zkHost1:2181,zkHost2:2181,zkHost3:2181 -Dalluxio.zookeeper.enabled=true
spark.executor.extraJavaOptions -Dalluxio.zookeeper.address=zkHost1:2181,zkHost2:2181,zkHost3:2181 -Dalluxio.zookeeper.enabled=true
或者配置Hadoop文件core-site.xml如下
alluxio.zookeeper.enabled
true
alluxio.zookeeper.address
zkHost1:2181,zkHost2:2181,zkHost3:2181
自定义Spark作业中Alluxio的属性:val s = sc.textFile("alluxio://192.168.1.101:19998/LICENSE")
val double = s.map(line => line + line)
double.saveAsTextFile("alluxio://192.168.1.101:19998/out")
df = spark.table("select ...")
df.format.parquet("alluxio://xxxxx")
官方Alluxio+Spark配置设置
检查配置是否正确
在$ALLUXIO_HOME运行 integration/checker/bin/alluxio-checker.sh spark spark://sparkMaster:7077
使用
存储 RDD 到 Alluxio 内存中就是将 RDD 作为文件保存到 Alluxio 中:
saveAsTextFile:将 RDD 作为文本文件写入,其中每个元素都是文件中的一行
saveAsObjectFile:通过对每个元素使用 Java 序列化,将 RDD 写到一个文件中
// as text file
rdd.saveAsTextFile("alluxio://localhost:19998/rdd1")
rdd = sc.textFile("alluxio://localhost:19998/rdd1")
// as object file
rdd.saveAsObjectFile("alluxio://localhost:19998/rdd2")
rdd = sc.objectFile("alluxio://localhost:19998/rdd2")
缓存 Dataframe 到 Alluxio 中(将 DataFrame 作为文件保存到 Alluxio 中):
df.write.parquet("alluxio://localhost:19998/data.parquet")
df = sqlContext.read.parquet("alluxio://localhost:19998/data.parquet")
Alluxio对Shuffle的提升
目前三种方案:
一是基于Alluxio-Fuse客户端,无需修改源码,直接挂载Shuffle目录,但Alluxio-Fuse目前的性能不是很好
二是重写Spark Shuffle Service底层源码实现基于Alluxio Client的Shuffle
三是可以Splash Shuffle Manager插件,我的另一篇文章有讲到 -> QCon总结-Splash Shuffle Manager
当然也可以选择等Spark3.0的Remote Shuffle Service
Alluxio+HadoopMR
运行HadoopMR程序:
bin/hadoop jar ../libexec/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar wordcount -Dalluxio.user.file.writetype.default=CACHE_THROUGH -libjars /opt/module/alluxio/client/alluxio-2.0.1-client.jar \
Alluxio+Presto
后续更新…
使用官方提供的沙箱
申请官方测试沙箱Sandbox:ALLUXIO SANDBOX
申请成功后,按照邮件的指引操作,注意,bin/sandbox setup &的过程中千万不要Ctrl+C中止,部署完成状态如下图:
运行基准测试(TPC-DS),耐心等待后的测试结果:
已安装TPC-DS基准套件,用于运行性能测试。Spark已安装为TPC-DS用来将其作业发送到的计算框架。TPC-DS的比例因子为100,这与26GB的数据集大小相关。由索引单独标识的基准按不同的使用方案分组,并且将结果报告为每个方案的汇总。
其中 w/o是without,即只是用S3为直接底层存储的情况;w/是with,即使用了Alluxio作为中间件下的性能
从图中测试结果可以看出,当计算数据存储在公有云虚拟机实例中时,Alluxio作为存储与计算框架的中间件,能够有1.5-3倍左右的性能提升
受到各方面限制,以上测试结果并非Alluxio的最佳预期。其他人的试过程
自测
Spark Sql做测试时候多次重复作业输入数据位于OS的高速缓冲区,Alluxio没有加速效果甚至变慢
我的测试环境是三台机器,每台101GB内存,16核,同台机器部署CM Hadoop,Spark,Hive,AlluxioWorker,AlluxioClient
Alluxio读参数CACHE_PROMOTE,写参数CACHE_THROUGH
测试方法 | 测试操作 | 运行时间(HDFS) | 运行时间(Alluxio) | 表结构 |
---|---|---|---|---|
SparkSQL | select count(1) from table; | 4s | 6s | 13.5GB 17字段 |
SparkSQL | select count(1) from table; | 5s | 6s | 13.5GB 17字段 |
SparkSQL | select count(1) from table; | 6s | 8s | 13.5GB 17字段 |
SparkSQL | select first(ip),first(language),first(operation_channel),first(imei) from table group by product_name; | 80s | 80s | 13.5GB 17字段 |
SparkSQL | select first(ip),first(language),first(operation_channel),first(imei) from table group by product_name; | 77s | 52s | 13.5GB 17字段 |
SparkSQL | select first(ip),first(language),first(operation_channel),first(imei) from table group by product_name; | 60s | 73s | 13.5GB 17字段 |
SparkSQL | select count(1) from test.table group by language; | 11.5s | 11.5s | 13.5GB 17字段 |
Spark Persist | df.write.parquet(Path) | 3.0min | 4.0min | 13.5GB 17字段 |
Spark Persist | spark.read.parquet(Path).count() | 4s | 5s | 13.5GB 17字段 |
Spark Persist | spark.read.parquet(Path).count() | 6s | 6s | 13.5GB 17字段 |
后来又做了Spark Dataframe的Persist到MEMORY_ONLY和Persist到Alluxio,效果也不是很好,究其原因,我认为是我的HDFS DataNode已经和计算框架Spark部署在一起了,而且磁盘IO没有瓶颈,所以这不符合Alluxio的应用场景,从而没有令人满意的效果.
至于HDFS更快的原因,我想是Spark要读取的数据很可能已经存在OS的高速缓冲区
Alluxio还是要用对场景才行.
什么是Alluxio FUSE
Alluxio-FUSE可以在一台Unix机器上的本地文件系统中挂载一个Alluxio分布式文件系统。通过使用该特性,一些标准的命令行工具(例如ls、 cat以及echo)可以直接访问Alluxio分布式文件系统中的数据。此外更重要的是用不同语言实现的应用程序如C, C++, Python, Ruby, Perl, Java都可以通过标准的POSIX接口(例如open, write, read)来读写Alluxio,而不需要任何Alluxio的客户端整合与设置。
Alluxio FUSE局限性
Alluxio FUSE使用
integration/fuse/bin/alluxio-fuse mount mount_point [alluxio_path]
integration/fuse/bin/alluxio-fuse umount mount_point
integration/fuse/bin/alluxio-fuse stat
Java API
Alluxio提供了两种不同的文件系统API:Alluxio API和与Hadoop兼容的API,Alluxio API提供了更多功能,而Hadoop兼容API为用户提供了使用Alluxio的灵活性,无需修改使用Hadoop API编写的现有代码.
Maven项目依赖设置 pom.xml
4.0.0
com.my.alluxio
AlluxioTest
1.0-SNAPSHOT
org.alluxio
alluxio-core-client-fs
2.0.1
org.apache.hadoop
hadoop-hdfs
2.6.0
org.apache.hadoop
hadoop-client
2.6.0
org.apache.maven.plugins
maven-compiler-plugin
3.5.1
7
maven-assembly-plugin
IOTestUtil
jar-with-dependencies
make-assembly
package
single
Java读写文件API
import alluxio.AlluxioURI;
import alluxio.client.file.FileInStream;
import alluxio.client.file.FileOutStream;
import alluxio.exception.AlluxioException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.IOException;
/**
* HDFS & Allxuio IO读取文件测试工具 IO接口 文件API
*/
public class IOTestUtil {
public static void main(String[] args) throws IOException, AlluxioException {
String filePath = args[0];
HDFSUtil h = new HDFSUtil("hdfs://192.168.1.101:8020");
h.readFile(filePath);
AlluxioUtil a = new AlluxioUtil();
a.readFile(filePath);
System.out.println("读文件测试 Finished");
System.out.println("------------------------");
if (args.length != 1){
String fileToWritePath = args[1];
a.writeFile(fileToWritePath);
System.out.println("写文件测试 Finished");
}
}
}
class HDFSUtil{
private Configuration conf = new Configuration();
public HDFSUtil(String HDFSURL){
conf.set("fs.defaultFS",HDFSURL);
System.setProperty("HADOOP_USER_NAME","hdfs");
}
public void readFile(String path) throws IOException {
FileSystem fs = FileSystem.get(conf);
fs.getFileStatus(new Path(path));
FSDataInputStream in = fs.open(new Path(path));
try{
long hdfsStartTime=System.currentTimeMillis();
in = fs.open(new Path(path));
byte[] buffer = new byte[1024];
int byteRead = 0;
while ((byteRead = in.read(buffer)) != -1) {
System.out.write(buffer, 0, byteRead); //输出字符流
}
long hdfsEndTime=System.currentTimeMillis();
System.out.println("HDFS读取运行时间:"+(hdfsEndTime-hdfsStartTime)+" ms");
}catch (Exception e){
e.printStackTrace();
} finally {
in.close();
}
}
}
class AlluxioUtil{
private static final alluxio.client.file.FileSystem fs = alluxio.client.file.FileSystem.Factory.get();
public AlluxioUtil(){}
public FileInStream readFile(String AlluxioPath) throws IOException, AlluxioException {
AlluxioURI path = new AlluxioURI(AlluxioPath); //封装Alluxio 文件路径的path
FileInStream in = fs.openFile(path);
try{
long startTime=System.currentTimeMillis();
in = fs.openFile(path);
// 调用文件输入流FileInStream实例的read()方法读数据
byte[] buffer = new byte[1024];
int byteRead = 0;
// 读入多个字节到字节数组中,byteRead为一次读入的字节数
while ((byteRead = in.read(buffer)) != -1) {
System.out.write(buffer, 0, byteRead); //输出字符流
}
long endTime=System.currentTimeMillis();
System.out.println("Alluxio读取运行时间:"+(endTime-startTime)+" ms");
}catch (IOException | AlluxioException e){
e.printStackTrace();
}finally {
in.close();
}
in.close(); //关闭文件并释放锁
return in;
}
public void writeFile(String AlluxioPath) throws IOException, AlluxioException {
AlluxioURI path = new AlluxioURI(AlluxioPath); // 文件夹路径
FileOutStream out = null;
try {
out = fs.createFile(path); //创建文件并得到文件输入流
out.write("qjj1234567".getBytes()); // 调用文件输出流FileOutStream实例的write()方法写入数据
}catch (IOException | AlluxioException e){
e.printStackTrace();
}finally {
out.close(); // 关闭和释放文件
}
}
}
Python API
Alluxio的Python库基于REST API实现的
CentOS6和Windows的环境下安装alluxio的python库失败,最终在CentOS7 Python2.7.5的环境下成功执行了pip install alluxio
if __name__ == '__main__':
print("后续用到API再更新")
pass