JuiceFS 元数据引擎选型:Redis、MySQL、TiKV 与 etcd 基准测试怎么解读
【免费下载链接】juicefsJuiceFS is a distributed POSIX file system built on top of Redis and S3.项目地址: https://gitcode.com/GitHub_Trending/ju/juicefs
在为 JuiceFS 挑选元数据引擎时,Redis、MySQL、TiKV、etcd 是常见的候选。JuiceFS 官方文档 Metadata Engines Benchmark 在同一套环境里对这几个引擎(外加 PostgreSQL、FoundationDB)做了同条件对比测试。这篇文章讲的是:如何正确读取这份基准测试的三张结果表,把测试条件、单位、倍数含义看清楚,最后落到“哪种负载该选哪个引擎”的判断上,并说明如何在你自己的环境里复测验证。
先看测试条件,确定数据适用范围
解读结果之前先确认测试是在什么条件下跑的,否则数字没法外推。这份基准测试的固定条件是:
- 所有测试使用同一套对象存储、同一批客户端和元数据主机,只更换元数据引擎,保证可比性;
- 客户端:Amazon c5.xlarge(4 vCPU、8 GiB 内存、最高 10Gbps 网络),Ubuntu 20.04.1 LTS;
- 元数据主机:Amazon c5d.xlarge(4 vCPU、8 GiB 内存、100 GB SSD 本地盘,SSD 格式化为 ext4 挂载在
/data),Ubuntu 20.04.1 LTS; - JuiceFS 版本:1.1.0-beta1+2023-06-08.5ef17ba0;
- 被测引擎版本:Redis 7.0.9、MySQL 8.0.25、PostgreSQL 15.3、TiKV 6.5.3、etcd 3.3.25、FoundationDB 6.3.23。
其中 Redis 有两列结果,Redis-Always和Redis-Everysec,对应 AOF 的appendfsync配置取always或everysec。这个区别直接决定你怎么读整份报告:
everysec(每秒 fsync)写入性能更好,但可能丢失最后一秒的写入,文档原文提示这属于“性能提升但牺牲一点数据可靠性”;always(每次写都 fsync)更保守,是可靠性优先的基准线。
文档同时指出:Redis 和 MySQL 在本测试中只保存一个本地副本,而 TiKV 和 etcd 通过 Raft 协议在三台主机上保存三个副本。也就是说,TiKV/etcd 的延迟数字是带着三副本复制开销测出来的,对比时要意识到两者的高可用代价不同。
解读 Golang Benchmark 表:纯元数据操作延迟
这张表来自源码内的简单基准测试pkg/meta/benchmarks_test.go,直接度量单个元数据操作在引擎侧的耗时,是“纯元数据操作”层面的数据。读表规则:
- 单位是us/op(微秒/次操作),越小越好;
- 括号里的数字是相对于 Redis-Always 的倍数,例如
mkdir行中 MySQL 的2042 (3.7)表示约 2042 us,是 Redis-Always 用时的 3.7 倍; read相关行全部为 0(小于 1us),文档明确说明:因为启用了元数据缓存,这些结果目前不可比,不要据此下结论。
挑几行有代表性的看(以下数值均引自文档):
| 操作 | Redis-Always | Redis-Everysec | MySQL | TiKV | etcd |
|---|---|---|---|---|---|
| mkdir | 558 | 468 (0.8) | 2042 (3.7) | 1237 (2.2) | 1916 (3.4) |
| create | 570 | 455 (0.8) | 1570 (2.8) | 1209 (2.1) | 1849 (3.2) |
| lookup | 173 | 178 (1.0) | 557 (3.2) | 608 (3.5) | 1054 (6.1) |
| getattr | 87 | 86 (1.0) | 530 (6.1) | 306 (3.5) | 536 (6.2) |
| readdir_1k | 1490 | 1547 (1.0) | 18779 (12.6) | 5834 (3.9) | 15809 (10.6) |
| write | 553 | 369 (0.7) | 2352 (4.3) | 1573 (2.8) | 1788 (3.2) |
能读出的规律:
- 常规操作(mkdir、create、rename、unlink)上,MySQL 大约是 Redis 的 3 倍多,TiKV 大约 2 倍,etcd 大约 3 倍多,与文档结论“MySQL 约为 Redis 的 2~4 倍、TiKV 与 MySQL 相近且多数场景略低、etcd 约为 TiKV 的 1.5 倍”一致;
- 批量读目录时差距急剧拉开:
readdir_1k(读 1000 个条目的目录)MySQL 是 Redis 的 12.6 倍、etcd 10.6 倍,只有 TiKV 压到 3.9 倍;如果你的业务大量扫大目录,这张表里这一行比 mkdir/create 更值得参考; getattr、access这类纯读操作上 MySQL 差距最大(约 6 倍),因为读操作没有写入路径上的优化空间。
解读 JuiceFS Bench 表:端到端的小文件吞吐
第二张表来自juicefs bench命令(官方命令为./juicefs bench /mnt/jfs -p 4,4 并发),它经过 FUSE 层走完整链路,度量的是整机端到端能力,单位是 files/s、MiB/s 或 ms/op。
| 项目 | Redis-Always | Redis-Everysec | MySQL | TiKV | etcd |
|---|---|---|---|---|---|
| Write big file | 730.84 MiB/s | 731.93 MiB/s | 729.00 MiB/s | 730.01 MiB/s | 746.07 MiB/s |
| Read big file | 923.98 MiB/s | 892.99 MiB/s | 905.93 MiB/s | 918.19 MiB/s | 939.63 MiB/s |
| Write small file | 95.20 files/s | 109.10 files/s | 82.30 files/s | 101.20 files/s | 95.80 files/s |
| Read small file | 1242.80 files/s | 937.30 files/s | 752.40 files/s | 681.50 files/s | 1229.10 files/s |
| Stat file | 12313.80 files/s | 11989.50 files/s | 3583.10 files/s | 4211.20 files/s | 2836.60 files/s |
| FUSE operation | 0.41 ms/op | 0.40 ms/op | 0.46 ms/op | 0.41 ms/op | 0.41 ms/op |
| Update meta | 2.45 ms/op | 1.76 ms/op | 2.46 ms/op | 3.76 ms/op | 3.40 ms/op |
这张表的读法是分两半看:
- 大文件读写四列几乎一样(729~746 MiB/s 写、892~940 MiB/s 读)。原因是大 I/O 场景下对象存储成为瓶颈,元数据引擎的差别被掩盖了。所以不能用这张表说明“某个引擎适合大文件”——它说明的是引擎不影响大文件。
- 元数据密集项差异明显:
Stat file上 Redis(约 12314 files/s)是 MySQL(约 3583)的 3 倍多、etcd(约 2837)的 4 倍多;Update meta上 TiKV(3.76 ms/op)和 etcd(3.40 ms/op)反而高于 Redis-Always(2.45 ms/op),与三副本复制开销的说明相符。
解读 mdtest 表:多客户端并发的元数据 IOPS
第三张表用 mdtest(版本 3.3.0)在 3 台客户端节点上并行压测,myhost主机文件内容为client1 slots=4/client2 slots=4/client3 slots=4,测试命令为:
# metadata only mpirun --use-hwthread-cpus --allow-run-as-root -np 12 --hostfile myhost --map-by slot /root/mdtest -b 3 -z 1 -I 100 -u -d /mnt/jfs # 12000 * 100KiB files mpirun --use-hwthread-cpus --allow-run-as-root -np 12 --hostfile myhost --map-by slot /root/mdtest -F -w 102400 -I 1000 -z 0 -u -d /mnt/jfsmdtest 表的单位是ops/sec,越大越好。选几行看:
| 项目 | Redis-Always | Redis-Everysec | MySQL | TiKV | etcd |
|---|---|---|---|---|---|
| Directory stat(空文件组) | 289992.466 | 379692.576 | 9359.278 | 49465.223 | 6500.178 |
| File stat(空文件组) | 288951.216 | 253218.558 | 9135.571 | 50432.658 | 6276.787 |
| File creation(空文件组) | 5472.628 | 9984.824 | 1326.613 | 4053.610 | 1801.956 |
| File read(100KiB 小文件组) | 62341.568 | 57998.398 | 4639.571 | 23376.733 | 5477.754 |
| File removal(空文件组) | 6084.791 | 12221.083 | 1073.063 | 3742.269 | 1648.734 |
解读要点:
- stat 类操作上 Redis 领先一到两个数量级(约 29 万 ops/s 对 MySQL 的约 9 千),这是纯元数据压力下的上限差距;
- 创建约 12000 个 100KiB 小文件时各引擎明显收敛(263~312 files/s 量级),这与文档结论“小 I/O(约 100 KiB)负载下,MySQL 总耗时约为 Redis 的 1~3 倍,TiKV 与 etcd 表现接近 MySQL”对应;
- 空文件组的
Tree removal里 Redis-Always(218.535)显著高于 Redis-Everysec(95.599),和直觉相反,说明单行数据不能脱离具体负载泛化,只能当该特定场景的参考。
fio 部分(4 MiB 块、4G 顺序写,fio --name=big-write --directory=/mnt/jfs --rw=write --refill_buffers --bs=4M --size=4G --numjobs=4 --end_fsync=1 --group_reporting)各引擎写入带宽都在 729~768 MiB/s,文档结论是大 I/O(约 4 MiB)负载下不同元数据引擎没有显著差异,对象存储成为瓶颈。
把三张表合成选型判断
三张表回答的问题不同,合成起来的判断逻辑是:
- 负载是纯元数据操作或大量小文件:引擎选择影响最大。Redis 明显最快;TiKV 次之(约为 Redis 的 2 倍延迟,且带三副本);MySQL 约为 Redis 的 2~4 倍;etcd 约为 TiKV 的 1.5 倍,stat 密集型下与 MySQL 差距最大。
- 负载以约 100 KiB 级别小文件读写为主:引擎间差距缩小到 1~3 倍,MySQL/TiKV/etcd 接近。
- 负载以大文件顺序读写为主:引擎选择不影响吞吐(对象存储是瓶颈),此时应转去看 Performance Evaluation Guide 里的对象存储侧测试(
juicefs objbench)和 Redis 的可靠性配置。 - 可靠性与副本:Redis 和 MySQL 在测试里是单副本,TiKV 和 etcd 是三副本 Raft。如果选型本身就要解决元数据高可用,TiKV/etcd 的延迟数字是含副本开销的“真实代价”;Redis 想降低丢失窗口则需要评估
appendfsync从everysec换回always带来的延迟上升。 - 容量规划:选型时同步估算元数据存储空间。按 How to Set Up Metadata Engine 给出的近似值,键值类引擎(Redis、TiKV)约 300 字节/文件,关系型引擎(MySQL、PostgreSQL 等)约 600 字节/文件;文件平均大于 64MB、碎片多、扩展属性多或文件名平均超过 50 字节时还需要更多空间。
注意文档给出的结论边界:这些倍数关系来自上述特定硬件与版本组合,文档没有承诺其他规模或引擎版本下保持同样的倍数,选型前建议按下一节在目标环境复测。
在自己的环境复测:验证选型结论是否成立
文档没有要求完全复刻 3 节点 mdtest 集群,最低成本的复测路径是juicefs bench:
用候选引擎分别
format出文件系统并挂载。各引擎的 META-URL 格式见 How to Set Up Metadata Engine,例如:# Redis juicefs format --storage s3 ... "redis://:mypassword@192.168.1.6:6379/1" pics # TiKV juicefs format --storage s3 ... "tikv://192.168.1.6:2379,192.168.1.7:2379,192.168.1.8:2379/jfs" pics # etcd juicefs format etcd://user:password@192.168.1.6:2379,192.168.1.7:2379,192.168.1.8:2379/jfs pics # MySQL juicefs format --storage s3 ... "mysql://user:mypassword@(192.168.1.6:3306)/juicefs" pics其中 IP、密码、前缀需替换为你自己的值;
--storage s3 ...代表对象存储相关参数按实际填写。JuiceFS v1.0+ 默认开启 Trash,基准测试会创建并删除临时文件,最终落入
.trash目录占用空间。测试前可用juicefs config META-URL --trash-days 0关闭 Trash(测试完按需恢复,该命令修改的是该文件系统的 Trash 保留天数配置)。挂载到
/mnt/jfs后执行:juicefs bench /mnt/jfs -p 4文档建议
-p设为服务器 CPU 核数。结果表格中VALUE为每秒处理能力,COST为单文件/单操作耗时。判断标准:对照官方表的量级而不是精确数值——如果你的环境里各候选引擎在
Stat file、Update meta上的相对差距与官方表(Redis 领先数倍、大文件各项接近)方向一致,说明官方倍数结论在你的环境成立;若差距远小于官方数据,优先怀疑网络、客户端规格或元数据主机磁盘与官方测试条件不一致。
如果你的负载包含大量空目录/小文件创建,再按文档中的 mdtest 命令(mpirun ... /root/mdtest ...)补充多客户端并发测试,命令以文档为准,/root/mdtest是文档中 mdtest 可执行文件的位置。
限制
- 该基准基于 JuiceFS 1.1.0-beta1+2023-06-08 及特定引擎版本,文档未提供其他版本组合的结果;
- golang benchmark 中
read类行因元数据缓存不可比,不要引用为读性能依据; - Redis 的两列结果对应不同的
appendfsync设置,比较时必须固定其中一列,否则把可靠性差异误读为引擎差异; - 大文件吞吐的引擎间差异不显著是“对象存储成为瓶颈”的结论,不代表元数据引擎可以忽略——stat、小文件创建等元数据密集路径上引擎差异依然存在。
【免费下载链接】juicefsJuiceFS is a distributed POSIX file system built on top of Redis and S3.项目地址: https://gitcode.com/GitHub_Trending/ju/juicefs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考