使用 JuiceFS Hadoop Java SDK
我们推荐以 Hadoop SDK 的方式在 Hadoop 下使用 JuiceFS。理论上你也可以通过 RawLocalFileSystem
让 HDFS 通过 FUSE mount 接入 JuiceFS,但受限于 HDFS 的实现,这样的实践存在性能问题,不推荐使用。
JuiceFS Hadoop Java SDK 不会自动去创建文件系统对应的 bucket,需要提前创建好。
与 HDFS 的区别
JuiceFS 与 HDFS 在某些方面有所不同,使用前请先了解。
用户组管理
Hadoop 中用户组信息是可配置的(hadoop.security.group.mapping
),默认使用系统用户组信息(ShellBasedUnixGroupsMapping
),HDFS 使用的是 NameNode 所在节点的用户组信息,通过管理命令(hdfs dfsadmin -refreshUserToGroupsMappings
)来刷新缓存。
JuiceFS 默认使用的是每个客户端在创建时所在节点的用户组信息,无法刷新。当要修改用户组信息时,需要同步到所有部署 JuiceFS 的节点,并重启使用 JuiceFS 的服务,因此我们推荐将该信息用下方的手段实现动态配置。
JuiceFS Hadoop SDK 可以通过指定配置文件来设置用户组信息,可以将 group 配置文件放置在 JuiceFS 上。这样所有节点就都可以读取同一份 group 配置文件,当需要向修改用户组配置的时候,也只需要修改此配置文件,所有 JuiceFS 客户端会在 2 分钟内自动更新信息,无需重启服务。具体操作如下:
在所有节点修改
core-site.xml
,添加如下配置:<property>
<name>juicefs.grouping</name>
<value>jfs://{VOL_NAME}/etc/group</value>
</property>在 JuiceFS 上创建
juicefs.grouping
所指向的配置文件修改此文件,添加用户组信息,格式如下:
groupname:username1,username2
内存使用
JuiceFS Hadoop SDK 需要额外使用 300~500 MiB 内存用来预读数据,提高性能。所以比如在使用 Spark 的时候,建议每个 executor 配置多个 CPU。因为每个 executor 使用一个 JuiceFS 客户端,一个 executor 内多个 task 可以共享这部分内存。
hflush 实现
当客户端 commit 时,会调用 HDFS 的 hflush
方法,JuiceFS 与 HDFS 在 hflush
的实现上有别:
HDFS 是将数据提交到多台 datanode 的内存里就算成功,因此时延比较低。提交完成以后,数据就对其他客户端可见。
JuiceFS 的 hflush
有多种模式,通过参数 juicefs.hflush
设置:
writeback
(默认)此模式下调用
hflush
接口只会将数据提交到本地磁盘(后台有线程会异步将数据上传到对象存储),但在客户端异常退出的情况下,可能由于部分数据没来得及上次对象存储而导致数据丢失。开启 writeback 以后,可以通过
juicefs.hflush-delay
来控制hflush
间隔,定时将数据写入本地缓存盘。该配置默认为 0,表示立即写入本地缓存盘。sync
此模式下调用
hflush
接口会同步地将数据提交到对象存储。但由于是数据需要提交到对象存储,不可避免的有较高的时延,但有更强的一致性保证。
缓存调优
JuiceFS 具有强大的缓存功能,在缓存一章里详细介绍,此处仅针对性补充 Hadoop 场景下的一些实践。与 JuiceFS Linux 客户端类似,Hadoop SDK 能调整各种缓存参数,详见参数配置。
单机缓存
为了使单机缓存能更好的被利用,JuiceFS 给每个 128MB 的逻辑文件块(同 HDFS 的 block)分配一个 BlockLocation
信息,Spark、MR、Presto 等计算引擎会利用此信息将任务调度到同一台机器上,读缓存就会生效。BlockLocation
是通过预先知道的机器列表算出来的,使用一致性哈希算法,减少机器上下线导致的缓存失效。JuiceFS 可以通过 YARN、Spark、Presto 等提供的接口获得计算节点列表,通过 juicefs.discover-nodes-url
参数设置。
分布式缓存
请先详读「分布式缓存」了解更多信息。
在 Hadoop SDK 中可以通过设置 juicefs.cache-group
来启用,设置了相同名字的机器组成一个共享缓存组。这种共享缓存模式比较适合 JuiceFS 客户端比较固定的情况,比如 Presto、Spark Thrift Server 等。而对于动态伸缩的计算集群,比如 Spark on Kubernetes,用专门的缓存集群更为合适。将计算集群的 juicefs.cache-group
设置为和缓存集群一样的名字,同时将计算集群的 juicefs.no-sharing
设置为 true
。这样一来,计算集群完全不参与构建缓存组,只从缓存集群读取数据并缓存在它的本地磁盘。
用类似下方的挂载命令来创建缓存集群:
sudo juicefs mount $VOL_NAME /jfs --cache-dir=xxx --cache-size=xxx --cache-mode=0777 --cache-group=xxx
准备工作
JuiceFS Hadoop SDK 需要通过外网访问 JuiceFS 元数据服务,需要部署 NAT 等给 Hadoop 集群提供外网访问能力。
JuiceFS 的元数据服务部署在与客户相同的公有云和相同区域中(可能是不同可用区),JuiceFS Hadoop SDK 是通过外网出口访问区域内的服务。如果 JuiceFS 元数据服务私有化部署在内网,则无此要求。
自动安装 JuiceFS Hadoop SDK
Python 脚本安装
安装脚本 setup-hadoop.py
,在 Cloudera Manager 节点、Ambari 节点或者公有云 EMR Master 节点上按下面步骤运行安装。
此脚本使用 Python 编写,支持 Python 2 和 Python 3。可以自动下载并安装 juicefs-hadoop.jar
,并且自动安装部署到整个集群,同时也可以自动部署 JuiceFS 相关配置到 core-site.xml
(仅支持 HDP 和 CDH)。
使用说明
python setup-hadoop.py COMMAND
COMMAND could be:
-h 显示帮助信息
install 在本机安装 JuiceFS JAR
install_all 在所有机器上安装 JuiceFS JAR, 需要把脚本运行节点和其他节点的 root 用户 SSH 打通
config 自动填写配置,目前支持 Ambari 和 ClouderaManager
deploy_config 自动配置下发到部署了客户端的机器,目前支持 Ambari 和 ClouderaManager
test 验证 JuiceFS JAR 是否真确安装
test_all 验证所有机器 JuiceFS JAR 是否正确安装
使用步骤
安装 JAR 文件
python setup-hadoop.py install
此操作会将
juicefs-hadoop.jar
下载到/usr/local/lib
下,并在 Hadoop 各个发行版下面对应组件的lib/
目录下建立软连接,具体放置目录会在日志中打出。配置
python setup-hadoop.py config
此操作会自动将必要配置项写入 HDFS 的
core-site.xml
,并在日志中打印出来。对于 CDH 和 HDP 环境,运行此命令,并按照提示输入管理员的账号密码。如果在这台机器上成功执行过
juicefs auth
或juicefs mount
,会自动读取/root/.juicefs/
中的认证信息,然后通过 RESTful API 自动将配置项写入core-site.xml
。此操作还会按照
juicefs.cache-dir
配置的目录在机器上创建缓存目录。将 JAR 文件分发到整个集群
CDH 或者 HDP 环境,执行:
python setup-hadoop.py install_all
其他公有云 EMR 环境,执行:
export NODE_LIST=node1,node2
python setup-hadoop.py install_allApache Hadoop 社区版自定义安装,执行:
# 组件 classpath,用逗号隔开
export EXTRA_PATH=$HADOOP_HOME/share/hadoop/common/lib,$SPARK_HOME/jars,$PRESTO_HOME/plugin/hive-hadoop2
export NODE_LIST=node1,node2
python setup-hadoop.py install_all
此操作将会把
juicefs-hadoop.jar
和/etc/juicefs/.juicefs
通过scp
的方式安装部署到指定的节点上去。全新安装或者升级需要重启的相关服务
部署配置
需要到 CDH 或者 HDP,或者其他 EMR 管理界面操作。
无需重启组件
- HDFS
- HUE
- ZooKeeper
- YARN
需要重启组件
以下各组件服务,只有当用到 JuiceFS 时才需要重启。
Hive
如果启用 HA,可以通过滚动重启,不影响使用。
- Hive Metastore Server
- HiveServer2
Spark on YARN
如果只是使用
spark-sql -f
提交任务,则无需重启。- ThriftServer
Spark Standalone
- Master
- Worker
Presto
- Coordinator
- Worker
Impala
- Catalog Server
- Daemon
HBase
- Master
- RegionServer
Flume
手动安装 JuiceFS Hadoop SDK
- 下载最新的
juicefs-hadoop.jar
- 将下载的 JAR 文件路径加入到应用的
classpath
中,可通过hadoop classpath
命令查看classpath
路径。
一些组件有默认放置 JAR 文件的目录,放在那些目录中会被自动加入到 classpath
中。
JuiceFS Hadoop SDK 参数配置
将以下配置参数加入到 Hadoop 配置文件 core-site.xml
中。
核心配置
配置项 | 默认值 | 描述 |
---|---|---|
fs.jfs.impl | com.juicefs.JuiceFileSystem | 指定 jfs:// 这个存储类型所使用的实现。 |
fs.AbstractFileSystem.jfs.impl | com.juicefs.JuiceFS | MR 等应用需要指定 AbstractFileSystem 的实现 |
juicefs.token | 访问 JuiceFS 的凭证,在控制台的设置页或者访问控制页可以看到。 | |
juicefs.accesskey | 对象存储的访问 ID(Access Key ID)。如果计算节点已经有访问对象存储的权限,则无需提供。 | |
juicefs.secretkey | 对象存储的私钥 (Secret Access Key)。如果计算节点已经有访问对象存储的权限,则无需提供。 |
缓存配置
配置项 | 默认值 | 描述 |
---|---|---|
juicefs.cache-dir | 本地缓存目录,可以指定多个文件夹,用冒号 : 分隔,也可以使用通配符(比如 * )。通常应用没有权限创建这些目录,需要手动创建并给予 0777 权限,便于多个应用共享缓存数据 。 | |
juicefs.cache-size | 0 | 磁盘缓存容量,单位 MB。如果配置多个目录,这是所有缓存目录的空间总和。 |
juicefs.cache-replica | 1 | 磁盘缓存副本数。 |
juicefs.cache-group | 配置此项则使用 P2P cache,各个相同 group 之间的 JuiceFS 客户端可以共享缓存,推荐在主要使用 Spark 的环境使用此配置,因为 Spark 在单个任务处理多个小文件时,计算没有数据本地化。 | |
juicefs.cache-full-block | true | 是否缓存连续读数据,在磁盘空间有限或者磁盘性能低下的时候,设置为 false。 |
juicefs.memory-size | 300 | 预读最大使用内存量,单位 MB。 |
juicefs.auto-create-cache-dir | true | 是否自动创建缓存目录。为 false 时,它会忽略不存在的缓存目录。 |
juicefs.free-space | 0.2 | 最低剩余磁盘空间比例,当剩余磁盘空间低于这个比例时,它会清空缓存数据以释放空间,默认 20%。 |
juicefs.metacache | true | 是否启用元数据缓存。 |
juicefs.discover-nodes-url | 指定发现集群计算节点列表的方式,每 10 分钟刷新一次。 YARN: yarn Spark Standalone: http://spark-master:web-ui-port/json/ Spark ThriftServer: http://thrift-server:4040/api/v1/applications/ Presto: http://coordinator:discovery-uri-port/v1/service/presto/ |
其他配置
配置项 | 默认值 | 描述 |
---|---|---|
juicefs.access-log | 访问日志的路径。需要所有应用都有写权限,可以配置为 /tmp/juicefs.access.log 。该文件会自动轮转,保留最近 7 个文件。 | |
juicefs.debug | false | 是否启用 Debug 级别的日志。 |
juicefs.max-uploads | 50 | 单进程写入对象存储最大并发数 |
juicefs.superuser | hdfs | 超级用户 |
juicefs.bucket | 指定存储桶名称 | |
juicefs.upload-limit | 0 | 单进程写入对象存储速度限制,单位 byte/s |
juicefs.object-timeout | 5 | 访问对象存储单次读请求的最长时间,单位 秒 |
juicefs.external | false | 是否使用公网域名访问对象存储 |
juicefs.rsaPrivKeyPath | 用于数据存储加密的 RSA 密钥路径 | |
juicefs.rsaPassphrase | 用于数据存储加密的 RSA 密钥密码 | |
juicefs.file.checksum | false | 用于 Hadoop DistCp 时是否验证 checksum |
juicefs.grouping | 指定 group 文件放置位置,用来配置用户组和用户映射信息,推荐配置在 jfs://myjfs/etc/group 。文件内容格式:groupname:username1,username2 |
当使用多个 JuiceFS 文件系统时,上述所有配置项均可对单个文件系统指定,需要将文件系统名字 VOL_NAME
放在配置项的中间,比如:
<property>
<name>juicefs.{VOL_NAME}.token</name>
<value>false</value>
</property>
常见发行版手动配置方法
如果你不希望通过自动化脚本安装 Hadoop SDK,可以参考本节内容来进行手动安装。
CDH
使用 Parcel 安装
在 Cloudera Manager 节点下载 Parcel 和 CSD,将 CSD 文件放入的
/opt/cloudera/csd
目录,将 Parcel 文件解压并将内容放入/opt/cloudera/parcel-repo
目录。重启 Cloudera Manager
service cloudera-scm-server restart
激活 Parcel
打开 CDH 管理界面 → Hosts → Check for New Parcels → JuiceFS → Distribute → Active
添加服务
打开 CDH 管理界面 → 集群名 → Add Service → JuiceFS → 选择安装机器 → 配置缓存目录(
cache_dirs
)部署 JAR 文件
升级
如果需要升级,则下载新的 Parcel 文件,并进行第 3 步。
通过 Cloudera Manager 修改配置
Hadoop
CDH 5.x
通过 HDFS 服务界面修改
core-site.xml
常用配置
fs.jfs.impl=com.juicefs.JuiceFileSystem
fs.AbstractFileSystem.jfs.impl=com.juicefs.JuiceFS
juicefs.cache-size=10240
juicefs.cache-dir=xxxxxx
juicefs.cache-group=yarn
juicefs.discover-nodes-url=yarn
juicefs.accesskey=xxxxxx
juicefs.secretkey=xxxxxx
juicefs.token=xxxxxx
juicefs.access-log=/tmp/juicefs.access.logCDH 6.x
除了上述 5.x 内容外。您还需通过 YARN 服务界面修改
mapreduce.application.classpath
,增加以下配置$HADOOP_COMMON_HOME/lib/juicefs-hadoop.jar
HBase
通过 HBase 服务界面修改
hbase-site.xml
配置:
<property>
<name>hbase.rootdir</name>
<value>jfs://{VOL_NAME}/hbase</value>
</property>
<property>
<name>hbase.wal.dir</name>
<value>hdfs://your-hdfs-uri/hbase-wal</value>
</property>通过 ZooKeeper 客户端删除
zookeeper.znode.parent
配置的 znode(默认/hbase
),此操作将会删除原有 HBase 集群里的所有数据。 :::Hive
通过 Hive 服务界面修改
hive.metastore.warehouse.dir
,可修改 Hive 建表默认位置(非必须)jfs://myjfs/your-warehouse-dir
Impala
通过 Impala 服务界面修改 Impala 命令行参数高级配置
此参数可以使用
20 / 本地挂载磁盘数
来设置,修改此参数主要是为了增加 JuiceFS 的读取 IO 线程数。-num_io_threads_per_rotational_disk=4
Solr
通过 Solr 服务界面修改 Solr 服务环境高级配置代码段
hdfs_data_dir=jfs://myjfs/solr
最后重启集群,让配置修改生效。
HDP
将 JuiceFS 集成到 Ambari
下载 HDP 安装文件,解压后将内容放到
/var/lib/ambari-server/resources/stacks/HDP/{YOUR-HDP-VERSION}/services
下重启 Ambari
systemctl restart ambari-server
添加 JuiceFS 服务
打开 Ambari 管理界面 → Services → Add Service → JuiceFS → 选择安装机器 → 配置 → deploy
在配置步骤,主要是配置缓存目录(
cache_dirs
)和下载版本(download_url
)。如果 Ambari 没有外网,可以直接将下载好的 JAR 包收到放到
share_download_dir
下,默认为 HDFS 的/tmp
目录。升级 JuiceFS
修改
download_url
的版本号,保存并 Refresh configs。
通过 Ambari 修改配置
Hadoop
通过 HDFS 服务界面修改
core-site.xml
,具体配置见 详细配置表。MapReduce2
通过 MapReduce2 服务界面修改配置
mapreduce.application.classpath
,在末尾增加:/usr/hdp/${hdp.version}/hadoop/lib/juicefs-hadoop.jar
(变量无需替换)。Hive
通过 Hive 服务界面修改
hive.metastore.warehouse.dir
,可修改 Hive 建表默认位置(非必须):jfs://myjfs/your-warehouse-dir
如果配置了
Ranger
服务,则需要配置HIVE
服务ranger.plugin.hive.urlauth.filesystem.schemes
,追加jfs
支持ranger.plugin.hive.urlauth.filesystem.schemes=hdfs:,file:,wasb:,adl:,jfs:
Druid
通过 Druid 界面修改目录地址(如无权限,需手动创建目录):
"druid.storage.storageDirectory": "jfs://myjfs/apps/druid/warehouse"
"druid.indexer.logs.directory": "jfs://myjfs/user/druid/logs"HBase
通过 HBase 服务界面修改一下参数
hbase.rootdir=jfs://myjfs/hbase
hbase.wal.dir=hdfs://your-hdfs-uri/hbase-wal通过 ZooKeeper 客户端删除
zookeeper.znode.parent
配置的 znode(默认/hbase
),此操作将会删除原有 HBase 集群里的所有数据。Sqoop
使用 Sqoop 将数据导入 Hive 时,Sqoop 会首先把数据导入
target-dir
,然后在通过hive load
命令将数据加载到 Hive 表,所以使用 Sqoop 时,需要修改target-dir
。1.4.6
使用此版本的 Sqoop 时还需要修改
fs
, 此参数修改默认文件系统,所以需要将 HDFS 上面的mapreduce.tar.gz
复制到 JuiceFS 上的相同路径,默认目录在 HDFS/hdp/apps/${hdp.version}/mapreduce/mapreduce.tar.gz
。sqoop import \
-fs jfs://myjfs/ \
--target-dir jfs://myjfs/tmp/your-dir1.4.7
sqoop import \
--target-dir jfs://myjfs/tmp/your-dir
最后,重启相应服务让配置修改生效。
阿里云 EMR
新建 EMR 集群集成 JuiceFS
在 EMR 软件配置界面配置高级设置
在软件配置 → 高级设置 → 软件自定义配置填入以下配置,缓存配置按需修改。
[
{
"ServiceName": "HDFS",
"FileName": "core-site",
"ConfigKey": "fs.jfs.impl",
"ConfigValue": "com.juicefs.JuiceFileSystem"
},
{
"ServiceName": "HDFS",
"FileName": "core-site",
"ConfigKey": "fs.AbstractFileSystem.jfs.impl",
"ConfigValue": "com.juicefs.JuiceFS"
},
{
"ServiceName": "HDFS",
"FileName": "core-site",
"ConfigKey": "juicefs.cache-group",
"ConfigValue": "yarn"
},
{
"ServiceName": "HDFS",
"FileName": "core-site",
"ConfigKey": "juicefs.cache-dir",
"ConfigValue": "/mnt/disk*/jfs"
},
{
"ServiceName": "HDFS",
"FileName": "core-site",
"ConfigKey": "juicefs.cache-size",
"ConfigValue": "1000000"
},
{
"ServiceName": "HDFS",
"FileName": "core-site",
"ConfigKey": "juicefs.discover-nodes-url",
"ConfigValue": "yarn"
},
{
"ServiceName": "HDFS",
"FileName": "core-site",
"ConfigKey": "juicefs.token",
"ConfigValue": ""
},
{
"ServiceName": "HDFS",
"FileName": "core-site",
"ConfigKey": "juicefs.conf-dir",
"ConfigValue": "/etc/juicefs"
},
{
"ServiceName": "HDFS",
"FileName": "core-site",
"ConfigKey": "juicefs.access-log",
"ConfigValue": "/tmp/juicefs.access.log"
}
]在基础信息界面的高级设置里面添加引导操作
下载
emr-boot.sh
脚本和juicefs-hadoop.jar
,并上传到您的对象存储上。「脚本位置」填写
emr-boot.sh
在 OSS 上面的地址,「参数」填写juicefs-hadoop-{version}.jar
在 OSS 上面的地址。可以访问公网
--jar oss://{bucket}/resources/juicefs-hadoop-{version}.jar --endpoint {endpoint}
或者
--jar https://{bucket}.{endpoint}/resources/juicefs-hadoop-{version}.jar无外网连接(私有部署)
由于 JuiceFS 需要联网下载部分必须配置文件来发行服务器的地址,因此在私有环境下(无外网连接),需要将此文件事先准备好。此配置文件可以在挂载 JuiceFS 的机器上面
/root/.juicefs
下面找到,文件名:{jfs-name}.conf
。将此配置文件同样上传到 OSS 上,然后在引导操作的参数里面填写下面配置:
--jar oss://{bucket}/{jar-path}
--conf-file oss://{bucket}/{conf-file-path}
已有 EMR 集群集成 JuiceFS
Hadoop
通过 HDFS 服务界面修改
core-site.xml
常用配置:
fs.jfs.impl=com.juicefs.JuiceFileSystem
fs.AbstractFileSystem.jfs.impl=com.juicefs.JuiceFS
juicefs.cache-size=10240
juicefs.cache-dir=xxxxxx
juicefs.cache-group=yarn
juicefs.discover-nodes-url=yarn
juicefs.accesskey=xxxxxx
juicefs.secretkey=xxxxxx
juicefs.token=xxxxxx
juicefs.access-log=/tmp/juicefs.access.logHive
通过 Hive 服务界面修改
hive.metastore.warehouse.dir
,可修改 Hive 建表默认位置 (非必须):jfs://{jfs-name}/{warehouse-dir}
最后,重启相应服务让配置修改生效。
腾讯云 EMR
新建 EMR 集群集成 JuiceFS
在 EMR 可用区与软件配置界面配置高级设置
在软件配置填入以下配置,缓存配置按需修改。
[
{
"serviceName": "HDFS",
"classification": "core-site.xml",
"serviceVersion": "2.8.5",
"properties": {
"fs.jfs.impl": "com.juicefs.JuiceFileSystem",
"fs.AbstractFileSystem.jfs.impl": "com.juicefs.JuiceFS",
"juicefs.token": "",
"juicefs.accesskey": "",
"juicefs.secretkey": "",
"juicefs.cache-group": "yarn",
"juicefs.cache-dir": "/data*/jfs",
"juicefs.cache-size": "10000000",
"juicefs.discover-nodes-url": "yarn",
"juicefs.superuser": "hadoop",
"juicefs.conf-dir": "/etc/juicefs",
"juicefs.access-log": "/tmp/juicefs.access.log"
}
}
]注意serviceVersion
需要和 Hadoop 版本匹配在基础信息界面的高级设置里面添加引导操作
下载
emr-boot.sh
脚本和juicefs-hadoop.jar
,并上传到您的对象存储上。对象存储需授权,引导操作的运行时机为「集群启动前」。
「脚本位置」填写
emr-boot.sh
在 COS 上面的地址,「参数」填写juicefs-hadoop-{version}.jar
在 COS 上面的地址。可以访问公网
--jar cosn://{bucket}/{jar-path}
无外网连接(私有部署)
由于 JuiceFS 需要联网下载部分必须配置文件来发行服务器的地址,因此在私有环境下(无外网连接),需要将此文件事先准备好。此配置文件可以在挂载 JuiceFS 的机器上面
/root/.juicefs
下面找到,文件名:{jfs-name}.conf
。将此配置文件同样上传到 COS 上,然后在引导操作的参数里面填写下面配置:
--jar cosn://{bucket}/{jar-path}
--conf-file cosn://{bucket}/{conf-file-path}
启动集群
已有 EMR 集群集成 JuiceFS
需要授予集群 COS 访问权限
Hadoop
通过 HDFS 服务界面修改
core-site.xml
常用配置:
fs.jfs.impl=com.juicefs.JuiceFileSystem
fs.AbstractFileSystem.jfs.impl=com.juicefs.JuiceFS
juicefs.cache-size=10240
juicefs.cache-dir=xxxxxx
juicefs.cache-group=yarn
juicefs.discover-nodes-url=yarn
juicefs.accesskey=xxxxxx
juicefs.secretkey=xxxxxx
juicefs.token=xxxxxx
juicefs.access-log=/tmp/juicefs.access.log注意由于腾讯云 EMR 默认使用
hadoop
用户启动 HDFS,HDFS 的superuser
为hadoop
。为了保持一致所以还需要指定juicefs.superuser=hadoop
。Hive
通过 Hive 服务界面修改
hive.metastore.warehouse.dir
,可修改 Hive 建表默认位置(非必须):jfs://{jfs-name}/{warehouse-dir}
最后,重启相应服务让配置修改生效。
金山云 KMR
AWS EMR
新建 EMR 集群集成 JuiceFS
在 Software and Steps 界面填写配置
基础配置
[
{
"classification": "core-site",
"properties": {
"fs.jfs.impl": "com.juicefs.JuiceFileSystem",
"fs.AbstractFileSystem.jfs.impl": "com.juicefs.JuiceFS",
"juicefs.cache-size": "10240",
"juicefs.access-log": "/tmp/juicefs.access.log",
"juicefs.discover-nodes-url": "yarn",
"juicefs.conf-dir": "/etc/juicefs",
"juicefs.cache-full-block": "false",
"juicefs.token": "",
"juicefs.cache-group": "yarn",
"juicefs.cache-dir": "/mnt*/jfs"
}
}
]使用 HBase on JuiceFS 配置。
juicefs.cache-size
和juicefs.free-space
需要按需配置。juicefs.token
需要到 JuiceFS 控制台获取。[
{
"classification": "core-site",
"properties": {
"fs.jfs.impl": "com.juicefs.JuiceFileSystem",
"juicefs.cache-size": "10240",
"juicefs.access-log": "/tmp/juicefs.access.log",
"juicefs.discover-nodes-url": "yarn",
"juicefs.conf-dir": "/etc/juicefs",
"juicefs.cache-full-block": "false",
"juicefs.token": "",
"juicefs.cache-group": "yarn",
"juicefs.free-space": "0.3",
"juicefs.cache-dir": "/mnt*/jfs",
"fs.AbstractFileSystem.jfs.impl": "com.juicefs.JuiceFS"
}
},
{
"classification": "hbase-site",
"properties": {
"hbase.rootdir": "jfs: //{name}/hbase"
}
}
]
在 General Cluster Settings 界面添加引导操作
下载
emr-boot.sh
脚本和juicefs-hadoop.jar
,并上传到您的对象存储上。「脚本位置」填写
emr-boot.sh
的 S3 地址,「参数」填写juicefs-hadoop-{version}.jar
的 S3 地址。可以访问公网
--jar s3://{bucket}/resources/juicefs-hadoop-{version}.jar
无外网连接(私有部署)
由于 SDK 需要联网下载配置文件来发现 metadata 服务器地址,因此在私有环境下(无外网连接),需要将此文件事先准备好。此配置文件可以从任意一台挂载了 JuiceFS 的机器获取,名为
/root/.juicefs/$VOL_NAME.conf
。将此配置文件同样上传到 S3 上,然后在引导操作的参数里面填写下面配置:
--jar s3://{bucket}/{jar-path}
--conf-file s3://{bucket}/{conf-file-path}
已有 EMR 集群集成 JuiceFS
在 EMR Master 节点上按照 手动安装 Hadoop SDK 的方法配置 JAR 文件,然后通过 EMR 界面修改配置:
Hadoop
通过 HDFS 服务界面修改
core-site.xml
,常用配置:fs.jfs.impl=com.juicefs.JuiceFileSystem
fs.AbstractFileSystem.jfs.impl=com.juicefs.JuiceFS
juicefs.cache-size=10240
juicefs.cache-dir=xxxxxx
juicefs.cache-group=yarn
juicefs.discover-nodes-url=yarn
juicefs.accesskey=xxxxxx
juicefs.secretkey=xxxxxx
juicefs.token=xxxxxx
juicefs.access-log=/tmp/juicefs.access.logHBase
修改
hbase-site
:"hbase.rootdir": "jfs://myjfs/hbase"
修改
hbase
:"hbase.emr.storageMode": "jfs"
等 EMR 配置刷新后,重启相应服务。
UCloud UHadoop
在 Master 节点上按照 手动安装 Hadoop SDK 的方法配置 JAR 文件。
修改 core-site.xml
,具体配置见 详细配置表。
最后,重启集群让配置修改生效。
自定义组件
常用组件的 juicefs-hadoop.jar
安装目录
Name | Installing Paths |
---|---|
Hadoop | ${HADOOP_HOME}/share/hadoop/common/lib/ |
Hive | ${HIVE_HOME}/auxlib |
Spark | ${SPARK_HOME}/jars |
Presto | ${PRESTO_HOME}/plugin/hive-hadoop2 |
Flink | ${FLINK_HOME}/lib |
Datax | ${DATAX_HOME}/plugin/writer/hdfswriter/libs ${DATAX_HOME}/plugin/reader/hdfsreader/libs/ |
Apache Spark
安装
juicefs-hadoop.jar
文件添加 JuiceFS 配置,Apache Spark 有多种方法引入配置:
修改
core-site.xml
文件命令行传入
spark-shell --master local[*] \
--conf spark.hadoop.fs.jfs.impl=com.juicefs.JuiceFileSystem \
--conf spark.hadoop.fs.AbstractFileSystem.jfs.impl=com.juicefs.JuiceFS \
--conf spark.hadoop.juicefs.token=xxx \
--conf spark.hadoop.juicefs.accesskey=xxx \
--conf spark.hadoop.juicefs.secretkey=xxx \
...通过修改 $SPARK_HOME/conf 目录下的
spark-defaults.conf
文件
Apache Flink
安装
juicefs-hadoop.jar
文件添加 JuiceFS 配置,Apache Flink 有多种方法引入配置:
- 通过修改
core-site.xml
文件 - 通过修改
flink-conf.yaml
文件
- 通过修改
Presto
- 安装
juicefs-hadoop.jar
文件 - 通过修改过
core-site.xml
添加 JuiceFS 配置
DataX
安装
juicefs-hadoop.jar
文件修改 DataX 配置文件:
"defaultFS": "jfs://myjfs",
"hadoopConfig": {
"fs.jfs.impl": "com.juicefs.JuiceFileSystem",
"fs.AbstractFileSystem.jfs.impl": "com.juicefs.JuiceFS",
"juicefs.token": "xxxxxxxxxxxxx",
"juicefs.accesskey": "xxxxxxxxxxxxx",
"juicefs.secretkey": "xxxxxxxxxxxxx"
}
测试验证
此处罗列各类 Hadoop 应用的验证步骤,确保能正常使用 JuiceFS。
Hadoop
hadoop fs -ls jfs://${VOL_NAME}/
hadoop fs -mkdir jfs://${VOL_NAME}/jfs-test
hadoop fs -rm -r jfs://${VOL_NAME}/jfs-test
Hive、SparkSQL、Impala
create table if not exists person(
name string,
age int
)
location 'jfs://${VOL_NAME}/tmp/person';
insert into table person values('tom',25);
insert overwrite table person select name, age from person;
select name, age from person;
drop table person;
Spark Shell
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs._
val conf = sc.hadoopConfiguration
val p = new Path("jfs://${VOL_NAME}/")
val fs = p.getFileSystem(conf)
fs.listStatus(p)
HBase
create 'test', 'cf'
list 'test'
put 'test', 'row1', 'cf:a', 'value1'
scan 'test'
get 'test', 'row1'
disable 'test'
drop 'test'
Flume
jfs.sources =r1
jfs.sources.r1.type = org.apache.flume.source.StressSource
jfs.sources.r1.size = 10240
jfs.sources.r1.maxTotalEvents=10
jfs.sources.r1.batchSize=10
jfs.sources.r1.channels = c1
jfs.channels = c1
jfs.channels.c1.type = memory
jfs.channels.c1.capacity = 100
jfs.channels.c1.transactionCapacity = 100
jfs.sinks = k1
jfs.sinks.k1.type = hdfs
jfs.sinks.k1.channel = c1
jfs.sinks.k1.hdfs.path =jfs://${VOL_NAME}/tmp/flume
jfs.sinks.k1.hdfs.writeFormat= Text
jfs.sinks.k1.hdfs.fileType= DataStream
Flink
echo 'hello world' > /tmp/jfs_test
hadoop fs -put /tmp/jfs_test jfs://${VOL_NAME}/tmp/
rm -f /tmp/jfs_test
./bin/flink run -m yarn-cluster ./examples/batch/WordCount.jar --input jfs://${VOL_NAME}/tmp/jfs_test --output jfs://${VOL_NAME}/tmp/result
将数据迁移到 JuiceFS
最佳实践
Hadoop
Hadoop 生态组件一般通过 org.apache.hadoop.fs.FileSystem
类与 HDFS 对接,JuiceFS 同样也通过继承这个类来支持 Hadoop 生态的各个组件。
Hadoop SDK 启用后,就可以通过 hadoop fs
命令操作 JuiceFS:
hadoop fs -ls jfs://{VOL_NAME}/
如果想省去 jfs://
协议前缀,可以将 fs.defaultFS
设置为 JuiceFS 地址,在 core-site.xml
里面增加如下配置:
<property>
<name>fs.defaultFS</name>
<value>jfs://{VOL_NAME}</value>
</property>
修改 defaultFS
会导致所有没有带协议的路径默认均指向 JuiceFS,可能会导致一些其他问题,建议先在测试环境中测试。
Hive
在 Hive 中建库建表时,使用 LOCATION 来指定存储数据的具体路径。
建库建表
-- create database
CREATE DATABASE ... database_name
LOCATION 'jfs://{VOL_NAME}/path-to-database';
-- create table
CREATE TABLE ... table_name
LOCATION 'jfs://{VOL_NAME}/path-to-table';Hive create 的表,默认会在 database 的 location 下。如果 database 的 location 已经在 JuiceFS 上,新建 table 默认也会在 JuiceFS 上。
改库改表
ALTER DATABASE database_name
SET LOCATION 'jfs://{VOL_NAME}/path-to-database';
ALTER TABLE table_name
SET LOCATION 'jfs://{VOL_NAME}/path-to-table';
ALTER TABLE table_name PARTITION(...)
SET LOCATION 'jfs://{VOL_NAME}/path-to-partition';Hive 支持使用多种文件系统存储数据。对于未分区表,整张表的数据必须是在同一个文件系统上。对于分区表,每个分区可以独立设置文件系统。
如果想默认建库就在 JuiceFS 上,可以通过将
hive.metastore.warehouse.dir
修改为 JuiceFS 上的路径。
Spark
Spark 有多种运行模式,如 Standalone、YARN、Kubernetes、Thrift Server 等。
由于 JuiceFS 的特殊的缓存架构设计,JuiceFS 需要保证客户端的机器 IP 尽量不变才能保证缓存的高效利用。因此,Spark 各种运行模式对于 JuiceFS 的最主要区别就是 executor 进程是否常驻,executor 所在机器的 IP 是否经常变化。
在 executor 进程常驻(例如 Thrift Server 模式),或者在 executor 所在的机器 IP 基本固定并且集群使用率比较高时(Spark on YARN,Standalone),使用「多机分布式缓存」方案。juicefs.discover-nodes-url
参数需要做相应的设置。
在 executor 进程经常变化,并且机器 IP 也经常变化时(Spark on K8s),使用「独立缓存集群」方案。juicefs.discover-nodes-url
设置为 all
。
Spark shell
scala> sc.textFile("jfs://{VOL_NAME}/path-to-input").count
HBase
HBase 主要在 HDFS 存储两部分数据,WAL 文件以及 HFile。写入数据时,会先写 WAL,然后再通过 hflush
将数据写入 RegionServer 的 memstore。这样可以保证即使 RegionServer 异常退出时,已经提交的数据仍然可以通过 WAL 恢复。当 RegionServer 里面的数据已经落入 HDFS 形成 HFile 后,WAL 文件会被删除,所以整体 WAL 文件对空间的使用量不会很大。
由于 JuiceFS hflush
的实现与 HDFS 有别(详见hflush
实现),当 juicefs.hflush
设置为 sync
时,JuiceFS 的 hflush
性能比较慢,因此建议将 WAL 文件写入 HDFS,最终的 HFile 写入 JuiceFS。
<property>
<name>hbase.rootdir</name>
<value>jfs://{VOL_NAME}/hbase</value>
</property>
<property>
<name>hbase.wal.dir</name>
<value>hdfs://{NAME_SPACE}/hbase-wal</value>
</property>
Flink
Apache Flink 若使用 Streaming File Sink 从文件系统读写数据。为了保证数据的可靠性,Flink 需要在 checkpoint 时使用 RollingPolicy
。
对于版本小于 2.7 的 Hadoop 版本,由于 HDFS 没有 truncate 功能,需要使用 OnCheckpointRollingPolicy
,每次 checkpoint 都关闭并生成新的文件写入数据,会导致大量小文件。
Hadoop2.7 及以上版本的 HDFS,可以使用 DefaultRollingPolicy
,可以根据文件大小、时间以及空闲时间来滚动文件。
JuiceFS 实现了 truncate 功能,所以同样也可以使用 DefaultRollingPolicy
。
Flink 支持使用 plugin 的模式对接文件系统,将 juicefs-hadoop.jar
文件放到 lib
目录下即可,详见手动安装 JuiceFS Hadoop SDK.
Flume
JuiceFS 同样利用 HDFS sink 与 Flume 集成。hdfs.batchSize
表示多少消息调用一次 hflush
接口。
为了保证数据不丢失,juicefs.hflush
应设置为 sync
,同时应该将 hdfs.batchSize
调大,将每个批次的数量控制在消息总大小 4MB(默认每个对象块的大小)左右。
另外如果启用了数据压缩(hdfs.fileType
设为 CompressedStream
),极端情况下如果出现对象存储不可写入的情况,可能会导致整个压缩文件损坏,导致之前已经 hflush
的数据仍然不可读。如果有这方面的顾虑,建议将 hdfs.fileType
设置为 DataStream
,后续再通过 ETL 任务进行数据压缩。
Sqoop
使用 Sqoop 将数据导入 Hive 时,Sqoop 会首先把数据导入 target-dir
,然后在通过 hive load
命令将数据加载到 Hive 表,所以使用 Sqoop 时,需要修改 target-dir
。
1.4.6
使用此版本的 Sqoop 时还需要将
fs
设为 JuiceFS,因此还需将 HDFS 上面的mapreduce.tar.gz
复制到 JuiceFS 上的相同路径,默认目录在 HDFS/hdp/apps/${hdp.version}/mapreduce/mapreduce.tar.gz
sqoop import \
-fs jfs://{VOL_NAME}/ \
--target-dir jfs://{VOL_NAME}/path-to-dir1.4.7
sqoop import \
--target-dir jfs://{VOL_NAME}/path-to-dir