Log-structured File Systems
换到博客园排版有问题,原版在这里:http://xubenbenhit.github.io/LogStructureFileSystem.html
Log-structured File Systems
先来扯淡,这篇博客讲的是LFS,之前写的硬盘与磁盘冗余阵列其实是第一篇,而这个应该算是第三篇,这中间差了一篇介绍文件系统的博客,原本打算今天回去之后一起写了,但是考虑到自己回家之后的效率不敢保证。故而先在实验室写完这个文章,而文件系统的资料全部在家。
1. 什么是LFS?
首先回顾一下我们是怎么来写Log文件的,不就是把最新的状态一行一行的写在日志文件的最末尾么(这个联系是我自己YY的)。那么Log-structured File System也是一样,就是更新数据的时候直接将数据放在末尾。如下图:
一开始,我们写入磁盘数据块Foo,然后旁边的A是它的inode:
然后,我们再写入块Bar,旁边的A'是inode:
最后,我们更新数据块Foo,获得Foo',这时候我们将其写回磁盘,就变成这样子:
2. LFS是怎么来的?
LFS是在上个世纪九十年代前后搞出来的,当时的主要考虑有这个几点(道听途说):
❝
内存越来越大,进而可以不断扩充Cache的容量,也就会意味着数据读取操作可以越来越不需要访问磁盘了,进而使得磁盘写操作越来也成为性能瓶颈;
序列磁盘数据读取速度跟随机读取磁盘数据速度的差距越来越大,这种情况下如果可以将随机磁盘操作转换为序列磁盘操作,则收益可观;
处理小文件的时候,之前的文件系统效率不高,而事实上小文件才是常见的;此外对于小文件的写操作,磁盘本身也不擅长,因为RAID4/RAID5处理小文件的时候性能也是不高的;
❞
因为有了这些,所以就有了LFS。LFS首先将磁盘数据的更新缓存在Cache中,当缓存到一定规模(称之为一个segment)的时候再一次性写入空闲磁盘,由此获得高性能。 当然了,说起来很简单,做起来就不是喽,这里面主要有两个方面的问题:其一是整个操作过程中的文件定位;其二是磁盘空间管理。
这里我觉得就不按照论文的思路来写了,因为没劲,不如就按照自己的理解一步步来做推演吧,比较论文作者也是自己一步步想出来的。
3. 开始推演
LFS是先在内存在存储文件更新,这个存储单元称之为一个segment,等到segment存满了的时候再一次性写入空闲磁盘。于是乎就需要首先保证整个操作的正确和高效。
首先,根据FFS(Fast FIle System)的设计经验,需要用一个inode来存储这个segment中每个文件的元信息,也就是文件的一些属性,诸如大小、文件块(文件可能需要多个磁盘block来存储)的物理地址、权限等等。当然了,inode也是在segment中的,为了方便考虑就存储在对应文件的后面,见第一部分的图。注意一点,这个inode一般很小,只有128Byte左右。
按照FFS的设计,将inode存储在一块连续的磁盘空间(物理地址是可以事先计算的),但是一次性将segment写入磁盘这个操作本身就会使得文件的inode“散布在”整个磁盘空间,而且按照LFS的设计,文件是不可能被原地修改的,这也就意味着最新版的文件的inode的地址始终在变化!!故而按照“惯例”,设计一层间接连接(indirection),称为imap,用来存储各个inode的物理地址。
既然有了imap,那么问题来了,imap存储在哪儿?第一种选择是将其存储在磁盘的某一固定位置,但是我们注意到每次写segment的时候都会对imap进行更新,而每次更新imap都需要将磁头转到固定位置,有点影响效率啊!不如将imap放在inode后面吧。
这里多说一句,imap本身可能也占用多个磁盘block,故而只需要将更新的那一块imap放在inode后面就可以了。这样又有个问题,imap地址不确定,怎么寻址呢?所以还是需要一个地址确定的区域,里面存储imap的地址就可以了,这个区域称之为CheckRegion,这里面存储了imap各个block的物理地址。就可以通过CheckRegion->imap->inode->file的方式定位到文件了。但是,文件夹怎么处理?
按照FFS的设计,所谓的文件夹无非就是一些文件名和文件inode的映射,在FFS中文件夹被当做普通的文件数据来存储,那么LFS也这么干。于是我们就可以看到 /dir/foo 是这样存储的:
具体而言是这样,首先定位到dir文件夹的inode所在的imap,然后根据查找到dir文件夹的inode物理地址,然后找到dir文件夹的物理地址,进而获取foo文件的inode,然后在CR->imap->inode->foo。注意到这样设计还有一个意外的好处,就是说文件夹下的文件更新操作是不需要更新文件夹本身的,这也就避免了“递归更新”文件夹的文件夹的文件夹。。。好的,至此,文件定位以及没有问题了。但是每次这样将segment写入空闲磁盘,一直这样下去,哪有那么多磁盘呢?这就涉及到磁盘空间回收(segment cleaning)的问题了。
一般来说,磁盘空间回收大致需要这三步:首先将一些segment读入内存;然后判断segment里面的block数据是否是“存活的”,也就是说文件是否处于最新版本;最后将所有的“存活”文件集中写进segment中,而将剩下的空间回收。如何判断block是否为最新版本?
为了实现这个功能,那么就需要知道segment中block的原信息了,比如它所归属的文件inode以及在文件中的位置。这些信息需要存储在segment中的一个称为segment summary block的区域中。那么我们就可以查找这个block数据的当前物理地址,比对一下就知道是否是最新版了。当然了,这样一来,最好将imap整个加载到内存中方便查询。
当然了,可以改进这个设定,为每个文件设置版本号,每次文件更新版本号递增,将这个版本号存储在segment summary block以及imap中,这样只需要比对一下文件版本号就可以判断整个文件是否是最新版本了。关于segment clean,什么时候执行呢?执行clean达到什么目标就停止呢?怎么选择segment执行clean?以及是否需要重组live file以便获得更好的locality? 第一个第二个实验表明不太重要,实际操作而言,设置两个阈值,点那个空闲segment数目低于某一阈值后执行clean,当回收使得空闲segment数目高于另一阈值后停止clean。
第三个问题很有讲究,事实上,论文中采用的算法是计算每个segment的clean性价比(cost-benefit),这个计算公式具体参考论文吧。为此在CheckRegine中保存一个segment usuage的表单。
第四个问题,也是很有技巧性的地方,论文中的做法是按照存活文件最近一次更改时间的顺序依次写入segment中。至此,描述的差不多了,下面看看两个细节。
Check Point Check Region中包含的数据imap地址以及segment usage等等都是在变化的,所以需要每过一段时间更新一下。正常情况下先将Cache中的segment写入磁盘,然后更新Check Region,因为考虑到更新CR过程中也可能出现异常,所以用两个timestamp块包裹住真实的CR数据,只有当前后两个timestamp一致的时候才认为这个CR是正常的。为了避免在更新CR过程中出现故障导致CR不可用,LFS使用两个CR,交替使用,这样即使故障了,也可以用另一个CR来恢复。
Crash Recovery 遇到特殊故障,LFS怎么恢复呢? 首先,寻找到最新的可用CR,这里的“可用”表示该CR的前后timestamp是一致的。然后使用论文中提及的Roll-Followed算法来恢复。这里面有一个“奇怪”的地方,就是说imap的最新版block不都已经在segment里面了么,那么直接用这个更新就可以了嘛!!其实不是的,因为考虑到磁盘写操作的时候imap本身可能没有写正确。。。。
至此,应该是差不多了,详细的东系统的介绍直接看下面的资料吧。
4. 参考文献
❝
- http://pages.cs.wisc.edu/~remzi/OSTEP/file-lfs.pdf
- http://www.eecs.berkeley.edu/Pubs/TechRpts/1992/CSD-92-696.pdf
- http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.54.502
- http://blog.notdot.net/2009/12/Damn-Cool-Algorithms-Log-structured-storage
❞
Log-structured File Systems的更多相关文章
- The storage wars: Shadow Paging, Log Structured Merge and Write Ahead Logging
The storage wars: Shadow Paging, Log Structured Merge and Write Ahead Logging previous: Seek, and yo ...
- SSTable and Log Structured Storage: LevelDB
If Protocol Buffers is the lingua franca of individual data record at Google, then the Sorted String ...
- Introducing Microsoft Sync Framework: Sync Services for File Systems
https://msdn.microsoft.com/en-us/sync/bb887623 Introduction to Microsoft Sync Framework File Synchro ...
- Mounting File Systems
1.Mounting File Systems Just creating a partition and putting a file system on it is not enough to s ...
- Canal 同步异常分析:Could not find first log file name in binary log index file
文章首发于[博客园-陈树义],点击跳转到原文Canal同步异常分析:Could not find first log file name in binary log index file. 公司搜索相 ...
- Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'系列一:
从库报这个错误:Got fatal error 1236 from master when reading data from binary log: 'Could not find first lo ...
- centos重启报错Umounting file systems:umount:/opt:device is busy
系统重启报错: Umounting file systems:umount:/opt:device is busy 只能硬关机,回想一下最近刚安装了nod32 for linux x64的杀毒软件,开 ...
- mysql从库Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'报错处理
年后回来查看mysql运行状况与备份情况,登录mysql从库查看主从同步状态 mysql> show slave status\G; *************************** . ...
- 'Could not find first log file name in binary log index file'的解决办法
数据库主从出错: Slave_IO_Running: No 一方面原因是因为网络通信的问题也有可能是日志读取错误的问题.以下是日志出错问题的解决方案: Last_IO_Error: Got fatal ...
随机推荐
- 2018软工实践—Alpha冲刺(7)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 学习MSI.CUDA 试运行软件并调试 ...
- JNDI和JDBC
没有JNDI的做法:程序员开发时,知道要开发访问MySQL数据库的应用,于是将一个对 MySQL JDBC 驱动程序类的引用进行了编码,并通过使用适当的 JDBC URL 连接到数据库.就像以下代码这 ...
- 201621123037《Java程序设计》第二周学习总结
#Week02-Java基本语法与类库 1. 本周学习总结 关键词:常量池.对象.null.不可变性.string对象拼接.字符串池 关键概念之间的联系:Java中有常量池,超出常量池以外的就会新开辟 ...
- QSet使用及Qt自定义类型使用QHash等算法
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QSet使用及Qt自定义类型使用QHash等算法 本文地址:http://techie ...
- 对scrum站立会议的理解
个人理解:首先我不明白scrum的含义,查了一下,scrum是迭代式增量软件开发过程,通常用于敏捷开发.scrum包括了一系列实践和预定义角色的过程骨架.scrum中的主要角色包括同项目经理类似的sc ...
- 【beta】视频预发布
beta阶段视频发布地址: 秒拍: http://www.miaopai.com/show/Ivh31LgnAuWELxboH6gl7g__.htm
- React Native 学习-组件说明和生命周期
组件的详细说明(Component Specifications) 当通过调用 React.createClass() 来创建组件的时候,你应该提供一个包含 render 方法的对象,并且也可以包含其 ...
- QP(Quote-Printable) 编码
QP(Quote-Printable) 方法,通常缩写为“Q”方法,其原理是把一个 8 bit 的字符用两个16进制数值表示,然后在前面加“=”.所以我们看到经过QP编码 后的文件通常是这 ...
- Java web 强制301跳转
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); response.setHeader("Location" ...
- iOS-开发者账号与证书
0.开发者账号的申请 1.iOS-证书相关 2.iOS-证书申请 3.iOS-APNS证书申请与使用 4.iOS-App发布证书的申请与使用