其他资讯
🌍unRAID ZFS 入门(一):ZFS 介绍
00 分钟
2023-3-28
2023-8-27
type
status
date
slug
summary
tags
category
icon
password
2023年6月14日,unRAID 官方宣布 6.12 正式版发布,从此开始 unRAID 原生支持 ZFS 这一优秀的文件系统。其实很多用户在多年前就已经呼吁 unRAID 官方把 ZFS 带入到系统中,那么多年后这一目标实现了,对于还不了解什么是 ZFS 的用户来说,本文章将带大家介绍什么是 ZFS 文件系统以及相关的一些基本概念。
notion image

1、什么是 ZFS?

ZFS 全称叫做 Zetta File System,是一种具有先进功能的文件系统卷管理器( volume manager )。
Zetta 指的是国际单位词头(英语:metric prefix),表示单位的倍数和分数,目前有24个词头,大多数是千的整数次幂,就跟十(deaca)、百(hecto)、千(kilo)、百万(mega)一样。Zetta 表示10的21次方 —— ,表示 ZFS 这个文件系统最多能够支持bytes 的数据量。
notion image

1.1、三个主要设计目标

(1)数据完整性

ZFS 文件系统中的所有数据都包括数据的校验和。ZFS 当写入数据时会计算校验和并将其与数据一起写入。当以后读取该数据时,ZFS重新计算校验和。如果校验和不匹配,意味着检测到一个或多个数据错误,ZFS将尝试自动纠正错误,从而防止数据损坏和数据丢失的问题。

(2)池化存储(ZPool)

ZFS 将物理存储设备添加到一个池中,并从该共享池中分配存储空间。空间对所有文件系统和卷(Volume)都是可用的,并通过向池中添加新的存储设备而增加。

(3)性能

缓存机制提供了更高的性能。ARC 是一个先进的基于内存的读取缓存。ZFS 用 L2ARC 提供了一个基于磁盘的第二级读缓存,以及一个名为 ZIL 的基于磁盘的同步写缓存。

1.2、优秀的特性

(1)快照(Snapshot)

如果你使用过 PVE 或者 Esxi 等虚拟化平台,那么你对快照应该不会陌生。快照被用来追踪文件系统的变更,每一个快照代表不同版本下的文件系统,也就是你的数据在不同时间下的状态,这意味着你可以轻松地将数据回滚到以前的版本。
快照并不是 ZFS 独有的特性,BTRFS 文件系统也可以实现这一效果。

(2)写时复制(Copy-on-write,CoW)

当你对一个数据进行修改时,ZFS 不会直接在原有数据上进行改动,而是会复制一份数据到新的存储位置上进行修改。当写入结束后,元数据会更新并指向新的数据存储位置,并且只有在必要的时候才会将修改后的数据写回到原有数据上。这么做的好处在于,假设写入新数据后出现了系统崩溃,那么原有的数据也不会丢失,因为我们没有直接对原始数据进行修改,而是在新的位置写入了数据。

(3)透明压缩(Compression)

ZFS 支持透明压缩。也就是说, (如果启用的话) ZFS 会自动压缩所有你放进去的文件。这不仅仅可以节省空间,甚至在慢速的硬盘上甚至可以提高性能 (因为压缩速度比写入速度快得多)。 —— 《ZFS 入门指北: 基础篇》
有一个反直觉的事实,那就是在 ZFS 中,压缩不仅能够节省存储空间,还能提读写高性能。那是因为压缩和解压缩一个数据所需要的时间,要比对一个未压缩的数据进行读写的时间要来的短。 —— "This may sound counter-intuitive, but turning on ZFS compression not only saves space, but also improves performance. This is because the time it takes to compress and decompress the data is quicker than then time it takes to read and write the uncompressed data to disk (at least on newer laptops with multi-core chips)." -Oracle

2、什么是 ZPOOL?

在 ZFS 的存储结构中,zpool 位于这个结构的最顶端。
notion image
ZFS 存储结构
ZFS 存储结构
zpool 是 ZFS 文件系统的一个重要特性之一,它主要用于管理存储设备和提供更好的数据容错性和存储空间。zpool 可以将多个物理磁盘或分区组合成一个逻辑卷,从而形成一个存储池。
从上面的图片中可以知道,zpool 是由 vdev 组成的,一个 zpool 中可以存在多个 vdev,多个 vdev 共同组成一个 zpool
zpool 支持多种 RAID 级别,包括镜像(mirror)、RAID-Z1、RAID-Z2、RAID-Z3 等,从而进一步增强数据的容错性和可靠性。

3、什么是 vdev ?

vdev 指的是 Virtual Devices(虚拟设备) ,vdev 由真实的物理存储设备组成。因为 ZFS 文件系统整合了文件系统和卷管理器( volume manager )的功能,所以写入 zpool 的数据将被分散到各个 vdev 上,有点类似于 Raid0。
ZFS 入门指北:规划与创建存储池》 虽然 zpool 和 Raid0 看上去的确很相似,ZFS 并不会简单地将要写的数据平均写到各个盘。实际上,ZFS 有一套很复杂的分配及调度机制来决定何时写数据,以及数据将写到何处。
大多数 vdev 用于普通存储,但也存在几种特殊的支持性 vdev 类型,如 CACHELOGSPECIAL ,这些特殊的 vdev 类型不在本文的讨论范围内。
《ZFS 101—Understanding ZFS storage and performance》: It is a common misconception that ZFS "stripes" writes across the pool—but this is inaccurate. A zpool is not a funny-looking RAID0—it's a funny-looking JBOD, with a complex distribution mechanism subject to change.
一个 vdev 可以包含一个或多个硬盘,vdev 可以由一个硬盘组成,也可以是多个硬盘组成的阵列,如 mirrorRAID-Z1RAID-Z2RAID-Z3 等。
ZFS 入门指北:规划与创建存储池》 与传统的硬件 RAID 卡相比,RAIDZ 是基于数据块的 (而不是基于整块磁盘),因此更加灵活和高效。在硬盘失效发生时,传统 RAID 5 阵列必须将硬盘阵列下线以进行耗时的重构,而 ZFS 的自愈功能会自动从 RAIDZ 中的冗余盘中计算出数据并提供给应用程序 (当然, 有性能降级)。 而且,当 RAID 5 阵列重构失败时,你只能将剩下的拷出来,然后重新构建阵列。而在 RAIDZ 中,ZFS 可以自动重建所有正常的块,并通知管理员哪些块无法重建。
RAID-ZX 中的 X 代表奇偶校验盘的个数,比如说 RAID-Z1 就表示有一块奇偶校验盘,RAID-Z2 表示有2块奇偶校验盘。
RAIDZ 阵列可以失去与其拥有的奇偶校验盘相同的磁盘,比如说如果一个 RAID-Z1 阵列坏了一块硬盘,那么可以保持 zpool 还可以正常运行,数据不会丢失; RAID-Z2 则可以允许坏两块硬盘。但如果说损坏的硬盘数超出 RAIDZ 阵列的奇偶校验个数,则会导致直接数据丢失,zpool 会立即崩溃。
需要说明的是,很多新手误以为冗余相当于数据备份,这是一个错误的认知。冗余是一种安全措施,是为了在遇到数据安全事故时(比如说硬盘损坏)还能保证数据的完整性不至于系统崩溃,从而让你能够采取必要的措施去将数据进行转移或备份等,从而增加系统的抗风险能力。所以如果你不幸遇到了这种事故,你要做的就是赶紧将损坏的硬盘进行一个替换让数据重建,又或者将重要的数据进行一个转移备份等。
ZFS 分层架构设计》: VDEV 在 ZFS 中的作用相当于 Linux 内核的 Device Mapper 层或者 FreeBSD GEOM 层,提供 Stripe/Mirror/RAIDZ 之类的多设备存储池管理和抽象。ZFS 中的 VDEV 形成一个树状结构,在树的底层是从内核提供的物理设备,其上是虚拟的块设备。每个虚拟块设备对上对下都是块设备接口,除了底层的物理设备之外,位于中间层的 VDEV 需要负责地址映射、容量转换等计算过程。
除了用于存储数据的 Stripe/Mirror/RAIDZ 之类的 VDEV ,还有一些特殊用途的 VDEV ,包括提供二级缓存的 L2ARC 设备,以及提供 ZIL 高速日志的 SLOG 设备。

4、ZFS 的冗余能力建立在 VDEV 之上

ZPOOL 与 VDEV 的关系
ZPOOL 与 VDEV 的关系
zpool 可以由一个或多个 vdev 组成,所以如果你需要增加 zpool 的存储空间,那么你需要增加 vdev 。但需要特别说明的是,如果你将一个由一块硬盘组成的 vdev 添加到了 zpool 中,由于这个单一硬盘组成的 vdev 没有任何的冗余,这也会造成 ZFS 丧失冗余的能力。
💡
那是因为 ZFS 文件系统的冗余能力是建立在 vdev 层面之上(而不是 zpool),所以如果某一个 vdev 自身没有冗余,那么就会造成 ZFS 丧失冗余的能力。
具体举例来说,如果 zpool 中的某一个 vdev 崩掉了,那么整个阵列也就崩掉了。因此对于用户来说,就必须要保证每一个 vdev 都要具备冗余的能力,更具体地说就是每一个 vdev 至少要有两块硬盘组成。
但如果说你使用的是 mirror 这种镜像的阵列模式,那么 vdev 可以是一个单一的硬盘组成而不影响阵列整体的冗余性。
为了适应不同的可靠性要求,存储数据的 VDEV 分为以下几种:
  • single: 简单的单盘 VDEV,无冗余;
  • mirror: 镜像 VDEV,允许多块存储盘,只要一块可用就可以保证数据安全,性能最高。
    • 类似于 RAID 1
  • RAIDz1, RAIDz2, RAIDz3: 允许多块存储盘,各自在数据丢失前允许 1/2/3 块盘失效
    • 相应的,最少需要 3/4/5 块存储盘
    • 使用校验信息块,类似于 RAID 5/6

5、空间效率及容错率

mirror 计算起来很简单:你将获得单盘的空间大小。只要阵列中有一块盘还活着,数据就不会丢失。
RAIDz 阵列需要至少 2+p 块存储盘(p 代表 RAIDz 冗余等级,RAIDz 中 p 为 1,RAIDz2 中为 2,RAIDz3 中为 3)。举个例子,假设所有盘都是相同容量:
  • 2 存储盘 + 1 冗余盘 (RAIDz1)
    • 22+166.7%2+12≈66.7% 空间效率,允许 3 块盘中损失 1 块
  • 4 存储盘 + 1 冗余盘 (RAIDz1)
    • 44+1=80%4+14=80% 空间效率,允许 5 块盘中损失 1 块
  • 4 存储盘 + 2 冗余盘 (RAIDz2)
    • 44+266.7%4+24≈66.7% 空间效率,允许 6 块盘中损失 2 块
需要注意的是如果混用不同容量的盘,则 ZFS 将把所有盘视作最小盘的大小。

6、什么是 dataset(数据集)

在 ZFS 中,dataset 是 ZFS 文件系统中的基本存储单元,类似于传统文件系统中的目录。每个 dataset 都是一个独立的命名空间,可以包含其他 dataset 或文件系统,也可以设置不同的属性和限额。
与传统的目录不同,ZFS dataset 的特点包括:
  1. 数据集是 ZFS 文件系统的基本存储单元,每个数据集拥有自己的属性和限额。
  1. 数据集可以嵌套,使得数据集之间可以形成层次结构。
  1. 每个数据集都可以设置独立的权限控制和属性限制,从而更好地控制数据访问和保护。
  1. 数据集可以被快速克隆和快照,以方便数据备份和恢复。
在 ZFS 中,数据集的命名方式类似于 Linux文 件系统中的路径,例如:
其中,jackie 是 ZFS 存储池的名称,home/jackie 是数据集的名称。
子数据集有层次结构的名称,就像目录一样。例如,unraid/home/jackie ,即 home 这个数据集是 unraid 的子集,并继承了它的属性。通过创建 unraid/home/jackie 进一步扩展这一点。这个孙数据集将从父数据集和祖父数据集继承属性,在子数据集上设置属性可以覆盖从父数据集和祖父数据集继承的默认值。
在 unRAID 中可以通过 zfs create 命令来创建新的数据集,并通过 zfs destroy 命令来删除数据集。不过在 6.12 版本中你不需要手动的去敲命令来创建数据集,当你创建了 ZFS 阵列之后,如果你在 共享(SHARES) 页面创建相应的共享文件夹并将文件夹的首要存储设置为 ZFS 的存储池时,会自动创建与共享文件夹同名的 dataset ,完整的路径为 你的zpool名称/共享文件夹名称
每个数据集都有一个唯一的名称,格式为 zpool名称/挂载路径
《ZFS 入门指北: 基础篇》 ZFS 的 数据集 有点类似于 LVM 的逻辑卷, 但是它内部仍然是 ZFS 的数据结构。

6.1、dataset 可以限制可用空间

dataset 是可以指定可用空间的,比如说我可以给某一个数据集分配 100G 的可用空间,那么这个 dataset 最多也只能使用 100G 的空间容量,但目前 unRAID 还不支持通过 WebUI 界面实现这一目的,但你可以通过 CLI 命令来实现,例如:
上面的命令给名为 unraid 的 zpool 下的 test 数据集可用空间进行了配额 quota=100G ,这样一来 test 这个数据集最多只能使用 100G 的空间。

6.2、dataset 可以更改挂载点

默认情况下,数据集的挂载点将等同于其 ZFS 层级名称 —— 名为 unraid 的池被挂载在 /urnaid,数据集 jackie 被挂载在 /unraid/jackie
那么具体到 unRAID 系统上来说,6.12 版本下通过 WebUI 创建的 zpool 是挂载在 /mnt 下面,所以如果我创建了一个名为 unraid 的 zpool ,并且在“共享(SHARE)”创建了一个使用 zpool 作为主要存储的、共享文件夹名称为 jackie 的文件夹,那么最终这个数据集 jackie 的绝对路径为:
但是,数据集的系统挂载点可以被更改。如果我们设置通过命令:
则数据集 unraid/jackie 实际上会在系统上被挂载在 /hello

7、什么是 Volume(卷)

ZFS 也可以创建卷(Volume),它们显示为磁盘设备。卷具有与数据集相同的许多功能,包括写时复制、快照、克隆和校验和。卷可用于在 ZFS 上运行其他文件系统格式。
对于还不了解 Volume 概念的朋友,这里我解释下 Volume 的概念。
Driver(硬盘)、Partition(分区) 和 Volume 之间的区别:
  1. Driver:对应的是物理设备,也就是硬盘,是物理概念。
  1. Partition:硬盘可以被分成一些逻辑块磁盘,这些逻辑块磁盘就被称为分区,是逻辑概念。
  1. Volume:也涉及分区的概念,它是一种逻辑存储设备,是一种逻辑上的存储数据的载体。在其上利用文件系统格式可以存储文件、目录等内容。
我们要在操作系统上使用一个硬盘,那么我们就得首先对这个硬盘进行分区,然后再对分区进行格式化,格式化的目的就是建立文件系统。
例如对于 Windows 系统来说,硬盘分区会被格式化成 NTFS 文件系统,然后我们就可以在文件系统之上使用各种应用去创建、读取和修改文件等。
C盘、D盘就是不同分区,这些分区都有相应的文件系统 —— NTFS
C盘、D盘就是不同分区,这些分区都有相应的文件系统 —— NTFS
notion image
在未引入 Volume 之前,假设 Windows 的 C 盘想要扩容,那么将无法通过新添加一个硬盘的形式去给C盘增加存储空间。要解决这个问题,我们可以通过 Volume 来实现。
Volume 是逻辑层面的存储设备,它可以对硬盘的分区进行管理。在这种情况下,文件系统直接对 Volume 进行操作,而不再是分区。这么做的好处在于我们可以很方便的对 Volume 进行扩容,并且新增了硬盘的情况下也不会对上层的文件系统产生影响,因为与文件系统打交道的是 Volume 而不再是硬盘分区,处于最上层的应用更是感知不到任何的变化。
notion image
当我们对底层的物理硬盘进行操作时,其不再是针对于分区进行操作,而是通过一个叫做逻辑卷的东西来对其进行底层的磁盘管理操作。比如说我增加一个物理硬盘,这个时候上层的服务是感觉不到的,因为呈现给上次服务的是以逻辑卷的方式。 —— 《Linux系统LVM逻辑卷工作原理》
Volume 有点像 loopback block device ,暴露一个块设备的接口,其上可以创建别的 FS (文件系统)。 —— 《ZFS 分层架构设计

评论