一则胡乱科普
我爸打电话来,声称菜鸟驿站的工作机制可以改进。
驿站现在会将快递员运来的一车包裹顺序地摆放在货架上。我爸则认为:驿站完全可以把同一个人的包裹摆放在一起,从而优化取件体验。
我不是学物流的,是学计算机的。而这个问题恰恰与文件系统碎片化问题很接近,于是我写了这一篇科普。
文件系统碎片化问题(File System Fragmentation) 是指单个文件被分成几个区段存储的现象。这使得我们读取整个文件时,磁盘针头必须不停地移动,造成严重的效率问题。这不是与同一个人的包裹被分成几个地方摆放的现象很相似吗?
造成这个问题的原因很简单。设想这样一个场景:假设你正在做大作业,要完成 PA.h
与 PA.cpp
两个文件。你不时地修改两个文件,插入一些文本。若文件系统简单地、线性地存储所有你写入的内容,这两个文件自然就都被碎片化地存储了成了形如:###@@@##@############@@@##@###@@@@@
的样子。
当然,文本编辑相关的问题是容易解决的。但若考虑从网络上下载大文件等场景呢?实际上,在 FAT 与 NTFS 一类的文件系统上,这样的碎片化问题是相当严重、影响巨大的。
但 ext4 下则几乎不存在碎片化问题。Linux 用户可以试着用 e4defrag
命令检查自己的硬盘中有多少个文件被碎片化了。一位网友在 Linux ext4 下只有两个文件被碎片化了,而在 Windows NTFS 下,这个数字是 95%。
这主要依靠 ext4 的几个伟大机制:
-
预分配(Preallocation)
应用程序可以预先向文件系统申请一块空间,之后再慢慢完成写入工作。这可以当然可以保证数据存储的连续性,尤其是对于一些 P2P 应用程序而言。
而在 NTFS 下,因为预分配机制没有较好的实现,一些程序(比如百度网盘)在运行时会产生海量的磁盘碎片。一种替代方案是在磁盘上预先写0占用空间,不过那当然需要相当大的开销。
-
区块预留(Block reservation)
最后一次分配区块的后继区块将被预留下来,作为未来文件增改而避免碎片化的备用。
在 NTFS 下,如果顺序地新建一系列文件,它们也会被连续地存储在磁盘中。而后续增加其中文件的内容则会导致碎片化问题。
-
延迟分配(Delayed Allocation)
文件系统会将用户试图写入硬盘的数据暂存,仅当写入磁盘可以保证区块数据连续性时才真正写入对应位置。
尽管许多现代文件系统都采用了这一机制,在 NTFS 下,文件写入磁盘仍几乎是实时的。
这几个机制带来的改善非常大。根据 Ubuntu 的说法,除非硬盘剩余空间不足 5%,ext4 是几乎不可能产生磁盘碎片。
计算机环节告一段落,我们回到菜鸟驿站的问题,容易构造这样的映射:
包裹 -> 数据;文件 -> 收件人;货架 -> 磁盘;快递车 -> 写入;驿站 -> 文件系统
这样一番对号入座之后,我们能否将 ext4 的几个机制照搬过来呢?
实际上仍然很困难,物理世界不是计算机。首要的问题是货柜空间相对包裹而言并不那么充裕,而整个磁盘相对单个文件而言非常庞大。此外,更有商业上、隐私上的考量:文件系统自然可以轻松地处理多用户操作,那么驿站能够打通各家快递公司的数据库吗?
参考阅读:
Link: https://superuser.com/questions/536788
Link: https://ext4.wiki.kernel.org/index.php/Ext4_Howto
Link: https://www.landley.net/kdocs/ols/2007/ols2007v2-pages-179-186.pdf