简述日志结构文件系统(LFS)
这篇文章只是简单的对日志结构文件系统LFS做一个简要了解,很多细节没有
传统文件系统的问题
在内存越来越大的今天,无论是操作系统还是应用软件越来越趋向于在内存中建立更多的磁盘缓存,这带来了更多的写入。
在传统文件系统中,写入操作要更新很多个块,各种位图、inode、数据块、父inode等,即使是将它们都写到同一个柱面组的FFS,也会出现很多短寻道和旋转延时。总而言之就是——带来太多的随机IO
由于顺序IO和随机IO的性能差异(该差异正在不断加大),日志结构文件系统(LFS)致力于将随机写入转换成顺序写入,对于读取,没办法了,因为随机读是用户的权力。
如何按顺序写入
一定要记住重点!!顺序写入!写入!写入!和读取没关系!
首先,LFS将inode和其指向的数据块紧密排布,而不是像传统文件系统,专门有一个区域保存inode,这避免了写入inode和数据块时的随机IO。
其次,LFS使用写入缓冲,在内存中更新,等更新了足够数量,立即将它们写入磁盘,这保证了LFS可以一次将一大批写入数据落盘。如下图,可能是LFS的一次写入的内容。
LFS一次写入的大块更新被称为段,显然,LFS的性能取决于段大小,因为一次写入的段越长,就有越多的数据可以被打包到一次顺序IO写入中。
多像Kafka的batch日志写入,不,应该说Kafka多像这个!后面还有更像的...
如何查找inode
为了保证顺序写入,inode被分散到了磁盘上各个位置,这使得LFS没办法像其它文件系统一样快速通过inode区域起始地址 + inode号
索引到inode。
而且,同一个inode号可能会在LFS中保存多个副本,比如5秒钟前被保存了一次,5秒钟后又保存一次,显然前面那个已经是过时的旧数据了。
LFS通过一个imap
来保存最新版本inode号到inode物理位置的映射。
多像Kafka的consumer offset版本映射...
但新问题是,每次写数据时都要写imap
,好不容易转出来的顺序IO又变大量随机IO了。
其实感觉也可以在持久化段时把其中所有inode地址提出来一次性写到
imap
,就是两次随机IO,但这样也可能出现不一致
LFS采用的策略是为每次更新保存一个imap
,并且它就紧挨着这次更新的数据放置:
现在imap
又在磁盘中散落了......新的问题是如何快速定位imap
最终的办法是在磁盘上保存唯一的固定位置,称为检查点区域(CS),它保存inode号到它最新的imap的映射,并且它定期更新(30s),并不(很大程度)影响顺序写入。
读取文件的步骤
- 读检查点区域,找到inode对应imap
- 根据imap找到inode对应物理位置
- 后面一样了
垃圾收集
LFS需要定期清理已经过时的旧版本数据。
LFS的大段写入机制给垃圾收集也带来了便利,垃圾收集往往能回收到大片的区域,不至于留下太多小的内存空洞(碎片)。
LFS清理程序定期读入许多旧的(部分使用的)段,确定哪些块在这些段中存 在,然后写出一组新的段,只包含其中活着的块,从而释放旧块用于写入。