JuiceFS
JuiceFS 是一款高性能 POSIX 文件系统,针对云原生环境特别优化设计,在 GNU Affero General Public License v3.0 开源协议下发布。使用 JuiceFS 存储数据,数据本身会被持久化在对象存储(例如,Amazon S3),而数据所对应的元数据可以根据场景需求被持久化在 Redis、MySQL、SQLite 等多种数据库引擎中。JuiceFS 可以简单便捷的将海量云存储直接接入已投入生产环境的大数据、机器学习、人工智能以及各种应用平台,无需修改代码即可像使用本地存储一样高效使用海量云端存储。
背景和预期
目前数据存取主要是在OSS上进行大json的存取,未来可能会存在小文件的存取以及其他种类数据存取的需求,JuiceFS是一个通过一些方式进行文件存取加速的中间件,预期未来可以在拓展更多的使用场景时可以对数据读写速度有所提升。
安装及本地测试
构建测试环境
- 创建测试环境及各文件夹
workdir
- d) data
- d) juicefs
- d) minio
- d) redis
- d) log
- d) juicefs
- f) Dockerfile
- f) docker-compose.yml
- 构建测试用docker镜像,目前官方最新版为
0.16.1
- 构建用 Dockerfile 如下
- 通过命令构建基础镜像
docker build -t lockinwu/test .
FROM centos:7
LABEL maintainer="stevenchenworking@gmail.com"
ENV DEFAULT_TAG '0.16.1'
WORKDIR /opt/juicefs
USER root
RUN JFS_LATEST_TAG=$(curl -s https://api.github.com/repos/juicedata/juicefs/releases/latest | grep 'tag_name' | cut -d '"' -f 4 | tr -d 'v') && \
JFS_LATEST_TAG=${JFS_LATEST_TAG:-$DEFAULT_TAG} && \
yum clean all && yum -y makecache && yum -y install wget tar && \
wget -c "https://github.com/juicedata/juicefs/releases/download/v${JFS_LATEST_TAG}/juicefs-${JFS_LATEST_TAG}-linux-amd64.tar.gz" && \
tar -zxf "juicefs-${JFS_LATEST_TAG}-linux-amd64.tar.gz" && \
install juicefs /usr/local/bin
- 下载所需其他docker组件并组建集群环境
- 所需docker-compose.yml文件如下
- 通过命令启动集群
docker-compose -f docker-compose.yml up -d
version: '3.6'
networks:
bigdata:
external: true
services:
redis-primary:
container_name: redis-primary
image: docker.io/bitnami/redis:6.2
ports:
- 6379:6379
environment:
- REDIS_REPLICATION_MODE=master
- REDIS_PASSWORD=redispwd
- REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL
volumes:
- ./data/redis:/bitnami/redis/data
- ./log/redis:/bitnami/redis/log
redis-secondary:
container_name: redis-secondary
image: bitnami/redis:6.2
ports:
- 6380:6379
depends_on:
- redis-primary
environment:
- REDIS_REPLICATION_MODE=slave
- REDIS_MASTER_HOST=redis-primary
- REDIS_MASTER_PORT_NUMBER=6379
- REDIS_MASTER_PASSWORD=redispwd
- REDIS_PASSWORD=redispwd
- REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL
minio:
container_name: minio
image: bitnami/minio:2021
ports:
- 9000:9000
environment:
- MINIO_ACCESS_KEY=miniokey
- MINIO_SECRET_KEY=miniokey
volumes:
- ./data/minio:/bitnami/redis/data
centos:
container_name: centos7
image: lockinwu/test
privileged: true
volumes:
- ./log/juicefs:/var/log
- ./data/juicefs:/mnt
- ./data/normal:/normal
command: [ "/usr/sbin/init" ]
文件写入测试
- 通过命令
docker exec -it docker_centos_1 bash
进入目标container - 运行命令挂载磁盘
- 注册remote 磁盘
juicefs format \
--storage minio \
--bucket http://minio:9000/pics \
--access-key miniokey \
--secret-key miniokey \
redis://:redispwd@redis-primary:6379/1 \
pics
- 挂载磁盘
juicefs mount -d redis://:redispwd@redis-primary:6379/1 /mnt/jfs
- 运行命令进行写入速度测试
dd if=/mnt/jfs/1G_10_1.img of=/mnt/jfs/1G_10_3.img bs=1G count=10 oflag=dsync
结果
读写基本上是本地数据的一半,和本地mount进去的速度差不多。但是没有云服务器可以测试,具体生产的表现未知。
source | dest | from | to | speed |
---|---|---|---|---|
local | local | /dev/zero | /tmp/1G_10_1.img | 269 MB/s |
local | local | /tmp/1G_10_1.img | /tmp/1G_10_2.img | 102 MB/s |
local | local | /tmp/1G_10_1.img | /dev/null | 98.1 MB/s |
local | juicefs | /dev/zero | /mnt/jfs/1G_10_1.img | 56.4 MB/s |
local | juicefs | /tmp/1G_10_1.img | /mnt/jfs/1G_10_2.img | 56.4 MB/s |
juicefs | local | /mnt/jfs/1G_10_1.img | /tmp/1G_10_3.img | 49.3 MB/s |
juicefs | local | /mnt/jfs/1G_10_1.img | /dev/null | 79.9 MB/s |
juicefs | juicefs | /mnt/jfs/1G_10_1.img | /mnt/jfs/1G_10_3.img | 38.6 MB/s |
juicefs | mount | /mnt/jfs/1G_10_1.img | /normal/1G_10_3.img | 43.8 MB/s |
local | mount | /dev/zero | /normal/1G_10_4.img | 179 MB/s |
local | mount | /tmp/1G_10_1.img | /normal/1G_10_5.img | 111 MB/s |
mount | juicefs | /normal/1G_10_1.img | /mnt/jfs/1G_10_2.img | 71.2 MB/s |
mount | mount | /normal/1G_10_1.img | /normal/1G_10_6.img | 69.3 MB/s |
blocks
- dd 命令运行时可能会卡住(运行时间长)
- 资源受宿主机限制较大,宿主机除了问题 docker 里面的操作也会受到很大影响。
- 测试使用的文件都是10G规模的,可能在测试过程中触碰到宿主机对docker可用磁盘空间的限制
- 此次测试没涉及不同品质磁盘的读写测试(SATA/SSD .etc)
dd 命令参考:
- if=文件名:输入文件名,缺省为标准输入。即指定源文件。< if=input file >
- of=文件名:输出文件名,缺省为标准输出。即指定目的文件。< of=output file >
- ibs=bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。
- obs=bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。
- bs=bytes:同时设置读入/输出的块大小为bytes个字节。
- cbs=bytes:一次转换bytes个字节,即指定转换缓冲区大小。
- skip=blocks:从输入文件开头跳过blocks个块后再开始复制。
- seek=blocks:从输出文件开头跳过blocks个块后再开始复制。
- count=blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数。
- conv=conversion:用指定的参数转换文件。
- ascii:转换ebcdic为ascii
- ebcdic:转换ascii为ebcdic
- ibm:转换ascii为alternate ebcdic
- block:把每一行转换为长度为cbs,不足部分用空格填充
- unblock:使每一行的长度都为cbs,不足部分用空格填充
- lcase:把大写字符转换为小写字符
- ucase:把小写字符转换为大写字符
- swab:交换输入的每对字节
- noerror:出错时不停止
- notrunc:不截短输出文件
- sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。
结论及展望
JuiceFS 是通过中心化的文件索引配合一些内部分布式读写的方式对磁盘文件读写、压缩、备份进行加速,目前官方提供包括mysql备份、clickhouse读写分离等多种成功案例,未来如果我们需要基于磁盘而非oss服务进行数据的IO操作可以考虑通过JuiceFS进行部署。同时,需要警惕的是,它的文件索引是放在中心化存储中(目前支持mysql、redis等),可能会存在索引存储的损坏带来的数据丢失等问题。