LFS(the Log-structured File System)系统详解

There was a large and growing gap between random I/O performance and sequential I/O performance:

Existing file systems perform poorly on many common workloads:

LFS文件系统的设计木主要是为了解决上面这以前文件系统所存在的两个问题:随机输入输出的性能和序列输入输出的性能相差很大;还有就是磁盘搜索和旋转延迟比较大。

LFS,
short for the Log-structured File System. When writing to disk, LFS first buffers
all updates (including metadata!) in an inmemory segment; when the segment is full,
it is written to disk in one long, sequential transfer to an unused part of the disk. LFS never overwrites existing data, but ratheralways
writes segments to free locations.

LFS文件系统的主要算法就是首先把所有的更新(包括元数据)缓存在内存中的成为segment的单位中。当segment填满之后,里面的数据就写入到磁盘中未使用的地方。
特别要注意的是:LFS并不会覆写已有的数据,而是把segment中的数据写入到磁盘中新的位置。(这样在磁盘中就会有old data和new data,在后面会详细讲到)

This
basic idea, of simply writing all updates (such as data blocks, inodes, etc.) to the disk sequentially, sits at the heart of LFS. If you understand this, you get the basic idea. But as with all complicated systems, the devil is in the details.

怎么把所以对文件系统状态的修改更新转换为一个序列操作呢?了解文件系统以及文件系统底层操作的就会知道,当我们在新建文件或文件夹,以及向文件中添加或删除数据时后,不仅仅是文件数据在磁盘的写入,与文件相关的i-node也要写入磁盘,i-node和文件所在磁盘位置相差可能很远。

仅仅只保证数据序列化写入还不够,比如在T时刻在地址A写入一个数据,准备在T+δ时刻往地址A+1写入另一个数据,但是在时间T和T + δ之间磁盘旋转了,假设磁盘旋转了Trotation时间,那么第二次写入实际上要等待Trotation?δ时间才能真正实施。所以为了保证高性能的写入,除了序列化写入外,还要保证连续性写入

而LFS就通过把数据更新缓存到内存中,然后一起写入到磁盘中,将文件数据和i-node放在磁盘相邻的位置,减少磁盘seek
time.

LFS在某一时刻写入的更新单元称为segment.当要往磁盘写入时,LFS把所有的更新缓存到内存中的segment,然后在某一时刻把segment的所有数据一次写入磁盘。只要segment设置的足够大,就能够取得很好的性能。

那么要取多大的缓存呢?可以参看下面原文中的介绍,非常简单。

下面我们来关注第一个重要的问题,在LFS中如何找到i-node?

为什么要关心这个问题呢,因为在传统的文件系统比如UNIX系统中,i-node存在在一个数据中,保存在磁盘中固定的位置。因此只要给定inode的序号以及i-node所在磁盘的地址,就可以通过i-node序号乘以i-node结构的长度,然后再加上磁盘地址就可以得到所需i-node的精确地址。但是在LFS系统中,i-node是分布在磁盘中的,并且由于在LFS系统中并不覆写数据,所以一个文件的最新版本的i-node在磁盘中的位置是不断变化的。

inode
map (imap)
. The imap is a structure that takes an inode number as input and produces the disk address of the most recent version of the inode. Thus, you can imagine it would often be implemented as a simple array,
with 4 bytes (a disk pointer) per entry. Any time an inode is written to disk, the imap is updated with its new location.

LFS通过引入imap来解决i-node查找问题。imap是这样的一个结构,输入一个inode number,生成最新版本的inode所在磁盘地址。基于此,imap可以实现为一个数组,每一项是4字节作为磁盘指针,当一个inode写入磁盘后,imap就更新相应的inode地址。

LFS需要imap能够持久的保存,这样在系统崩溃的时候就能够找到inode的位置。

如果把imap保存在磁盘固定的位置上的话,每次更新的时候都要访问这个磁盘,就会增加磁盘读写时间,降低了系统性能,所以在LFS中,把更新相关的imap存放在更新数据所写入磁盘位置的右边。

那么现在问题来了,既然imap分散保存在磁盘的各个位置上,那么使用时该如何找到这些imap呢?系统中必须在一个固定磁盘的位置存储这些imap的信息。在LFS中这个固定保存Imap地址信息的块成为CR.

在CR中保存指向最新版本的imap的指针,系统就可以通过读取CR查找获取想要的imap信息。CR中的信息周期性的进行更新,可能是30秒一次,所以对系统的性能影响不大。

所以LFS最终在磁盘上的整体结构包含一个CR,imap(将inode number映射为Inode的地址),以及指向文件的inode.

LFS系统如何保存目录数据呢?

和UNIX系统类似,一个目录就是(name,inode number)的结构体的集合。举例来说,当在磁盘上创建一个文件,LFS必须写入一个新的inode,新的数据,以及指向这个文件的目录数据和目录inode(目录数据和Inode是被更新了,不过在LFS不会覆写数据,所以这些数据都要在磁盘新的位置中写入)。

LFS还解决了另外一个问题 递归更新问题。

举例来说,当一个文件的inode被更新后,它在磁盘上的位置改变了,如果我们不仔细处理这种情况的话,指向这个文件的目录的也会更新,这个目录的目录也会更新,沿着文件系统树向上更新。LFS很漂亮的避免了这个问题。即使一个inode的磁盘位置改变,这个改变不会反映到他的目录中,因为更新的只是inode的imap,目录仍然保存一样的(name,inode number)映射。通过非直接的方法,LFS避免了递归更新问题。

新的问题来了,既然LFS不覆写数据,只是在新的磁盘位置写入数据,磁盘总有写满的时候,同时在磁盘中有大量的老版本的数据,LFS怎么解决这个问题?

如原文中所示,假设有个Inode number为k的inode指向磁盘块D0,我们现在更新了文件数据,那么在磁盘中生成一个新的inode和数据磁盘块。结构磁盘中就会出现这样一种情况,inode,数据磁盘块有两个版本,一个老版本,一个新版本。

如原文中另外一个事例,如果在一个文件中添加数据,在磁盘中为原始文件增加了一个新的磁盘块用于保存添加的数据,我们可以看到,磁盘中增加了一个新的inode,但是原有的数据块除了被新的inode指向外,还依然被老版本的inode指向。

对于这些老版本的inode,数据块等应该怎么处理?一个方法是保存这些老版本的数据然后允许用户恢复到老版本(比如当如用误删除或覆写了一个文件,用这种方法就会非常方便的恢复)。这样的文件系统称为versioning file system.

在LFS中只保存最新的版本和之前的老版本,LFS周期性的扫描磁盘检测老的版本数据然后清除掉,为后续数据的腾出磁盘空间。

LFS怎么清楚这些老版本数据呢?如果仅仅只是检查时把老版本的inode ,data,imap等占用空间释放掉,那么在磁盘中就会产生许多的hole,磁盘的写入性能会收到极大的影响,因为到后来可能找不到合适大小的磁盘空间来放置新的数据,虽然有许多的空磁盘,但是这些空间都太小。

LFS最终还是基于segment进行清理操作。基本的清理过程如下:LFS首先读入一些老版本的segment,然后判断在segment中那些磁盘块中的数据是Live的,在把这些live的数据写入到一个新的segment集合中,释放原有segment占用的磁盘空间。我们期望能够读取M个存在的segment,把他们的live内容压缩到N个新的segment中,然后释放掉老的M个segment占用的磁盘空间,用于后续的写入。

接下来新的问题来了,如何判定segment中哪些磁盘是live的?

Specifically, LFS includes, for each data blockD, its inode number (which file it belongs
to) and its offset (which block of the file this is). This information is recorded in a structure at the head of the segment known as thesegment summary block.

在LFS中为每一个磁盘块D记录了新的信息,包含inode number(这个磁盘块属于哪个文件)和offset(属于文件第几个磁盘块).这个信息保存在segment的的头部的一个结构中,称为segment summary block。

Given
this information, it is straightforward to determine whether a block is live or dead. For a blockD
located on disk at addressA, look in the segment summary block and find its inode numberN
and offset T. Next, look in the imap to find whereN
lives and readN
from disk (perhaps it is already in memory, which is even better). Finally, using the offsetT, look in the inode (or some indirect block)
to see where the inode thinks the Tth block of this file is on disk. If it points exactly to disk addressA, LFS can conclude that the blockD
is live. If it points anywhere else, LFS can conclude thatD
is not in use (i.e., it is dead) and thus know that this version is no longer needed.

有了这个信息,就可以很直接的判定一个磁盘块是live 或 dead。假设有一个磁盘块D位于地址A,通过查看segment summary block可以找到这个磁盘块属于的inode number N和offset T.接下来,通过查看imap可以找到N对应的inode的地址,根据inode信息找到文件所占用的磁盘块,查看这个文件的第T个磁盘块所在地址,比较通过inode查找得到的地址和segment
summary block中记录的地址,如果两个不一样,那么该磁盘块D就是old 版本,不再被使用。

There are some shortcuts
LFS takes to make the process of determining liveness more efficient. For example, when a file is truncated or deleted, LFS increases itsversion number
and records the new version number in the imap. By also recording the version number in the on-disk segment, LFS can short circuit the longer check described above simply by comparing the on-disk version
number with a version number in the imap, thus avoiding extra reads.

除此之外,还有一些更简单的判断磁盘live的方法。比如,当一个文件增加数据或者被删除了,LFS增加这个文件的版本号,然后记录在Imap中,同时也记录在磁盘的segment中。LFS可以通过比较磁盘块的version number和imap中的version number来判定这个磁盘块是否live.

LFS如何处理数据写入时系统崩溃的情况。

Let’s cover the second
case first. To ensure that the CR update happens atomically, LFS actually keeps two CRs, one at either end of the disk, and writes to them alternately. LFS also implements a careful protocol when updating the CR with the latest pointers to the inode map and
other information; specifically, it first writes out a header (with timestamp), then the body of the CR, and then finally one last block (also with a timestamp). If the system crashes during a CR update, LFS can detect this by seeing an inconsistent pair of
timestamps. LFS will always choose to use the most recent CR that has consistent timestamps, and thus consistent update of the CR is achieved.

为了确保CR数据写入的原子性,LFS其实保存了两个CR,保存在磁盘的两端,CR更新到磁盘中时是随机挑选一个CR写入。LFS同样实现了一个非常小心的协议来更新CR。首先写入一个header(附带写入一个timestamp),然后写入CR的主要内容,然后写入最后一个磁盘块数据以及一个timestamp。如果在CR更新时系统奔溃了,LFS通过观察到一对不一致的timestamp检测到出现了系统崩溃,LFS就会采用含有一致性timestam的离崩溃时间最接近CR。

原文CSDN下载地址

时间: 2024-08-26 00:39:53

LFS(the Log-structured File System)系统详解的相关文章

java中的io系统详解

java中的io系统详解 分类: JAVA开发应用 笔记(读书.心得)2009-03-04 11:26 46118人阅读 评论(37) 收藏 举报 javaiostreamconstructorstringbyte 相关读书笔记.心得文章列表 Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组. Java 内用 Unicode 编码存储字符,字符流处理类负责将外部的其他

解决出现"Bringing up interface eth0: ~~ 'System eth0'“详解

问题:用ifconfig查看只有一个回环口,用ifconfig -a查看有eth1和lo,如下图: 配置文件中有eth0存在 此时重启服务FAILED 解决方法: #mv /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth1 将网卡eth0的名称改为eth1 修改配置文件如下: #vi /etc/udev/rules.d/70-persistent-net.rules 将硬件地址和n

Android的file文件操作详解

Android的file文件操作详解 android的文件操作要有权限: 判断SD卡是否插入 Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED); 获得sd卡根目录 File skRoot = Environment.getExternalStorageDirectory(); 获得私有根目录 File fileRoot = Context.getFilesDir()+""

linux系统/var/log目录下的信息详解

一./var目录 /var 所有服务的登录的文件或错误信息文件(LOG FILES)都在/var/log下,此外,一些数据库如MySQL则在/var/lib下,还有,用户未读的邮件的默认存放地点为/var/spool/mail 二.:/var/log/ 系统的引导日志:/var/log/boot.log例如:Feb 26 10:40:48 sendmial : sendmail startup succeeded就是邮件服务启动成功! 系统日志一般都存在/var/log下常用的系统日志如下:核心

Tomcat日志系统详解

综合:Tomcat下相关的日志文件 catalina引擎的日志文件,文件名:catalina.日期.log Tomcat下内部代码丢出的日志,文件名localhost.日期.log(jsp页面内部错误的异常,org.apache.jasper.runtime.HttpJspBase.service类丢出的,日志信息就在该文件!) Tomcat下默认manager应用日志,文件名manager.日期.log 控制台输出的日志,Linux下默认重定向到catalina.out Access日志(Se

《Tomcat日志系统详解》

综合:Tomcat下相关的日志文件 Cataline引擎的日志文件,文件名catalina.日期.log Tomcat下内部代码丢出的日志,文件名localhost.日期.log(jsp页面内部错误的异常,org.apache.jasper.runtime.HttpJspBase.service类丢出的,日志信息就在该文件!) Tomcat下默认manager应用日志,文件名manager.日期.log 控制台输出的日志,Linux下默认重定向到catalina.out Access日志(Ser

Linux下日志系统详解

Linux下日志系统详 1.linux系统上有两个日志服务syslog和syslog-ng syslog服务有两个进程syslogd和klogd syslogd: 系统产生的日志信息 klogd:内核产生的日志信息 klogd:在系统启动时内核产生日志输出至物理终端(/dev/console)并存放至/var/log/dmesg文件中 查看klogd产生的日志信息可通过 dmesg 和 cat /var/log/dmesg 命令查看 syslogd:在系统启动后,由各子系统产生日志并存放至 /v

[日志log] 常用log日志记录方式对比和详解

1.现在都有哪些记录日志的方法 A.java.util.logging.Logger - 使用详解 B.log4j - 使用详解 C.SLF4J-使用详解 2.比较log4j和slf4j的异同 http://blog.csdn.net/tanga842428/article/details/52924883 http://www.importnew.com/7450.html

Linux syslog日志系统详解

一. syslog简介 syslog是一种工业标准的协议,可用来记录设备的日志.在UNIX系统,路由器.交换机等网络设备中,系统日志(System Log)记录系统中任何时间发生的大小事件.管理者可以通过查看系统记录,随时掌握系统状况.UNIX的系统日志是通过syslogd这个进程记录系统有关事件记录,也可以记录应用程序运作事件.通过适当的配置,我们还可以实现运行syslog协议的机器间通信,通过分析这些网络行为日志,藉以追踪掌握与设备和网络有关的状况. 功能:记录至系统记录. 二 . sysl