分布式缓存:Alluxio
已经有的开源为什么还要进行开发:
基于开源来做的一个内部应用场景,就像sylph一样(也是开源的)
最终的目标:
1.为HDFS迁移未来一段时间数据的跨机房访问做缓冲;
2.对同机房数据的访问做加速缓冲;
什么是Alluxio:
->Alluxio是世界上第一个以内存为中心的虚拟的分布式存储系统(面向基于云的数据分析和人工智能的开源的数据编排技术),为上层计算框架(数据驱动型应用)和底层存储系统构建了桥梁;
->应用程序能够通过一个公共接口连接到许多存储系统,Alluxio内存至上的层次化架构使得数据的访问速度能比现有方案快几个数量级;
在大数据生态系统中,Alluxio位于计算框架(数据驱动框架或应用如Apache Spark、Presto、Tensorflow、Apache HBase、Apache Hive或Apache Flink)和各种持久化存储系统(如Amazon S3、Google Cloud Storage、OpenStack Swift、HDFS、GlusterFS、Ceph...)之间;
为什么是Alluxio:
通过简化应用程序访问其数据的方式(无论数据是什么格式或位置),Alluxio能够帮助克服从数据中提取信息所面临的困难:
->内存速度I/O:内存的高I/O吞吐率;层次化存储机制能够成功利用内存
固态硬盘或磁盘;
->简化云存储和对象存储接入:与传统文件相比,云存储系统和对象存储系统使用不同的语义,即其对性能等影响也不同(在云存储和对象存储系统上进行常见的文件系统操作,如李处目录和重命名等,通常会导致显著的性能开销) -> 将Alluxio与云存储或对象存储一起部署可以缓解这些问题:即从Alluxio中检索读取数据,而不是从底层云存储或对象存储中检索读取;
->应用程序部署简易:Alluxio管理应用程序和文件或对象存储之间的通信,将应用程序的数据访问请求转换为底层存储接口的请求;Alluxio与Hadoop生态系统兼容,现有的数据分析应用程序,如Spark和MR等,无需更改任何代码就能在Alluxio上运行;
Alluxio快速入门:
https://docs.alluxio.io/os/user/stable/cn/Getting-Started.html
1.配置Alluxio:
$ cp conf/alluxio-site.properties.template conf/alluxio-site.properties
$ echo "alluxio.master.hostname=localhost" >> conf/alluxio-site.properties
[添加AWS相关配置,为后续使用官网提供的AWS上的测试沙箱使用:
$ echo "aws.accessKeyId=<AWS_ACCESS_KEY_ID>" >> conf/alluxio-site.properties
$ echo "aws.secretKey=<AWS_SECRET_ACCESS_KEY>" >> conf/alluxio-site.properties
]
$ ./bin/alluxio validateEnv local
该命令将汇报在本地环境运行Alluxio可能出现的问题
2.启动Alluxio:
$ ./bin/alluxio format
在启动Alluxio进程前,需要通过该命令格式化Alluxio的日志和worker存储目录
$ ./bin/alluxio-start.sh local SudoMount
默认配置下,通过该命令可以在localhost启动Alluxio
Alluxio启动运行后:
localhost:19999 -> 查看Alluxio master的运行状态;
localhost:30000 -> 查看Alluxio worker的运行状态
3.使用Alluxio Shell:
$ ./bin/allluxio fs
查看文件系统操作命令列表
$ ./bin/alluxio fs ls /
ls命令列出Alluxio中根目录下的文件,包括文件的大小、创建的日期、文件的所有者和组以及Alluxio中这个文件的缓存占比。
$ ./bin/alluxio fs copyFromLocal LICENSE /LICENSE
copyFromLocal命令可以拷贝本地文件到Alluxio中
->注:默认设置中,Alluxio使用本地文件系统作为底层文件系统(UFS)。默认的UFS路径是./underFSStorage:
$ ls ./underFSStorage -> 查看UFS中的内容
$ ./bin/alluxio fs persist /LICENSE
通过该命令将文件从Alluxio空间持久化到UFS(将Alluxio中的数据持久化到底层文件系统中)
4.Alluxio中的挂载功能:
$ ./bin/alluxio fs mkdir /mnt
通过该命令在Alluxio中创建一个目录(目录可以用作挂载点)
$ ./bin/alluxio fs mount --readonly alluxio://localhost:19998/mnt/s3 s3://alluxio-quick-start/data
->mount:(即可以让其他存储系统中的数据在Alluxio中也能获取)
mount命令将一个底层存储中的路径链接到Alluxio路径,并且在Alluxio中该路径下创建的文件和文件夹会在对应的底层文件系统路径进行备份;
--readonly选项在Alluxio中设置挂载点为只读;
--option <key>=<val>选项传递一个属性到这个挂载点(如S3 credential)
$ ./bin/alluxio fs mount /mnt/hdfs hdfs://host1:9000/data/
$ ./bin/alluxio fs mount --shared --readonly /mnt/hdfs2 hdfs://host2:9000/data/
$ ./bin/alluxio fs mount --option aws.accessKeyId=<accessKeyId> \ --option aws.secretKey=<secretKey> /mnt/s3 s3://data-bucket/
$ ./bin/alluxio fs ls -R /
通过Alluxio统一命名空间,可以无缝地从不同存储系统中交互数据。例如:使用ls -R 命令,可以递归地列举出一个目录下的所有文件。
5.用Alluxio加速数据访问:
查看$ ./bin/alluxio fs ls /mnt/s3/sample_tweets_150m.csv的状态:
输出显示了文件Not In Memory(%0 不在内存中),该文件是推特的样本,我们统计一下有多少推文提到了单词"kitten",并计算该操作的耗时
$ time ./bin/alluxio fs cat /mnt/s3/sample_tweets_150m.csv | grep -c kitten
->Alluxio可以提供访问该数据的速度:
在通过cat 命令获取文件后,你可以用ls命令查看文件的状态:
$ ./bin/alluxio fs ls /mnt/s3/sample_tweets_150m.csv
输出显示文件已经100%被加载到Alluxio中了,即再次访问该文件的速度应该会快很多,例如,我们统计一下拥有"puppy"这个单词的在推文中出现的次数:
$ time ./bin/alluxio fs cat /mnt/s3/sample_tweets_150m.csv | grep -c puppy
6.关闭Alluxio:
$ ./bin/alluxio-stop.sh local
编译Alluxio源代码:
Checkout源码:
$ git clone git@github.com:3286360470/alluxio.git
$ cd alluxio
使用Maven编译源码:
$ mvn clean install -DskipTests
通过如下指令跳过不同的检查:
$ mvn -T 2C clean install -DskipTests -Dmaven.javadoc.skip -Dfindbugs.skip -Dcheckstyle.skip -Dlicense.skip
验证Alluxio编译完成:
$ echo "alluxio.master.hostname=localhost" > conf/alluxio-site.properties
$ ./bin/alluxio format
$ ./bin/alluxio-start.sh local
访问localhost:19999或者查看alluxio/logs目录下的日志文件,或者执行下面的简单程序:
$ ./bin/alluxio runTests -> 运行结果Passed the test即编译完成
$ ./bin/alluxio-stop.sh local 停止Alluxio
编译选项:
编译后位于/<PATH_TO_ALLUXIO>/client/alluxio-2.1.0-client.jar的Alluxio客户端jar包将适用于不同的计算框架(如:Spark、Flink、Presto等)
Hadoop发行版的支持: 要针对Hadoop发行版本中某一个版本构建Alluxio可以通过如下命令指定
$ mvn install -P<HADOOP_PROFILE> -Dhadoop.version=<HADOOP_VERSION> -DskipTests
->注:所有Apache发行版都可以直接使用
-Phadoop-1 -Dhadoop.version=1.0.4
-Phadoop-1 -Dhadoop.version=1.2.0
...
-Phadoop-3 -Dhadoop.version=3.0.0
->Cloudera发行版,版本号格式:$apacheRelease-cdh$cdhRelease
-Phadoop-2 -Dhadoop.version=2.3.0-cdh5.1.0
...
->Hortonworks发行版,版本号格式:$apacheRelease.$hortonRelease
-Phadoop-2 -Dhadoop.version=2.1.0.2.0.5.0-67
...
——>注:执行上面命令时可能会出现maven-shadded-plugin执行出错的异常,通过下面命令强制加载最新的jar包来解决问题:
mvn install -Phadoop-2 -Dhadoop.version=2.6.0-cdh5.14.4 -Djar.forceCreation -Dmaven.javadoc.skip=true -DskipTests -e
mvn -T 2C clean install -DskipTests -Dmaven.javadoc.skip -Dfindbugs.skip -Dcheckstyle.skip -Dlicense.skip -Phadoop-2 -Dhadoop.version=2.6.0-cdh5.14.4
编译后的源码工程导入idea:
Import existing project;
Maven Projects -> developer;
Maven Targets and Plugins:
$ cd ${ALLUXIO_HOME}
Checkstyle: 确保代码是遵循官方约定的形式运行
$ mvn checkstyle:checkstyle
FindBugs: 在提交代码之前,针对findbugs插件运行最新的代码,保证没有新的warnings引入
$ mvn compile findbugs:findbugs
Compilation: 使用如下命令更简洁的编译代码
$ mvn clean compile -DskipTests
可以使用如下命令加速编译:
$ mvn -T 2C compile -DskipTests -Dmaven.javadoc.skip -Dfindbugs.skip -Dcheckstyle.skip -Dlicense.skip -pl '!webui'
-T 2C 以每核CPU至少两个线程的方式运行maven;
-DskipTests 跳过单元和集成测试;
-Dmaven.javadoc.skip 跳过javadoc的生成;
-Dfindbugs.skip 跳过findbugs执行;
-Dcheckstyle.skip 跳过code-style检查;
-Dlicense.skip 跳过检查文件并获得许可证;
-pl '!webui' 跳过Alluxio UI模块的构建(如果这个跳过了,则不能本地访问UI)
Creating a Local install:(你可以通过Maven install来在本地进行编译测试)
$ mvn -T 2C install -DskipTests
通过如下命令来配置本地环境:
$ cp conf/alluxio-site.properties.template conf/alluxio-site.properties
$ echo "alluxio.master.hostname=localhost" >> conf/alluxio-site.properties
$ ./bin/alluxio format
如果已经做过上面的配置了,则可以直接启动一个本地的Alluxio:
$ ./bin/alluxio-start.sh local SudoMount
Unit Tests:
$ cd ${ALLUXIO_HOME}
$ mvn test
使用本地filesystem作为底层存储:
运行一个简单的单元测试:
$ mvn -Dtest=<AlluxioTestClass>#<testMethod> -DfailIfNoTests=false test
对于指定模块来运行单元测试:
$ mvn test -pl underfs/hdfs
在不同的Hadoop版本对HDFS UFS进行单元测试:
$ mvn test -pl underfs/hdfs -Phadoop-2 -Dhadoop.version=2.7.0
$ mvn test -pl underfs/hdfs -Phadoop-3 -Dhadoop.version=3.0.0
利用真实环境中的运行的HDFS进行测试:
$ mvn test -pl underfs/hdfs -PufsContractTest -DtestHdfsBaseDir=hdfs://ip:port/alluxio_test
可以通过如下参数将日志输出到STDOUT:
-Dtest.output.redirect=false -Dalluxio.root.logger=DEBUG,CONSOLE
Alluxio命令行接口:
https://docs.alluxio.io/os/user/stable/cn/basic/Command-Line-Interface.html#mount
命令列表:
General operations:
extensions
format:(注:format只在第一次运行Alluxio之前进行格式化,并且format应该在cluster未运行的时候进行格式化)
格式化Alluxio master和它的workers;
执行命令后,所有的信息都会被删除
-s -> 只格式化本地和尚未存在的底层存储
$ ./bin/alluxio format
$ ./bin/alluxio format -s
formatMaster:(注:formatMaster应该在cluster未运行的时候进行格式化)
格式化Alluxio master;
执行命令后,所有的信息都会被删除
Alluxio master存储如下的元数据:
文件系统操作;
文件分布在哪些workers;
journal 日志交易;
底层存储文件元数据
formatWorker:(注:formatWorker应该在cluster未运行的时候进行格式化)
格式化Alluxio worker
执行命令后,所有该worker上的信息都会被删除
$ ./bin/alluxio formatWorker
bootstrapConf:
生成bootstrap配置文件${ALLUXIO_HOME}/conf/alluxio-env.sh并指定确认的值ALLUXIO_MASTER_HOSTNAME(当配置文件不存在的时候)
$ ./bin/alluxio bootstrapConf <ALLUXIO_MASTER_HOSTNAME>
fs
文件系统操作指令
fsadmin
getConf
job
logLevel
runClass
runTests
runJournalCrashTest
runMesosTest
runUfsTests
readJournal
upgradeJournal
killAll
copyDir
clearCache
confDocGen
table
version
validateConf
validateEnv
File System Operations:
cat
checkConsistency
checksum
chgrp
chmod
chown
copyFromLocal
copyToLocal
count
cp
du
fileInfo
free
getCapacityBytes
getUsedBytes
help
leader
load
loadMetadata
location
ls
masterInfo
mkdir
mount
mv
persist
pin
rm
setTtl
stat
tail
test
touch
unmount
unpin
unsetTtl
Table Operations:
attachdb
detachdb
ls
sync
transorm
Alluxio架构原理:(Architecture And Data Flow,链接:https://docs.alluxio.io/os/user/stable/en/Architecture-DataFlow.html)
首次访问时,仅从底层文件系统读取一次数据;
为了达到更好的效果,建议将Alluxio与计算框架部署在一个集群中
Alluxio components:
masters
leading master:(master -> RPC Service + File System Metadata + Block Metadata + Worker Metadata 和底层以及journal存储进行交互)
-> 负责管理系统的 global metadata (包括文件系统metadata,如文件系统的索引节点树;block metadata,如块位置;worker容量metadata,如空闲和使用空间)
-> 维护所有文件系统的事务操作记录 即 journal日志
standby masters:(master -> File System Metadata + Block Metadata + Worker Metadata 和journal存储进行交互)
-> 保证Alluxio的HA模式(statndby masters读取leading master维护的journals日志,以此来保持和leading master的状态是一致的,但他们并不处理任何来自其他Alluxio组件的请求,只有当leading master挂掉了,stantdby masters会重新选出leading master)
secondary masters(for UFS journal):
-> 主要目的是为Alluxio提供了一个检查点(每个leading node会在本地磁盘持久化下面两个文件:
fsimage: node启动时对整个文件系统的快照;
edit logs: node启动后,对文件系统的改动序列;
只有在node重启时,edit logs才会合并到fsimage文件中,从而得到一个文件系统的最新快照。
)
job masters:(master -> RPC Service + Job Metadata)
-> 负责调度重量级文件系统操作,将各请求操作分配给各Job workers
workers
Alluxio wrokers:(worker -> RPC/Data Service + Block Metadata + Block Metadata)
-> 负责管理本地可配置的资源;
-> workers只负责管理 blocks(实际的files到blocks的映射只存储在master上);
-> workers在底层存储上执行数据操作;
从底层存储读取并存储在worker中的数据对于clients来说立即可用;
client可以是轻量级的,并且不依赖于任何底层存储;
-> workers对于RAM的容量管理(https://docs.alluxio.io/os/user/stable/en/advanced/Alluxio-Storage-Management.html#multiple-tier-storage)
Alluxio job workers:(worker -> RPC Service + Task List + Alluxio Client 和底层以及RAM/SSD/HDD存储进行交互)
-> 负责运行 Job master给他们分配的任务(接收 load, persist, replicate, move, copy等操作在给定的文件系统位置的 指令)
clients
应用程序(Spark、MR等)通过clients与Alluxio servers进行交互
Data flow:Read
Local Cache Hit:
-> 发生在请求的数据 就存储在 本地(client 和 worker在一台机器上)的Alluxio worker上(客户端通过"短路"读取来绕过Alluxio worker,直接读取文件系统上的文件)
Remote Cache Hit:
-> 发生请求的数据存储在Alluxio,但不在client所在机器的worker上(client在完成读数据之后,clients指令local worker复制数据在本地的worker上)
Cache Miss:
-> 数据不在Alluxio中,就会发生 cache miss 并且应用会从底层存储访问数据
cache需要从底层存储拉取数据,此时,带宽就成为了影响性能的瓶颈:
通过设置worker的alluxio.worker.network.async.cache.manager.threads.max
Cache Skip:
-> 通过设置client的alluxio.user.file.readtype.default=NO_CACHE来调整其带来的影响来关闭Alluxio缓存
Data flow:Write
通过设置client的alluxio.user.file.writetype.default配置来选择写数据的类型。
Write to Alluxio only (MUST_CACHE):
-> Alluxio client仅向local Alluxio worker写入数据,不会有数据向底层存储写入(MUST_CACHE对于临时数据写入且对数据的容错率低是有用的)
Write through to UFS (CACHE_THROUGH):
->
Write back to UFS (ASYNC_THROUGH):
-> 数据首先会同步的写入worker,并且会在后台同步到底层存储
Write to UFS Only (THROUGH):
-> 数据直接写入底层存储,而不被缓存在Alluxio的workers中
FAQ:
->Alluxio运行在什么平台和Java版本上:
JVM1.8
Linux / MacOS
->当新节点加入的时候,Alluxio会重新分配cached blocks来使内存使用均衡:
当前版本尚不支持
->怎样支持其他底层存储系统:
许多contributors正在开发;
开发支持其他存储系统的文档(https://docs.alluxio.io/os/user/stable/en/ufs/Ufs-Extension-API.html)
->如何向官方Alluxio提交代码:
contributor guide: https://docs.alluxio.io/os/user/stable/en/contributor/Contributor-Getting-Started.html
->AWS访问凭证:(https://docs.aws.amazon.com/zh_cn/sdk-for-java/v1/developer-guide/signup-create-iam-user.html)
注册 AWS
打开 https://aws.amazon.com/ 并单击注册。
按照屏幕上的说明进行操作。在注册过程中,您会接到一个电话,需要您使用电话按键输入 PIN 码。
接着,创建一个 IAM 用户并下载 (或复制) 它的秘密访问密钥。
创建 IAM 用户
转到 IAM 控制台(您可能需要首先登录 AWS)。
单击侧边栏中的用户以查看您的 IAM 用户。
如果您未设置任何 IAM 用户,则单击创建新用户以创建一个用户。
在列表中选择您将用来访问 AWS 的 IAM 用户。
打开安全凭证选项卡,然后单击创建访问密钥。
ETL平台工程学习:
public class URLClassLoader extends SecureClassLoader {}
public class SecureClassLoader extends ClassLoader {}
-> ClassLoader只能加载classpath下面的类,而URLClassLoader可以加载任意路径下的类:
一般动态加载类都是直接用Class.forName()方法,但此方法只能创建程序中已经引用的类,并且只能用包名的方法进行索引,不能对一个.class文件或者一个不在程序引用里的.jar包中的类进行创建;
URLClassLoader提供了这个功能,即可以通过以下几种方式进行加载:
*文件:(从文件系统目录加载)
*jar包:(从Jar包进行加载)
*Http:(从远程的Http服务进行加载)
ImmutableList是一个不可变、线程安全的列表集合,它只会获取传入对象的副本,而不会影响到原来的变量或对象:(有两种方法创建不可变对象)
静态内部类Builder:ImmutableList.<String>builder().add().add()....build();
静态of方法
双冒号运算符:
类名::方法名 -> 这样的式子表示不一定会调用这个方法,这种式子一般是用做Lambda表达式,而且Lambda有所谓的懒加载嘛,即不要括号,就是说看情况调用
例:
person -> person.getAge();
可以替换成:
person::getAge
() -> new HashMap<>();
可以替换成:
HashMap::new
这种[方法引用]或者说[双冒号运算]对应的参数类型是Function<T, R> T表示传入类型,R表示返回类型。比如表达式 person -> person.getAge(); 传入参数是person,返回值是person.getAge().
Gadtry是一个构建于java8之上的工具类库,涵盖了Ioc, Aop, exec, graph等等工具库(com.github.harbby.gadtry)
ObjectMapper初始化:
@Bean(name = "mapper")
public ObjectMapper objectMapper() {
return new ObjectMapper()
.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}