LFS 论文阅读笔记

来源:互联网 发布:初中视频免费教学软件 编辑:程序博客网 时间:2024/05/17 09:44

简介

  • 将所有对磁盘的操作(sequentially)顺序的写入类似于日志的结构中,可以加速对文件写以及恢复
  • 包含索引信息因此可以从日志结构中很快的读取
  • 为了在磁盘中保持一大块空闲区域供以快速写入,将日志分成了段(segments),并且使用(segment cleaner)块清理器从碎片化严重的段中压缩有用的信息
  • Sprite LFS比当时的Unix文件系统在小文件写方面性能高出一个数量级,并且在读以及大文件写入方面也要优于,他能利用70%的磁盘带宽用于写入,而其他的只有5-10%

1. 介绍(Introduction)

  • 磁盘速度成为一个性能瓶颈,LFS 可以有效解决这个问题
  • 基于一个假定前提:文件会被缓存在内存中,加大内存的大小会满足在读请求方面的效率
  • 将操作写入日志(log)中的方法可以极大提升写入性能因为消除了大部分的寻道开销(seek)
  • 同时崩溃恢复方面只需要检查日志结构的最新部分,而不是去扫描整个盘面来恢复数据的一致性
  • 将所有数据永久存在log结构中,包含索引信息,所以读取很高效
  • 需要一大块(large extent)的空闲区域来供以写入数据,这样才高效运行,通过提供大块空闲区域(),段清理器可以通过压缩数据来持续地提供空的段
  • 同时,经过模拟实验,发现一个简单但是性价比很高的(压缩/清理)算法:将新旧数据区别对待,因为旧的数据很少被改变、新的数据改变较多
  • Sprite LFS性能很好,除了一种情况(文件随机写之后再顺序读
  • 65%-75%的带宽用于写数据,另外的用于清理;普通的5%-10%用于写数据,其他的用于寻道(太可怕了,寻道时间)

2. 1990’S年代的文件系统

主要讲了1990’s文件系统设计中的问题

文件系统设计的两个决定性因素:
- 技术(Technology)
- 工作负载(Workload)

2.1 技术(CPU、磁盘、内存)

  • 磁盘的增长主要在于容量和成本上,性能方面(传输带宽和存取时间)远远比不上CPU的增长速度
  • 传输带宽可以通过磁盘阵列和平行磁头技术来提升,但是存取时间因为被机械运动(mechanical motion)限制了,很难提升。
  • 大内存 == 大的文件缓存区域,对文件系统有两大影响:
    1. 改变了磁盘的工作负载,更多的是读请求。出于安全考虑,最终的写请求都会被映射到磁盘上,磁盘细嫩那个的决定性因素的是磁盘写。
    1. 大的文件缓存可以充当写缓冲区的角色,收集更多的写操作最后才一次性写回磁盘。当然,缓冲带来的弊端就是崩溃恢复很难,要求高或许可以使用非易失性的RAM。

2.2 工作负载

  • 目前文件系统应用的工作负载主要集中在对于小文件的操作,这会造成大量小的随机磁盘I/O,性能取决于文件系统对于“元数据(metadata)”的更新
  • 大文件顺序读取受限于磁盘的带宽,并不会太多的受到文件放置策略
    (file allocation policies)的影响
  • 所以Sprite LFS着力于解决高效地获取小文件。

2.3 现存文件系统的问题

两个大问题:
1. 文件系统将信息分布在磁盘中,会导致大量的小的存取操作;同时,文件的属性(inode)的存放和文件内容是分开的,也会增加读取操作(寻道啊。。。最终就只有5%的带宽用于写数据,其他都用来寻道了,哈哈哈哈)例如,创建一个小文件,需要5次磁盘I/O:两次文件属性、文件内容、目录内容、目录属性。
2. 第二个问题是写数据的过程是同步的,应用必须等待写完成才能继续执行。Unix FFS写数据块是异步的,但是其写元数据是同步的,所以对于大量小文件工作负载来说,磁盘的性能受限于同步地写元数据。
- 因此现存文件系统不支持试用文件缓存来作为文件写缓冲区使用。。。。

3. 日志结构文件系统(Log-structured file systems)

第 3 节讨论了日志结构文件系统设计的可选方案,并导出了 Sprite LFS 的结构,主要关注于清理机制

基本思想 : 通过在内存的文件缓存中缓冲一系列的文件系统更改。最后通过单一的磁盘写操作顺序地写到磁盘中。将大量的小随机同步写转换成了一次大的顺序同步写。

两个问题:
1. 如何从日志中快速读取信息(3.1)
2. 如何在磁盘中保持大块空闲区域供以写入数据(3.2 - 3.6)

3.1 文件定位和读取

利用下列的数据结构达到快速地文件读取:

Data Structure Purpose Location inode 保存文件属性(保护位、修改时间等)、文件的磁盘块地址(如果文件磁盘块大于10,将还包含indirect blocks的地址) 日志(log) Inode map 日志中inode的位置,还有上次存取时间以及版本号 日志(log) Indirect block 包含更多数据的地址或者是indirect block的地址 日志(log)

- 普通文件系统inode节点存放在一块非固定的区域中,很简单可以找到,和普通的Unix 文件系统不同,日志结构文件系统将inode存放在了日志结构中,所以有一个inode map 存放identifying numberinode 块位置的映射,同时会有一个固定位置的checkpoint来指示inode map块位置(block address)
- 因为inode map的查询操作需要很少的磁盘I/O,带来的紧凑性可以被缓存在内存中。
- 日志文件系统的排放是非常紧凑的,所以在获得高性能的写操作的同时又有和其他文件系统同样快速地读取操作。

3.2 空闲空间管理:分段(segments)

注意:在日志结构文件系统扩张到磁盘末尾的时候,因为文件的删除和覆盖操作,磁盘的空间将会被严重的碎片化!
- 有两种方法解决这个问题:穿插thread和复制copy
- 1. 穿插:在空闲的碎片块中写入新的数据,这将加剧磁盘文件系统的碎片化
- 2. 复制:每当磁盘用到末尾的时候就将所有的数据往前移动,这样会导致一些长久存放的文件反复被复制,开销非常大
- Sprite LFS结合了这两个方法:磁盘被分成了固定大小的区域–段segment。它的特性就是:对端写操作必须是从开头到结束;在段被复写之前,所有的有效数据将会复制出去。
- 日志log是基于segment-by-segment分布的,这样把长期有效的数据放在某些段中,在复制的时候这些段就可以被跳过。同时段segment的大小也是足够大可以保证读或写一个段的时间会远大于寻道的时间,这样几乎所有的带宽都用在了对段的操作上。(512KB或者1MB,现在可能更大。。。)

3.3 段清理机制(mechanism)

  • 步骤很简单:1.将一些内存段读入内存;2.验证段中数据的有效性;3.将段中有效的数据重新写回干净的段中clean segments。这样被读过的段就会是clean的
  • 段清理必须要清楚每个块属于哪个文件并且块在文件中的位置,这些信息将用于更新inode指向新的block
  • 利用每个段中的数据结构–端摘要segment summary(包含文件编号以及块偏移量),段摘要块标识出了写入段中的所有信息;例如对于每一个数据块段摘要都有文件编号和块编号。
  • 通过在inode map中保存一个叫版本号version number的数据,当文件被删除或者长度归零时版本号将递增,版本号和inode编号结合起来形成了文件内容的唯一标识号(uid)。故如果在segment summary中一个块的uid和当前存储在inode map中的uid不匹配,该块就会被立即丢弃,无需检查文件的 inode 。
  • 无空闲块表以及无位映射图,简化了崩溃恢复

3.4 段清理策略(policies)

关于如何进行段清理,有四个策略问题需要解决:
1. 什么时候后去清理?
- 答: 这个问题作者没有理论上的方法,采用了阈值策略,当cleande'shi'h segment数量小于10的时候开始清理,大于某个数值的时候停止清理。
2. 一次应该清理多少个segment
- 答: 这个问题也没有理论上的方法。。。一次清理几十个块吧。

其实前两个问题对于LFS的性能影响不大。。。重点是后两个问题。

说明:u代表segment的利用率(0 <= u < 1);write cost 是写入数据开销,是写入一个byte磁盘忙碌的平均时间数量,包含所有的清理开销、寻道、旋转延迟等,因为段被设计的足够大,所以可以忽略寻道和旋转等待时间,write cost就是总的磁盘I/O的byte数除以写入磁盘的新数据byte数。
- 在稳定状态下,每写一个segment,都应该产生一个空的segment。
- 可以很明显的看出来,利用率u越小越好!

write cost=total bytes read and writtennew data written=read segs +write live+write newnew data written=N+Nu+N(1u)N(1u)=21u

3. 哪些segment需要被清理?
- 答:当然是那些segemnt利用率低的,同时这也可能带来一个取舍:低的磁盘利用率换来高性能的LFS,代价是高的数据存储成本。所以可以这样:大部分的segment是满的,留下小部分的segment为空或者几乎没有使用,用于清理,这样清理器将会一直在这些空的segment上工作,即保持了高的磁盘利用率,又获得了高性能的LFS。
4. 清理之后如何排放有效的数据?
- 答:似乎没有看到明确的解答,但是作者好像提了使用age sort的方法,就是将有效数据的块根据修改时间来排序,将有着相似修改时间的块放置在一起分为一组。

3.5 模拟实验结果(Simulation results)

模拟器比起实际环境更加严苛,用于帮助了解随机存储模式以及文件放置位置的影响。使用固定数量的4kb大小的文件来保持固定的全局磁盘利用率。每次模拟器simulator重写一个文件,使用下面两种随机存储模型:

  1. Uniform:每个文件拥有相同的访问概率,也就是说,在清理器清理完segment之后,写回有效数据的时候,并不会重新组织有效数据的排放顺序(故自然不会在重新组织上有任何提升)。
  2. Hot-and-cold:重新写回数据的时候将long-lived(cold)的数据和short-lived(hot)的数据分开不同的数据段存放。(10%的hot文件90%被选择,90%的cold文件在10%的时间被选择)

使用贪婪清理策略的模拟结果

  • 从上图可以看出,和wrtie cost的计算公式相比,在磁盘利用率<0.2的时候,write cost是小于2的(其实总体的write cost都要低),因为实际上清理器清理的段并没有需要读入的数据。
  • 但是,可以发现一个很奇怪的现象,使用了hot-and-cold策略之后(甚至在改变hot和cold的比例之后效果更差)write cost竟然升高了???什么情况???我看到这里也是一脸懵逼(-_-#)
  • 原来是因为使用了贪婪的清理策略greedy policy(只清理那些segment利用率最低的segment),但是对于cold数据所在的segment来说,利用率很难下降到清理点阈值之下,所以有很多的cold segment就一直苟活,苟活的同时又一直占用了大量的空的blocks。。。

这里写图片描述

  • 这幅图说明了locality导致在清理点被清理的segment的平均利用率更高,当然write cost会上升啦!
  • 收到这幅图的启发,在cold segment里面的空闲空间比hot segment里面是更加有价值的,因为一旦cold segment被清理重排过后的一段相当长的时间内不会产生空闲空间!
  • 因此,段中空闲空间的价值基于段中数据的稳定性,但是很难去衡量数据的稳定性因为无法得知数据未来的存取情况,所以使用文件的存活时间来假定数据稳定性:越老的数据越有可能不被改变,也就是越稳定。

4. 崩溃恢复(Crash recovery)

5. 基于Sprite LFS的实验

第 5 节基于基准测试程序和清理开销的长期度量对 Sprite LFS 进行评估

6. 相关工作(Related work)

第 6 节比较了 Sprite LFS 和其他文件系统

原创粉丝点击