在 Hadoop 生态使用 JuiceFS
JuiceFS 提供与 HDFS 接口高度兼容的 Java 客户端,Hadoop 生态中的各种应用都可以在不改变代码的情况下,平滑地使用 JuiceFS 存储数据。
环境要求
1. Hadoop 及相关组件
JuiceFS Hadoop Java SDK 同时兼容 Hadoop 2.x、Hadoop 3.x,以及 Hadoop 生态中的各种主流组件。
2. 用户权限
JuiceFS 默认使用本地的「用户/UID」及「用户组/GID」映射,在分布式环境下使用时,为了避免权限问题,请参考文档将需要使用的「用户/UID」及「用户组/GID」同步到所有 Hadoop 节点。也可以通过定义一个全局的用户和用户组文件使得集群中的所有节点共享权限配置,相关配置请查看这里。
3. 文件系统
通过 JuiceFS Java 客户端为 Hadoop 生态提供存储,需要提前创建 JuiceFS 文件系统。部署 Java 客户端时,在配置文件中指定已创建文件系统的元数据引擎地址。
创建文件系统可以参考 JuiceFS 快速上手指南。
如果要在分布式环境中使用 JuiceFS,创建文件系统时,请合理规划要使用的对象存储和数据库,确保它们可以被每个集群节点正常访问。
4. 内存资源
根据计算任务(如 Spark executor)的读写负载,JuiceFS Hadoop Java SDK 可能需要额外使用 4 * juicefs.memory-size
的堆外内存用来加速读写性能。默认情况下,建议为计算任务至少配置 1.2GB 的堆外内存。
5. Java 运行时版本
JuiceFS Hadoop Java SDK 默认使用 JDK 8 编译,如果需要在高版本的 Java 运行时中使用(如 Java 17),需在 JVM 参数中增加以下选项以允许使用反射 API:
--add-exports=java.base/sun.nio.ch=ALL-UNNAMED
更多关于以上选项的说明请参考官方文档。
安装与编译客户端
安装预编译客户端
请参考「安装」文档了解如何下载预编译的 JuiceFS Hadoop Java SDK。
手动编译客户端
不论为哪个系统环境编译客户端,编译后的 JAR 文件都为相同的名称,且只能部署在匹配的系统环境中,例如在 Linux 中编译则只能用于 Linux 环境。另外,由于编译的包依赖 glibc,建议尽量使用低版本的系统进行编译,这样可以获得更好的兼容性。
编译依赖以下工具:
- Go 1.15+(中国用户建议使用 Goproxy China 镜像加速)
- JDK 8+
- Maven 3.3+(中国用户建议使用阿里云镜像加速)
- Git
- make
- GCC 5.4+
Linux 和 macOS
克隆仓库:
git clone https://github.com/juicedata/juicefs.git
进入目录,执行编译:
cd juicefs/sdk/java
make
如果使用 Ceph 的 RADOS 作为 JuiceFS 的存储引擎,需要先安装 librados-dev
包。
cd juicefs/sdk/java
make ceph
编译完成后,可以在 sdk/java/target
目录中找到编译好的 JAR
文件,包括两个版本:
- 包含第三方依赖的包:
juicefs-hadoop-X.Y.Z.jar
- 不包含第三方依赖的包:
original-juicefs-hadoop-X.Y.Z.jar
建议使用包含第三方依赖的版本。
Windows
用于 Windows 环境的客户端需要在 Linux 或 macOS 系统上通过交叉编译的方式获得,编译依赖 mingw-w64,需要提前安装。
与编译面向 Linux 和 macOS 客户端的步骤相同,比如在 Ubuntu 系统上,先安装 mingw-w64
包,解决依赖问题:
sudo apt install mingw-w64
克隆并进入 JuiceFS 源代码目录,执行以下代码进行编译:
cd juicefs/sdk/java
make win
部署客户端
让 Hadoop 生态各组件能够正确识别 JuiceFS,需要进行以下配置:
- 将编译好的 JAR 文件和
$JAVA_HOME/lib/tools.jar
放置到组件的classpath
内,常见大数据平台和组件的安装路径见下表。 - 将 JuiceFS 相关配置写入配置文件(通常是
core-site.xml
),详见客户端配置参数。
建议将 JAR 文件放置在一个统一的位置,其他位置通过符号链接进行调用。
大数据平台
名称 | 安装路径 |
---|---|
CDH | /opt/cloudera/parcels/CDH/lib/hadoop/lib /opt/cloudera/parcels/CDH/spark/jars /var/lib/impala |
HDP | /usr/hdp/current/hadoop-client/lib /usr/hdp/current/hive-client/auxlib /usr/hdp/current/spark2-client/jars |
Amazon EMR | /usr/lib/hadoop/lib /usr/lib/spark/jars /usr/lib/hive/auxlib |
阿里云 EMR | /opt/apps/ecm/service/hadoop/*/package/hadoop*/share/hadoop/common/lib /opt/apps/ecm/service/spark/*/package/spark*/jars /opt/apps/ecm/service/presto/*/package/presto*/plugin/hive-hadoop2 /opt/apps/ecm/service/hive/*/package/apache-hive*/lib /opt/apps/ecm/service/impala/*/package/impala*/lib |
腾讯云 EMR | /usr/local/service/hadoop/share/hadoop/common/lib /usr/local/service/presto/plugin/hive-hadoop2 /usr/local/service/spark/jars /usr/local/service/hive/auxlib |
UCloud UHadoop | /home/hadoop/share/hadoop/common/lib /home/hadoop/hive/auxlib /home/hadoop/spark/jars /home/hadoop/presto/plugin/hive-hadoop2 |
百度云 EMR | /opt/bmr/hadoop/share/hadoop/common/lib /opt/bmr/hive/auxlib /opt/bmr/spark2/jars |
社区开源组件
名称 | 安装路径 |
---|---|
Hadoop | ${HADOOP_HOME}/share/hadoop/common/lib/ , ${HADOOP_HOME}/share/hadoop/mapreduce/lib/ |
Spark | ${SPARK_HOME}/jars |
Presto | ${PRESTO_HOME}/plugin/hive-hadoop2 |
Trino | ${TRINO_HOME}/plugin/hive |
Flink | ${FLINK_HOME}/lib |
StarRocks | ${StarRocks_HOME}/fe/lib/ , ${StarRocks_HOME}/be/lib/hadoop/common/lib |
客户端配置参数
请参考以下表格设置 JuiceFS 文件系统相关参数,并写入配置文件,一般是 core-site.xml
。
核心配置
配置项 | 默认值 | 描述 |
---|---|---|
fs.jfs.impl | io.juicefs.JuiceFileSystem | 指定要使用的存储实现,默认使用 jfs:// 作为 scheme。如想要使用其它 scheme(例如 cfs:// ),则修改为 fs.cfs.impl 即可。无论使用的 scheme 是什么,访问的都是 JuiceFS 中的数据。 |
fs.AbstractFileSystem.jfs.impl | io.juicefs.JuiceFS | 指定要使用的存储实现,默认使用 jfs:// 作为 scheme。如想要使用其它 scheme(例如 cfs:// ),则修改为 fs.AbstractFileSystem.cfs.impl 即可。无论使用的 scheme 是什么,访问的都是 JuiceFS 中的数据。 |
juicefs.meta | 指定预先创建好的 JuiceFS 文件系统的元数据引擎地址。可以通过 juicefs.{vol_name}.meta 格式为客户端同时配置多个文件系统。具体请参考「多文件系统配置」。 |
缓存配 置
配置项 | 默认值 | 描述 |
---|---|---|
juicefs.cache-dir | 设置本地缓存目录,可以指定多个文件夹,用冒号 : 分隔,也可以使用通配符(比如 * )。请预先创建好这些目录,并给予 0777 权限,便于多个应用共享缓存数据。 | |
juicefs.cache-size | 0 | 设置本地缓存目录的容量,单位 MiB,默认为 0,即不开启缓存。如果配置了多个缓存目录,该值代表所有缓存目录容量的总和。 |
juicefs.cache-full-block | true | 是否缓存所有读取的数据块,false 表示只缓存随机读的数据块。 |
juicefs.free-space | 0.1 | 本地缓存目录的最小可用空间比例,默认保留 10% 剩余空间。 |
juicefs.open-cache | 0 | 缓存打开的文件元数据(单位:秒),0 表示关闭 |
juicefs.attr-cache | 0 | 目录和文件属性缓存的过期时间(单位:秒) |
juicefs.entry-cache | 0 | 文件项缓存的过期时间(单位:秒) |
juicefs.dir-entry-cache | 0 | 目录项缓存的过期时间(单位:秒) |
juicefs.discover-nodes-url | 指定发现集群缓存节点列表的方式,每 10 分钟刷新一次。
|
I/O 配置
配置项 | 默认值 | 描述 |
---|---|---|
juicefs.max-uploads | 20 | 上传数据的最大连接数 |
juicefs.max-deletes | 10 | 删除数据的最大连接数 |
juicefs.get-timeout | 5 | 下载一个对象的超时时间,单位为秒。 |
juicefs.put-timeout | 60 | 上传一个对象的超时时间,单位为秒。 |
juicefs.memory-size | 300 | 读写数据的缓冲区最大空间,单位为 MiB。 |
juicefs.prefetch | 1 | 预读数据块的线程数 |
juicefs.upload-limit | 0 | 上传带宽限制,单位为 Mbps,默认不限制。 |
juicefs.download-limit | 0 | 下载带宽限制,单位为 Mbps,默认不限制。 |
juicefs.io-retries | 10 | IO 失败重试次数 |
juicefs.writeback | false | 是否后台异步上传数据 |
其它配置
配置项 | 默认值 | 描述 |
---|---|---|
juicefs.bucket | 为对象存储指定跟格式化时不同的访问地址 | |
juicefs.debug | false | 是否开启 debug 日志 |
juicefs.access-log | 访问日志的路径。需要所有应用都有写权限,可以配置为 /tmp/juicefs.access.log 。该文件会自动轮转,保留最近 7 个文件。 | |
juicefs.superuser | hdfs | 超级用户 |
juicefs.supergroup | supergroup | 超级用户组 |
juicefs.users | null | 用户名以及 UID 列表文件的地址,比如 jfs://name/etc/users 。文件格式为 <username>:<UID> ,一行一个用户。 |
juicefs.groups | null | 用户组、GID 以及组成员列表文件的地址,比如 jfs://name/etc/groups 。文件格式为 <group-name>:<GID>:<username1>,<username2> ,一行一个用户组。 |
juicefs.umask | null | 创建文件和目录的 umask 值(如 0022 ),如果没有此配置,默认值是 fs.permissions.umask-mode 。 |
juicefs.push-gateway | Prometheus Pushgateway 地址,格式为 <host>:<port> 。 | |
juicefs.push-auth | Prometheus 基本认证信息,格式为 <username>:<password> 。 | |
juicefs.push-graphite | Graphite 地址,格式为 <host>:<port> 。 | |
juicefs.push-interval | 10 | 指标推送的时间间隔,单位为秒。 |
juicefs.push-labels | 指标额外标签,格式为 key1:value1;key2:value2 。 | |
juicefs.fast-resolve | true | 是否开启快速元数据查找(通过 Redis Lua 脚本实现) |
juicefs.no-usage-report | false | 是否上报数据。仅上版本号等使用量数据,不包含任何用户信息。 |
juicefs.block.size | 134217728 | 单位为字节,同 HDFS 的 dfs.blocksize ,默认 128 MB |
juicefs.file.checksum | false | DistCp 使用 -update 参数时,是否计算文件 Checksum |
juicefs.no-bgjob | false | 是否关闭后台任务(清理、备份等) |
juicefs.backup-meta | 3600 | 自动将 JuiceFS 元数据备份到对象存储间隔(单位:秒),设置为 0 关闭自动备份 |
juicefs.backup-skip-trash | false | 备份元数据时忽略回收站中的文件和目录。 |
juicefs.heartbeat | 12 | 客户端和元数据引擎之间的心跳间隔(单位:秒),建议所有客户端都设置一样 |
juicefs.skip-dir-mtime | 100ms | 修改父目录 mtime 间隔。 |
多文件系统配置
当需要同时使用多个 JuiceFS 文件系统时,上述所有配置项均可对特定文件系统进行指定,只需要将文件系统 名字放在配置项的中间,比如下面示例中的 jfs1
和 jfs2
:
<property>
<name>juicefs.jfs1.meta</name>
<value>redis://jfs1.host:port/1</value>
</property>
<property>
<name>juicefs.jfs2.meta</name>
<value>redis://jfs2.host:port/1</value>
</property>
配置示例
以下是一个常用的配置示例,请替换 juicefs.meta
配置中的 {HOST}
、{PORT}
和 {DB}
变量为实际的值。
<property>
<name>fs.jfs.impl</name>
<value>io.juicefs.JuiceFileSystem</value>
</property>
<property>
<name>fs.AbstractFileSystem.jfs.impl</name>
<value>io.juicefs.JuiceFS</value>
</property>
<property>
<name>juicefs.meta</name>
<value>redis://{HOST}:{PORT}/{DB}</value>
</property>
<property>
<name>juicefs.cache-dir</name>
<value>/data*/jfs</value>
</property>
<property>
<name>juicefs.cache-size</name>
<value>1024</value>
</property>
<property>
<name>juicefs.access-log</name>
<value>/tmp/juicefs.access.log</value>
</property>
Hadoop 环境配置
请参照前述各项配置表,将配置参数加入到 Hadoop 配置文件 core-site.xml
中。
CDH6
如果使用的是 CDH 6 版本,除了修改 core-site
外,还需要通过 YARN 服务界面修改 mapreduce.application.classpath
,增加:
$HADOOP_COMMON_HOME/lib/juicefs-hadoop.jar
HDP
除了修改 core-site
外,还需要通过 MapReduce2 服务界面修改配置 mapreduce.application.classpath
,在末尾增加(变量无需替换):
/usr/hdp/${hdp.version}/hadoop/lib/juicefs-hadoop.jar
Flink
将配置参数加入 conf/flink-conf.yaml
。如果只是在 Flink 中使用 JuiceFS, 可以不在 Hadoop 环境配置 JuiceFS,只需要配置 Flink 客户端即可。