引言。
juicefs是为云原生设计的高性能分布式文件系统,xff1的特点如下a;
直接参考相关技术架构:https://juicefs.com/docs/zh/community/architecture。
写流程cache简要说明。
cache分为两层磁盘cache和内存cache。
源码分析。
编写同步线程处理。
func (fs *fileSystem) Write(cancel <-chan struct{ }, in *fuse.WriteIn, data []byte) (written uint32, code fuse.Status) func (v *VFS) Write(ctx Context, ino Ino, buf []byte, off, fh uint64) (err syscall.Errno) // filehandle获得 func (v *VFS) findHandle(inode Ino, fh uint64) *handle // 加文件写锁,如果有其他client并发写,等待 func (h *handle) Wlock(ctx Context) bool // filewriter编写数据 func (f *fileWriter) Write(ctx meta.Context, off uint64, data []byte) syscall.Errno // 目前file使用了1000多个slice,或者使用的buffersize大于预留,等待 // 加filewriter mutex锁,使用cas操作 f.Lock() // 等待正在进行的flush完成 // offset和length拆分chunk,单独写每个chunk func (f *fileWriter) writeChunk(ctx meta.Context, indx uint32, off uint32, data []byte) syscall.Errno // 根据文件的chunk idx找到相应的chunkwriter func (f *fileWriter) findChunk(i uint32) *chunkWriter // 在chunkwriter中找到slicewriter,如果没有合适的slice,申请新写作 func (c *chunkWriter) findWritableSlice(pos uint32, size uint32) *sliceWriter // 每一个slice遍历c;发现未覆盖的slice直接使用,如果没有可用的slice,再在外面申请一个 // 每个chunk当第一个slice生成时,启动异步线程,等待数据写盘,刷slice到对象存储的映射。 func (c *chunkWriter) commitThread() // slicewriter写数据 func (s *sliceWriter) write(ctx meta.Context, off uint32, data []uint8) syscall.Errno // 将数据写入buffer func (s *wSlice) WriteAt(p []byte, off int64) (n int, err error) // 如果只是写满chunk,异步刷盘#xff08;异步) func (s *sliceWriter) flushData()。
slice刷盘。
func (s *sliceWriter) flushData( // 生成sliceid func (s *sliceWriter) prepareID( // 刷盘 func (s *wSlice) Finish( func (s *wSlice) FlushTo( // 遍历每一个block刷盘 func (s *wSlice) upload( // sliceidchunkidx,blocksize生成key用于对象存储文件名 func (s *rSlice) key( // slice数据写盘(异步) go func() { // 标记slice刷盘完成 func (s *sliceWriter) markDone(。
slice数据写盘。
func (s *wSlice) upload( go func() // 写磁盘cache,存储在加速盘中 func (cache *cacheStore) stage // 生成路径与对象存储相关的路径一致,将数据写到本地文件系统目录 func (cache *cacheStore) flushPage( // 将数据写入磁盘cache༌即使用os本地文件系统写文件 func (f *File) Write( // 插入keymap,将key、datasize、atime,插入内存cache func (cache *cacheStore) add( // 如果内存cache空间不足,触发淘汰 // 数据上传到对象存储 func (store *cachedStore) upload( // 存储上传对象 func (store *cachedStore) put( // 更新内存cache中的key,与data相对应 func (cache *cacheStore) uploaded( // 删除本地文件系统cache的文件 os.Remove(stagingPath)。
关键总结。
slice中的连续小io将在slice中聚合,等待触发刷slice。
参考文献。
https://juicefs.com/docs/zh/community/internals。