EAimTY的博客
一个没什么技术的开源爱好者,一个苦逼的学生狗。
首页
关于
主题
ZFS──瑞士军刀般的文件系统
Feb 15, 2020

你是否曾遇到过如下情况:

  • 应该给这个分区分配多少空间?另一个呢?
  • 我正在覆写一个文件,突然间设备断电了!我的源文件和更改全都损坏了!
  • 我买不起硬RAID卡,mdadm用起来又太麻烦……
  • 我不想用RAID,但是想把两块硬盘上的空间分配至一个分区中,有没有除了用LVM外的其它办法?
  • LUKS用起来好麻烦,每加载一个分区都要输入一次密钥……
  • 每次备份系统都要把整个系统打包,太浪费空间了!
  • 我的硬盘太太太大了!
  • 我的某个文件太太太大了!

那么为何不试试这个瑞士军刀般的文件系统──ZFS?


玩过NAS的朋友们应该对ZFS不陌生,FreeNAS之类的很多存储服务器系统都原生支持ZFS文件系统,配置简单而优点众多。

ZFS有非常多优点,然而为什么在PC上使用ZFS却不多见呢?我很早之前就听说过ZFS的各种优点,于是在写这篇文章前一个月,我把自己的主力PC的整个文件系统(包括根分区)迁移至ZFS。经过一个月的使用体验,我发现:

ZFS真香!

注:
①这是一篇介绍与安利ZFS的文章,不会深入分析其架构与实现。同时本文也不是使用教程,如果你想尝试在Linux下ZFS,请移步ZFS on Linux Wiki与各大发行版的Wiki;
②我的所有体验都是在Linux(Debian sid)下完成的,也就是说下面内容基于ZFS on Linux项目,Solaris系、BSD系对ZFS的支持应该会更好。另外,我使用的Kernel版本是5.4,太低的内核版本可能会影响使用体验。


ZFS的前生今世

The Birth of ZFS by Jeff Bonwick
https://youtu.be/dcV2PaMTAJ4

Story Time (Q&A) with Matt and Jeff
https://youtu.be/yNKZQBsTX08

ZFS First Mount by Mark Shellenbaum
https://youtu.be/xMH5rCL8S2k

ZFS past & future by Mark Maybee
https://youtu.be/c1ek1tFjhH8

ZFS的开发并非是一帆风顺的。

诞生

ZFS与Solaris是密不可分的。
让我们回到20年前。当时,Sun公司如日中天,1992年发布的Solaris、1995年发布Java都是其辉煌的证明。1993年,Sun进入了财富500强。

在公司业绩蒸蒸日上的环境下,ZFS诞生了。

2001年,Solaris已诞生了整整10年,Sun希望改进Unix文件系统(Unix File System)以解决一些问题。Sun内部的Jeff Bonwick就是在此时有了对ZFS架构的基本构思。他说服了Sun高管,组建了ZFS的开发团队。

2004年9月14日,Sun正式宣布了ZFS文件系统。2005年6月14日,Sun公司将正在开发中的Solaris 11的源代码以CDDL许可开放,这一开放版本就是OpenSolaris。2005年10月31日,ZFS并入了Solaris开发的主干源代码,并在2005年11月16日作为OpenSolaris build 27的一部分发布。

波折

好景不长,2009年4月20日,甲骨文公司宣布以74亿美金收购Sun公司。此时的Sun已如夕阳。由于甲骨文公司对OpenSolaris计划没有积极支援的意图。OpenSolaris委员会于2010年7月12日对甲骨文给出“最后通牒”,要求在8月16日派出一位代理人商讨计划的走向,否则将在8月23日的委员会会议中做出回应。由于甲骨文未加回应,委员会于该日达成共识,解散OpenSolaris委员会,社区将不再提供新的源码,计划的控制权由开发员社区交还给甲骨文。

至此,Sun的ZFS已成为Oracle的专有软件,ZFS成为Oracle的注册商标,而OpenSolaris,包括其中的ZFS,由illumos项目继续着开发。

壮大

但ZFS并没有至此没落。社区在2013年成立了OpenZFS以配合ZFS在illumos中的开源发展,由Jeff Bonwick当年组建的ZFS开发团队中的Matt Ahrens作为OpenZFS项目的负责人。在开源社区的努力下,ZFS不断增加新特性、提升稳定性。

回到2007年,苹果将ZFS移植到了Mac OS X上,但该项目在2009年被关闭,之后MacZFS项目继续维护着代码;2008年,ZFS随FreeBSD 7.0正式进入了FreeBSD;同年,ZFS开始被原生移植至Linux,后来成为了OpenZFS下属的ZFS on Linux项目。如今,几乎所有主流操作系统都支持了ZFS,甚至有OpenZFS on Windows项目为Windows提供ZFS移植!

我们今天所说的ZFS在绝大多数情况下指的都是OpenZFS。


什么是ZFS

ZFS这个名字本身没有含义,只是"Zettabyte File System"的首字母缩写。但ZFS本身并不具备任何的缩写意涵,只是想阐述做为一个具备高扩展容量文件系统且还有支持许多延伸功能的一个产品。
它是一个128位的文件系统,也就是说它能存储1800亿亿(18.4×10^18)倍于当前64位文件系统的数据。ZFS的设计如此超前以至于这个极限就当前现实可能永远无法遇到。

Jeff Bonwick曾说过:

要填满一个128位的文件系统,将耗尽地球上所有存储设备。除非你拥有煮沸整个海洋的能量,不然你不可能将其填满。

并解释填满ZFS与煮沸海洋的关系:

尽管我们都希望摩尔定律永远延续,但是量子力学给定了任何物理设备上计算速率与信息量的理论极限。举例而言,一个质量为1公斤,体积为1升的物体,每秒至多在10^31位信息 上进行10^51次运算。一个完全的128位存储池将包含2^128个块=2^137字节=2^140位;因此,保存这些数据位至少需要(2^140位) / (10^31位/公斤) = 1360亿公斤的物质。

但单纯的“大”并不能成为ZFS的代替其它文件系统的原因,因为如今有很多文件系统(如XFS)也可做到这点,虽然不及ZFS,但数据存储量也暂时不会成为其瓶颈。

ZFS的优点远不止“大”,下面来讲ZFS的众多优秀特性。


ZFS的特性

虚拟设备(VDEV)、存储池(zpool)、数据集(dataset)、虚拟卷(zvol)

这些是ZFS的实现核心,是ZFS易用性的基础,ZFS的绝大多数优点是在其上实现的。

我们在使用传统文件系统时,“分区”与“分区表”是相互独立的,基于不同的技术实现。ZFS则不同,可以认为它同时承担了分区与分区表的角色。

虚拟设备(VDEV)

VDEV类似于Linux中的Device Mapper层,可以认为是ZFS架构中的最底层,它用来定义使用设备的类型。
为何叫做虚拟设备?因为一个VDEV并不需要是一个特定的独立设备(例如一块硬盘),它可以是一块硬盘、一个RAID阵列、RAID-Z(ZFS实现的RAID方式,下文会详细介绍)、甚至是一个文件。

ZFS支持以下VDEV类型:

  • 文件(File)
  • 一块磁盘或一个RAID0阵列(Stripe)
  • 标准RAID1阵列(Mirror)
  • RAID-Z(包括RAID-Z1、RAID-Z2、RAID-Z3)
  • 热备盘(Spare)
  • L2ARC(Cache,用ARC算法实现的二级缓存,保存于高速存储设备上,通常使用SSD)
  • ZIL(Log,记录两次transaction group之间发生的fsync,保证突发断电时的一致性)

存储池(zpool)

存储池建立于VDEV之上,可以认为与传统文件系统中的“分区表”对应。它拥有类似于LVM的功能,能管理一个或多个VDEV。类似于内存,存储池大小会是所有设备的大小总和。这意味着在一个存储池中,可以同时包含一块硬盘、一个RAID1阵列和RAID0阵列等不同部分!
LVM不能作为最终文件系统,建立的LV需要格式化为最终文件系统(如ext4、fat32、NTFS、F2FS等)后才能使用。不同于LVM,建立好的ZFS存储池不需要任何操作即可直接使用。

数据集(dataset)、虚拟块(zvol)

将数据集与虚拟块放在一起介绍是因为它们是“平级”的,都建立于存储池之上,可以认为与传统文件系统中的“分区”对应。

虽然存储池可以直接使用,但是有时我们需要实现一些特殊的需求,例如:你将ZFS作为根系统挂载,在快照系统时不想将/tmp下的文件和目录加入快照,怎么办?这时你可以定义一个“tmp”数据集,并设置其属性为com.sun:auto-snapshot=false
细心的朋友可能会发现,即使在没有创建“tmp”数据集时,/tmp仍然是存在的,因为在ZFS中,可以认为数据集是为设置权限,限额,快照,挂载点等高级特性才存在的。
在没有定义数据集大小的情况下,ZFS会自动为其分配存储池中的空间。ZFS也允许子数据集的存在,在没有特别设定的情况下子数据集将继承父数据集的属性。

虚拟块是ZFS提供的块设备方式,类似于数据集,虚拟块为block设备,可以被格式化,可以被iSCSI分享。举个例子,你想在一块被分入存储池的空间上划分出一个F2FS文件系统格式的“分区”,你需要使用的就是虚拟块。

由此可见,在ZFS下,操作一个“分区”就像是操作一个目录一样简单,并且“分区”是动态大小的!

写时复制(copy-on-write,CoW)

在绝大多数文件系统下,当我们覆写一个文件时,已覆写的部分会完全丢失,在覆写的中途想要取消是不可能的。
ZFS不同,当你执行覆盖文件操作时,新数据会先存储在不同的区域,在写入完成后再将文件系统元数据信息指向新写入的区域。
这能极大地提升系统的稳定性与安全性。突然断电时,正在操作的文件也不会损坏。所以如果使用了ZFS,就可以完全抛弃fsck了。

当然,这么做有一个显著的缺点:文件会散落在磁盘的各个区域,也就是我们常说的“磁盘碎片”。
但是,随着SSD的普及,磁盘碎片已经变得无伤大雅,而传统的机械硬盘也更多地成为了“长期存储设备”,例如用于NAS,其上数据不会非常频繁地进行覆写操作。

数据完整性验证、自动修复

写入的数据时,ZFS会创建数据的校验和,校验和是数据的256位散列,校验和功能的范围可以从简单快速的fletcher4(默认)到强加密散列(如SHA256)。
读取数据时,ZFS会检查读到数据的校验和,如果与写入时的检验和不符,那么就说明遇到了错误,ZFS会尝试自动修正错误。这能在很大程度上保证资料完整性。

RAID-Z

上文在介绍VDEV时提到了RAID-Z,这是ZFS实现的RAID方式,不需要任何其它硬件或软件。
现时RAID-Z有3种类型:RAID-Z1、RAID-Z2、RAID-Z3。

  • RAID-Z1,类似于RAID5,一重奇偶校验,至少需要三块硬盘;
  • RAID-Z2,类似于RAID6,双重奇偶校验,至少需要四块硬盘;
  • RAID-Z3,三重奇偶校验,ZFS独有,至少需要五块硬盘。

快照(Snapshot)

这时ZFS在文件系统层级实现的备份功能。
当ZFS写入新数据时,可以保留包含旧数据的块,因而能够维护文件系统的快照版本。而因为组合快照的所有数据都会被储存,且整个存储池通常每小时会进行几次快照,所以快照的创建速度非常快。任何未变动的数据会在文件系统及其快照之间进行共享,因此也具备空间高效性。快照本质上是只读的,确保在创建后快照不会被修改。快照可以被整个恢复,也可以恢复快照中的某些文件或目录。

ZFS也可以创建可写快照:“克隆(Clone)”。“克隆”让两个独立的文件系统共享一组块。对克隆文件系统的修改都会创建新的数据块以反映这些更改。但是无论存在多少个克隆,未变动的块仍然会被共享。这是写入时复制原则的实施方式。

去重(Deduplication)

ZFS提供文件级别(file-level)、块级别(block-level)、字节级别(byte-level)的去重。
文件级别去重通过比对校验和来发现重复,是一般使用的级别,对性能影响最小。
其它两个级别的去重可以用于某些特殊场合,能节省更多的存储空间。

透明压缩(Compression)

ZFS原生提供透明压缩功能,也就是在读写文件时实时进行压缩与解压缩。ZFS会尝试压缩文件的头部,如果压缩率不佳,会自动放弃压缩将原数据写入。
压缩可以在一定程度上“提高IO”,但代价是占用CPU性能,要在考虑IO性能与CPU性能后再选择是否开启。
ZFS支持以下压缩算法:

  • lz4,默认且推荐的压缩算法,对系统性能影响小,存取数据的速度几乎与不采用压缩时一样;
  • gzip,这个不用解释,ZFS默认的gzip级别是6。对性能有一定的要求,但如果存储的数据是存档,可以考虑使用gzip;
  • lzjb,与lz4类似,但更推荐lz4;
  • zle,简单来说就是“去0”。

一般来说,不推荐同时开启ZFS的压缩与块级别以上的去重。

透明加密(ZFS Native Encryption)

这是ZFS支持的最新特性,能够加密存储池或数据集。
默认下,ZFS使用aes-128-ccm作为加密算法,目前为止是绝对安全的,如果不放心,还可以选择更高级别的加密。
传统的LUKS需要为每一个加密分区提供密钥,而ZFS可以对存储池加密。
当然,开启加密必定会影响性能,要在考虑性能后再选择是否开启。


综上,不难发现ZFS不只是一个单纯的文件系统,它还提供了一系列工具来提高使用体验。

但是,拥有如此多的优点,

为什么ZFS没有在更大程度上流行?

回到2005年,最初的ZFS随着OpenSolaris的开源而进入了开源世界,但同时也因许可证问题与Linux“天生不合”。
OpenSolaris开源时采用通用开发与散布许可证(CDDL),从而ZFS也成为了CDDL协议下的开源软件。
Oracle收购Sun,终止OpenSolaris开发,让我们口中的ZFS变成了OpenZFS,OpenZFS项目因无法联系到所有ZFS的初期开发者而无法变更许可证。CDDL协议与GPL协议不兼容,所以很多Linuxer无法接触到ZFS,从而导致了ZFS无法在更大程度上流行。

但最近ZFS也在慢慢融入Linux家庭中,上文中提到的ZFS on Linux项目对此作出了巨大的贡献。
2019年,Canonical在Ubuntu19.10中默认加入了ZFS的支持。这是ZFS融入Linux的历史性的一步!虽然有着许可证问题,但是更多人能逐渐理解并包容这一历史遗留问题。Canonical目前为止还没有因ZFS的引入而被缠入法律纠纷。有了第一个“吃西红柿的人”,相信之后会有更多的发行版拥抱ZFS。

今天,ext在某些方面的缺点已经成为瓶颈,BtrFS因开发缓慢且不够稳定而暂时无法成为生产环境下的文件系统,ZFS应是最佳文件系统的候选之一。

多年以后,当BtrFS成为主流时,也请不要忘记ZFS,不要忘记这个优秀的开源社区,不要忘记这个伟大的文件系统探路者。


本文参考了:

如果你在文章中发现任何纰漏,请在评论中告诉我,谢谢!

respond-post-223
Feb 16, 2020, 09:36

说的好,zfs的许可证确实是个问题🤔🤔🤔,所以我选择ntfs😂😂🧐

Feb 16, 2020, 12:42

土豆你分明是个Apple Boy,怎么能叛变呢?🤣

Feb 16, 2020, 12:50

哦哦哦,对,我是Apple Girl,那么,APFS大法好!

添加新评论

请填写称呼
请填写合法的E-mail地址
请填写合法的网站地址
请填写内容