juicefs IO流程源码解读

juicefs作为一个基于对象存储的文件系统,结合了低成本和完整的POSIX语义。文章详细介绍了juicefs的写入和读取流程,包括如何利用chunk和slice优化IO性能,以及支持客户端缓存和异步flush机制,特别适合AI训练场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    juicefs是一个基于对象存储底座的文件系统,因其兼具对象存储的低成本和完整posix语义而受众多用户喜爱,同时易于支持完备的客户端缓存,在AI训练场景尤其出众,本篇针对juicefs最核心的IO流程进行源码剖析。

1. 写流程

fileSystem.Write(in fuse.WriteIn, data []byte)
  -> VFS.Write(Ino(in.NodeId), buf, in.Offset, in.Fh) // Offset是file的offset
    -> handle.fileWriter.Write(off, buf) // off是file的offset
      -> fileWriter.writeChunk(indx, off, data) // indx表示chunk在file中的编号, off表示chunk中的offset
          -> chunkWriter.findWritableSlice(off) // off表示chunk中的offset, 为支持合并写, 将chunk分成若干slice, 每个slice都有一个sliceWriter, 每个chunkWriter都有一个commitThread负责后台flush
                sliceWriter.write(off, data) // off表示slice中的offset
                  -> wSlice.WriteAt(p, off) //  将数据写到内存buffer, off表示slice中的offset
commitThread // loop扫描每个slice
  -> sliceWriter.flushData() // 每个slice被freeze后就起一个异步flush线程, 待flush done
    -> sliceWriter.chunkWriter.Finish(length) // length是该slice中冻结的数据长度
      -> wSlice.FlushTo(offset) // flush offset前未upload的数据, 其中, offset是flush的截止偏移
        ->wSlice.upload(index) // index是block在slice中的编号
       chunkWriter.fileWriter.dataWriter.Meta.Write(inode, indx, off, slice) // slice数据flush done之后, 将slice的元数据append到chunk.slices后面, 这里index是file中的chunk编号, off是chunk中的offset

2. 读流程

fileSystem.Read(in fuse.ReadIn, buf []byte)
  -> VFS.Read(Ino(in.NodeId), buf, in.Offset, in.Fh) // 读取文件指定偏移, 这里Offset是file的offset
    -> handle.fileReader.Read(off, buf) // 读取文件对象指定偏移, 这里off是file的offset
      -> fileReader.splitRange(block) // 这里block表示文件的一个区间, 为支持slice读合并, 将block分成若干slice,
          fileReader.prepareRequests(ranges) // 每个slice有一个sliceReader负责读数据, 这里起异步sliceReader
          fileReader.waitForIO(reqs, buf) // 这里req.frange.off是req.sliceReader这个slice中的offset, 这里调用后等待数据ready被唤醒
sliceReader.Run()
  -> sliceReader.fileReader.dataReader.Meta.Read(inode, index, &slices) // sliceReader读取chunk对应的slice列表, 这里index是file中的chunk编号
     sliceReader.fileReader.dataReader.Read(page, slices, offset) // sliceReader读取数据, 这里offset是chunk中的offset
       ->dataReader.readSlice(s *meta.Slice, page *chunk.Page, off int) // 这里off是Slice中的有效offset
         ->rSlice.ReadAt(p Page, off int) // 这里rSlice指特定meta.Slice的读取实体, off是meta.Slice中的offset, p是数据存放地址
     sliceReader.Done() // 数据ready, 唤醒主线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值