内容


在预算之下实现大量快速而又稳定的存储

利用 ZFS 和 RAID-Z 构建并维持快速存储服务器

ZFS 和 RAID-Z 简介

ZFS 是目前可用的最先进的文件系统之一。ZFS 是 zettabyte 文件系统 的首字母缩写,可以作为对该系统的存储功能的直接引用,该系统最多可存储 256 万亿 zettabyte 。换一种方式来表达的话,一个 zettabyte 等于 1,073,741,824 个太字节!

ZFS 这个独特而强大的工具具有多面性。我们将重点介绍与构建可伸缩的、冗余存储服务器有关的部分。这为我们引入了 RAID-Z 的概念 ,顾名思义,RAID-Z 是与 RAID 技术类似 (更确切地说是与 RAID-5 类似)的一项技术。

熟悉 RAID 的人大概都想知道应该用什么设备(或控制器)来处理磁盘和数据。在使用 RAID-Z 时,所有一切都由文件系统本身来处理。但是,与类似技术不同的是,RAID-Z 会自我修复毁坏的数据块,并且无需用户参与即可动态修复它们。RAID-Z 会经常检验数据校验和,以确认完整性,它还能够识别需要重新构建的块。它会在所请求的数据到达用户那里之前完成检验工作。

由于许多操作系统都支持 RAID-Z 和 ZFS,所以可以根据您的偏好来选定 OS。无论选择的是哪种 OS,本文中讨论的示例和技术都应该能够正确应用和运作。

存储设计

您现在需要多少空间?预计一年中需要使用多少空间?需要提供多少个用于安装的硬盘驱动器才合适?所有这些都是开始安装前应该考虑的问题。为了提供最好的准备,我将讨论每个设计决策。

操作系统

强烈推荐使用对 ZFS 文件系统提供本机支持的操作系统,以便充分利用所有的特性和性能。将要采用的所有示例都使用 OpenIndiana(Open Solaris 的社区维护分支)作为操作系统,因此,所用的命令和终端互动会反映出 OpenIndiana 环境。(有关 OpenIndian 的更多信息,请参阅 参考资料 。)

不过,如果您更习惯于使用 Linux®,并且知道使用兼容命令可以获得与本文同样的结果,那么您应该了解您选择的分布是否支持 zfs-fuse(ZFS 文件系统的一个端口)。

存储空间

因为存储空间将直接影响到您的其他选择,所以从设计阶段就开始规划存储空间极其重要。空间还会受到所需 RAID-Z 配置类型的影响(在 RAID-Z 选项 一节中,有更多关于这方面的介绍)。

不要指望将 OS 用作整个存储的一部分。建议在单独的硬盘驱动器上安装 OS,因为这样会使得重装或修复系统变得更容易,且不会影响共享。

您需要牢记的是,无论使用多少设备,要确保这些设备能够满足您的 RAID-Z 需求(例如,对于此演示,至少需要 5 个硬盘驱动器)。尽管 RAID-Z 安装可以配备不同大小的硬盘驱动器(例如一个 5 x 2 太字节的驱动器和一个 1 x 1 太字节的驱动器),ZFS 会依据池中最小的驱动器的大小来有效定义硬盘驱动器。

同一品牌、相同大小的驱动器会提供更佳的性能。

RAID-Z 选项

在 RAID-Z 安装中,有大量配置可供使用。我会介绍其中的两个配置,然后深入研究此项目的最终选择的更多细节。

RAID-Z 是最小的容错。它在池中提供了一个磁盘奇偶校验磁盘,如果一个以上驱动器出问题,则会出现一个损坏的、不可恢复的存储池。

RAID-Z2 将两个磁盘用于奇偶校验。即使出现有损坏的或出故障的磁盘,这两个磁盘也能提供安全性。尽管 RAID-Z2 为了使系统正确运行而使用两个额外的磁盘,但与普通的 RAID-Z 安装相比,提供了更强大的容错功能。

RAID-Z2 安装的最低要求是应该配置 5 个驱动器(两个用于奇偶校验),剩下三个驱动器全部用于存储。例如,两太字节的驱动器会导致六太字节的存储。

硬盘驱动器

如我之前所言,最好使用同一牌子、相同大小的驱动器。使用极为相似的一组驱动器可以提供更好的安全性。

在构建存储服务器时,最好购买至少一个额外硬盘驱动器来减少可能的延迟。碰到有制造问题的硬盘驱动是很常见的事。

成长和可伸缩性

额外的驱动器意味着速度的增加,因为数据遍布于整个空间。因此,确保总空间大小与目标存储空间匹配非常重要。有一些 SATA 控制器允许对主机板进行扩展,但如果不事先做好准备的话,可能会带来一些麻烦。

获得可伸缩、可成长存储的三个关键要素如下:

  1. 硬盘驱动器的数量
  2. 总存储容量
  3. 硬盘驱动器的服务器容量

我刚刚建立了一个16 万亿字节的存储服务器,该服务器提供了将空间扩展至两倍的能力,这使您能够应对无法预料的空间增长,并帮助您控制预算。

创建一个池

最初,我们决定在单独的驱动器上安装操作系统,并且提供了 5 个可用的其他设备。我们需要注意每个设备上的标签,以便以后创建存储池的时候指定它们。

清单 1. 寻找设备标签
root@raidz:~# format
Searching for disks...done

AVAILABLE DISK SELECTIONS:
0. c7d0 DEFAULT cyl 4092 alt 2 hd 128 sec 32
/pci@0,0/pci-ide@1,1/ide@0/cmdk@0,0
1. c9t0d0 DEFAULT cyl 1022 alt 2 hd 128 sec 32
/pci@0,0/pci8086,2829@d/disk@0,0
2. c9t1d0 DEFAULT cyl 1022 alt 2 hd 128 sec 32
/pci@0,0/pci8086,2829@d/disk@1,0
3. c9t2d0 DEFAULT cyl 1022 alt 2 hd 128 sec 32
/pci@0,0/pci8086,2829@d/disk@2,0
4. c9t3d0 DEFAULT cyl 1022 alt 2 hd 128 sec 32
/pci@0,0/pci8086,2829@d/disk@3,0
5. c9t4d0 DEFAULT cyl 1022 alt 2 hd 128 sec 32
/pci@0,0/pci8086,2829@d/disk@4,0

Specify disk (enter its number):

我们发出 format 命令来寻找标签(或 ID),不需要输入数字进行选择。单击 Ctrl-C 可从命令提示中退出。

在设备 0 上安装 OS,稍后再决定如何添加其他 5 个设备,因此,对于存储池而言,以下标签非常有趣:

  • c9t0d0
  • c9t1d0
  • c9t2d0
  • c9t3d0
  • c9t4d0

ZFS 的一个引人注目的特性是它能够很快地创建文件系统本身。格式化或重新格式化硬盘驱动器通常非常耗时。而在使用 ZFS 的情况下,创建文件系统需要约两秒时间。不管硬盘驱动器的大小如何,创建文件系统都只需要几秒的时间。

清单 2. 创建存储池
zpool create tank raidz2 c9t0d0 c9t1d0 c9t2d0 c9t3d0 c9t4d0

Zpool create tank 命令会判断要构建的文件系统,对一些驱动器进行格式化,并将此存储池标记为 tank。我将 raidz2 指定为 RAID-Z 类型,但您可以选择 raidzraidz3清单 1 中列出了我选择的 5 个设备的 ID。

我们已经完成了另一个重要步骤:已经装载存储池并准备使用它!

清单 3. 验证池的创建
root@raidz:~# df -h
Filesystem             size   used  avail capacity  Mounted on
swap                   642M    16K   642M     1%    /tmp
swap                   642M    44K   642M     1%    /var/run
rpool/export/home      7.8G    21K   4.1G     1%    /export/home
rpool                  7.8G    77K   4.1G     1%    /rpool
tank                   5.8G    34K   5.8G     1%    /tank

为了简便起见,我们缩短了命令输出,但您可以看见,显示 tank 几乎占用了六千兆字节,并且该命令装载在文件系统的 root 级别上。因为选择安装两个磁盘奇偶校验磁盘,所以有效存储大小将接近于其他三个磁盘的总和。在装载存储池并准备好使用它之后,让我们来检查一下磁盘和所有数组的健康情况。

清单 4. 存储池状态
root@raidz:~# zpool status tank
pool: tank
state: ONLINE
scrub: none requested
config:

NAME        STATE     READ WRITE CKSUM
tank        ONLINE       0     0     0
raidz2      ONLINE       0     0     0
c9t0d0      ONLINE       0     0     0
c9t1d0      ONLINE       0     0     0
c9t2d0      ONLINE       0     0     0
c9t3d0      ONLINE       0     0     0
c9t4d0      ONLINE       0     0     0

errors: No known data errors

如果需要,可以在存储池 tank 中创建嵌套式文件系统。如果希望设置单独的特定存储需求,并且将权限绑定在共享自身上,那么这种方法非常有用。如果只有一个分享,那么使用此方法反而可能有些复杂。

清单 5. 添加共享
root@raidz:/tank# zfs create tank/bar 
root@raidz:/tank# zfs list
NAME                        USED  AVAIL  REFER  MOUNTPOINT
rpool                      3.74G  4.07G  77.5K  /rpool
rpool/ROOT                 2.99G  4.07G    19K  legacy
rpool/swap                  512M  4.43G   137M  -
tank                        160K  5.83G  34.8K  /tank
tank/bar                   34.0K  5.83G  34.0K  /tank/bar

我们创建了一个名为 bar 的共享,并将它作为一个单独的共享。但是,不要被显示的六千兆字节所迷惑,我们并没有将总的共享空间加倍,而是认为了解总的存储池中有多少可用空间很有用。

恢复

在建立存储池之后,我们需要认识到的是,数据可能被毁坏,硬盘驱动器可能会出现故障。幸运的是,ZFS 和 RAID-Z 使您能够轻松管理这些任务。这部分提供了对坏的硬盘驱动器以及操作系统无法恢复时的总系统故障的模拟。

损坏的硬盘驱动器

在此场景中,我故意提供了一个无法访问服务器的硬盘驱动器。让我们来看一下出现故障时的 ZFS 报告。

清单 6. 损坏的驱动器的状态
root@raidz:~# zpool status tank
pool: tank
state: DEGRADED
status: One or more devices could not be opened.  
Sufficient replicas exist for the pool to continue functioning in 
a degraded state.
action: Attach the missing device and online it using 'zpool online'.
scrub: none requested
config:

NAME        STATE     READ WRITE CKSUM
tank        DEGRADED     0     0     0
raidz2      DEGRADED     0     0     0
c9t0d0      ONLINE       0     0     0
c9t1d0      ONLINE       0     0     0
c9t2d0      ONLINE       0     0     0
c9t3d0      ONLINE       0     0     0
c9t4d0      UNAVAIL      0     0     0  cannot open

errors: No known data errors

存储池只是降级了。状态命令显示了池中的情况,以及哪个硬盘驱动器似乎出故障了。还需要重点注意的是,存储器是完全可用的。请记住,我选择了 raidz2,它允许最多两个硬盘驱动器同时失败。为了让这一场景变得更加真实,我将一些日志文件复制到存储器中,以模拟降级状态。

更换有问题的硬盘驱动器之后,我再一次启动服务器以观察结果。

清单 7. 从降级状态中恢复
root@raidz:~# zpool status tank
pool: tank
state: ONLINE
status: One or more devices has experienced an unrecoverable error.  An
attempt was made to correct the error.  Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
using 'zpool clear' or replace the device with 'zpool replace.'
scrub: resilver completed after 0h0m with 0 errors on Tue Nov  9 07:25:23 2010
config:

NAME        STATE     READ WRITE CKSUM
tank        ONLINE       0     0     0
raidz2      ONLINE       0     0     0
c9t0d0      ONLINE       0     0     0
c9t1d0      ONLINE       0     0     0
c9t2d0      ONLINE       0     0     0
c9t3d0      ONLINE       0     0     0
c9t4d0      ONLINE       0     0     2  31.5K resilvered

errors: No known data errors

在没有我们参与的情况下,不仅共享得到完全恢复,而且输出也提供了一些详细信息:关于发生了什么事,采取了哪些措施以及对结果不满意(比如文件损坏)时的可能选项。

resilvered 标签表示 ZFS 为特定驱动器重新构造了相应数量的数据。

不可修复的操作系统

在这一节中,我复制了一个具有无法引导错误的系统错误。因为系统安装在远离重要存储器的单独硬盘驱动器上,所以可以在同一硬盘驱动器上重新安装该系统,无需接触与共享有关联的设备。

像以前一样,我们依赖于 zpool 命令来诊断存储器,观察是否还能使用它。

清单 8. 重新安装之后的池状态
root@reinstalled:~# zpool status
pool: rpool
state: ONLINE
scrub: none requested
config:

NAME        STATE     READ WRITE CKSUM
rpool       ONLINE       0     0     0
c7d0s0      ONLINE       0     0     0

errors: No known data errors

这证实安装是起作用的,但我仍然没有看到存储器。

清单 9. 找到存储池
root@reinstalled:~# zpool import
pool: tank
id: 11026414298329032494
state: ONLINE
status: The pool was last accessed by another system.
action: The pool can be imported using its name or numeric identifier and
the '-f' flag.
see: http://www.sun.com/msg/ZFS-8000-EY
config:

tank        ONLINE
raidz2      ONLINE
c9t0d0      ONLINE
c9t1d0      ONLINE
c9t2d0      ONLINE
c9t3d0      ONLINE
c9t4d0      ONLINE

太好了!这就是存储池。它形状完美并且我准备导入它。

清单 10. 池的导入和验证
root@reinstalled:~# zpool import tank
cannot import 'tank': pool may be in use from other system, it was 
last accessed by raidz (hostid: 0x4013af) on Tue Nov  9 07:31:33 2010
use '-f' to import anyway
root@reinstalled:~# zpool import -f tank
root@reinstalled:~# zpool status tank
pool: tank
state: ONLINE
scrub: none requested
config:

NAME        STATE     READ WRITE CKSUM
tank        ONLINE       0     0     0
raidz2      ONLINE       0     0     0
c9t0d0      ONLINE       0     0     0
c9t1d0      ONLINE       0     0     0
c9t2d0      ONLINE       0     0     0
c9t3d0      ONLINE       0     0     0
c9t4d0      ONLINE       0     0     0

errors: No known data errors
root@reinstalled:~# df -h
Filesystem             size   used  avail capacity  Mounted on
/                      7.8G   2.8G   4.2G    41%    /
/devices                 0K     0K     0K     0%    /devices
swap                   800M   368K   800M     1%    /etc/svc/volatile
rpool/export           7.8G    21K   4.2G     1%    /export
rpool                  7.8G    79K   4.2G     1%    /rpool
tank                   5.8G   104K   5.8G     1%    /tank

我试图引入池,但另一个系统可能正在使用输出报告。在这种情况下,将会使用以前安装的存储器。我强行执行导入操作,并验证状态,但它返回的结果中没有任何错误。最后,我检查了装载和安装情况,确认它们和以前一样。

我浏览了一些常见场景,并毫不费力地恢复了存储器。

共享

共享很简单。下一节将介绍如何通过 NFS 实现共享,因为许多操作系统(包括各种风格的 Linux 和 UNIX)都支持 NFS。

因为 ZFS 提供了 NFS 本机支持,所以您只需了解文件系统、分享类型和位置即可。

清单 11. 通过 NFS 实现分享
root@reinstalled:~# zfs set sharenfs=on tank

在本例中,tank 是共享,并且可以通过 NFS 在本地网络中共享它。此外,还可以在特定分享上设置权限,但要注意的是,如果您共享了该共享的 root 权限,则会自动共享其所有现有子共享或者将来创建的子分享。

图 1. 在 Mac OSX 中连接到 NFS 共享
屏幕截图显示了连接到 nfs://10.0.1.45/tank 的一个 Mac OSX 屏幕
屏幕截图显示了连接到 nfs://10.0.1.45/tank 的一个 Mac OSX 屏幕

在服务器上建立共享通常很耗时,但是,通过特定协议(比如 NFS)共享文件系统本身的功能很有用。

前面的共享没有提供保护或权限设置,所以让我们看看如何修改该共享,从而允许对网络中的特定子网络进行读取和写入 操作。

清单 12. ZFS 共享中基于网络的权限
zfs set sharenfs=rw=@10.0.0.0/8 tank

即使不进行额外的配置,这类网络限制也会起作用。只要发送出此命令,访问就会受到限制,只有指定的子网能对共享进行读写访问。

可以仔细调整权限,将它们用于特定用户或组,而权限的实现和配置可能因系统的不同而有所不同。

结束语

ZFS 已经移植到许多操作系统上使用,现在许多 UNIX 和 Linux 版本中都可以使用它。

虽然还有许多关于 ZFS 和 RAID-Z 的信息需要讨论,但本文只查看了对构建共享最重要的一些事项,从设计决策到通过网络共享存储。

RAID-Z 不是唯一可用于 ZFS 的磁盘阵列类型,镜像速度通常更快且消耗的内存更少,但需要等量的硬盘驱动器才能使用它。在这种情况下,我们为共享准备了 5 个硬盘驱动器,并且未必会使用到所有这些设备。

当试图在可以支持多个设备的服务器中构建存储并通过网络共享该存储时,ZFS 是一个理想选择。但是,如果没有提供至少两个单独的设备,您就无法享受到 ZFS 带来的所有好处。设备越多,得到的性能就越好!

希望您已经准备好探索 ZFS 文件系统,并像我一样发现它非常有用。


相关主题

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Open source
ArticleID=757330
ArticleTitle=在预算之下实现大量快速而又稳定的存储
publish-date=09132011