Tier Storage ,一个全能的分布式文件系统
以JuiceFS为代表分布式文件系统有效的部分解决了存储与计算分离的诉求,在性能上取得一定的平衡。关于JuiceFS是什么,可以参考JuiceFS你应该知道的一些事。 不过,JuiceFS从某种角度而言,是一个缓存系统(本质是一个标准的分布式文件系统),他会充分利用本地的内存和磁盘去加速对象存储的读写,但这种模式对于那种基本上是“一次读一次写”的诉求,难以达到理想性能。而所谓“一次读一次写”的典型场景是计算引擎的shuffle场景和数据交换的场景,这导致Shuffle性能和使用本地磁盘性能相差巨大。其次,JuiceFS没有很好的解决异构存储的问题,用户可能为了性能,愿意优先将数据保存在本地磁盘,其次本地磁盘不足,才使用对象存储,从而在性能和价格方面获得一个比较好的平衡。
通常,我们把数据存储分成两类:
- 短生命周期数据。允许丢失,系统一般都会自动failover,一般是使用完会立即删除。比如Shuffle数据,不同系统的数据交换等。
- 长生命周期数据。不允许丢失,典型比如结果数据,一般会存储到数仓,数仓等地。我们平时接触的大部分数据都是这种类型数据。
JuiceFS/Alluxio目前主要面向的都是长生命周期的数据,也就是只实现了Cache模式。而对于短生命周期数据,最好的模式Tier模式。 我基于JuiceFS实现了Tier模式,具体原型实现代码在这里
我们在原来JuiceFS的基础上新增了三个参数:
- store-mode 枚举值: cache/hierarchy
- store-disk-size 数字
- store-disk-dir 目录列表,按逗号分割
当我们使用Tier模式,并且同时配置了store-disk-dir,cache-dir。store-disk-dir会作为优先盘使用,如果本地写满了,才会往对象存储上写(这里我配置的也是本地存储替代实际的对象存储)。
在这种模式下,对于shuffle而言:
- 如果shuffle比较小,那么会完全使用本地磁盘,性能基本没有损耗。
- 如果shuffle很大,用户本地磁盘不够,JuiceFS则会spill到对象存储。当然了,用户如果追求性能也可以选择继续手动或者自动增加本地磁盘。但无论如何,我们解决了偶尔出现的超大shuffle超出本地磁盘会失败的问题。
- 上层引擎无感知,无需修改Spark/Flink关于shuffle的代码
此外,我们还实现了节点可以互相取数据的功能,这意味着,
- 我们可以很方便使用多个节点的本地磁盘组成一个分布式文件系统
- 缓存可以在节点之间互相“窃取”,避免数据需要回源(从对象存储获取)
- 对Tier模式来说,这也是必须的功能
PS: 通过多个目录挂载,一个应用可以同时使用cache模式,tier模式,从而覆盖大部分场景。比如Spark,正常的读写我们配置按cache的挂载的目录,而对于shuffle,则配置挂载了Tier模式的目录即可。
缓存“窃取”的测试案例
假设我们在一个机器上启动两个实例:
实例A:
./juicefs mount -o debug --store-mode hierarchy --store-disk-dir /Users/allwefantasy/.juicefs/store --cache-dir /Users/allwefantasy/.juicefs/cache --store-disk-size 1024 localhost /Users/allwefantasy/jfs
实例B:
./juicefs mount -o debug --store-mode hierarchy --store-disk-dir /Users/allwefantasy/.juicefs/store1 --cache-dir /Users/allwefantasy/.juicefs/cache1 --store-disk-size 1024 localhost /Users/allwefantasy/jfs1
实例A中,我们挂载了/Users/allwefantasy/jfs目录,实例B,我们挂载的是 /Users/allwefantasy/jfs1。
我们往/Users/allwefantasy/jfs 写入文件:
(dev) [w@me ~]$ echo "dfkdafekafkekafkkakefk" > jfs/dd7.txt
接着我们可以从/Users/allwefantasy/jfs1中获取文件内容
(dev) [w@me ~]$ cat jfs1/dd7.txt
这说明,实例之间已经可以互相读取文件了。
我们也可以写入一个大文件,超过1024M(亦或是减少store-disk-size),数据会被分散保存在store-disk-dir以及对象存储里。
cache-dir会和store-disk-dir 有重复么?
相同节点的cache-dir 和 store-disk-dir 不会有数据重复。当数据写入到store-disk-dir的时候,会在cache-dir中做软链接,而非复制数据。
不同节点之间,同一份数据可能会同时存在于cache-dir/store-disk-dir,因为当我们读取别的节点的数据,会缓存到cache-dir中,避免反复去别的节点读取。不过未来可以让用户自己控制,从而在性能和存储成本上获得一个tradeoff.
数据清理
如果是shuffle,那么计算引擎会清理掉本地写入的数据。如果是其他场景使用了hierarchy,则缓存会通过各个节点自身的定时任务自动清理。
RoadMap
- 进一步完善使其 solid,并且production ready.
- 回馈给JuiceFS社区
- 增加内存支持。形成 mem-disk-object store三个层级。目前是两个层级。