ZFS-基于Ubuntu使用Zettabyte File System
ZFS 的支持从 Ubuntu Wily 15.10 开始作为技术预览加入,到 Ubuntu Xenial 16.04 实现完整支持。注意 ZFS 只支持 64位架构。另外,ZFS 仅支持 data storage, 不支持 root filesystem(在18.04经过配置后可以支持)。
运行ZFS要求空余内存多于 2GB,建议 ZFS 系统不少于 8GB 内存。
安装 ZFS, 使用:
sudo apt install zfsutils-linux
下面快速预览 ZFS, 更多的关于 ZFS的信息请参考 excellent documentation ,由 Aaron Toponce 编写。
注意
为了节约篇幅,本文档中 devices 指 /dev/sda /dev/sdb 等等。 使用device路径 /dev/disk/by-uuid 可以唯一地代表一个设备从而避免在设备名称映射改变时启动失败。
ZFS 虚拟设备 (ZFS VDEVs)
一个 VDEV 是一个meta-device,代表着一个或多个设备。ZFS 支持 7 中不同类型的 VDEV:
- File - 预先分类的文件,为*.img的文件,可以作为一个虚拟设备载入ZFS。
- 物理磁盘驱动器 (HDD, SDD, PCIe NVME, etc)。
- Mirror - 标准的 RAID1 mirror。
- ZFS 软件RAID,如 raidz1, raidz2, raidz3 'distributed' parity。
- Hot Spare - hot spare(热备)用于 ZFS 的软件 raid。
- Cache - a device for level 2 adaptive read cache (ZFS L2ARC)
- Log - ZFS Intent Log (ZFS ZIL)。
VDEVS 动态地由 ZFS. 进行分带。一个 device 可以被加到 VDEV, 但是不能移除。
ZFS Pools
zpool 是存储池,从一系列VDEVS中创建出来。更多的 ZFS 文件系统可以从 ZFS pool 中创建出来。
下面的例子中,名为 "pool-test"的存储池从3个物理磁盘驱动器中创建出来:
$ sudo zpool create pool-test /dev/sdb /dev/sdc /dev/sdd
Striping 被动态地执行,创建了一个零冗余的RAID-0存储池。
注意:如果管理很多存储驱动器,很容易引起混淆,可以使用 /dev/disk/by-id/ 名称机制,提供基于序列号的驱动器标识。上面的方法主要是为了方便演示。
查看存储池的状态:
$ sudo zpool status pool-test
删除存储池:
$ sudo zpool destroy pool-test
创建 2 x 2 镜像的 zpool 例子
下面创建 zpool,包含的 VDEV 有两个 drives组成为一个镜像。
$ sudo zpool create mypool mirror /dev/sdc /dev/sdd
我们再加两个驱动器组成的镜像到存储池中:
$ sudo zpool add mypool mirror /dev/sde /dev/sdf -f $ sudo zpool status pool: mypool state: ONLINE scan: none requested config: NAME STATE READ WRITE CKSUM mypool ONLINE 0 0 0 mirror-0 ONLINE 0 0 0 sdc ONLINE 0 0 0 sdd ONLINE 0 0 0 mirror-1 ONLINE 0 0 0 sde ONLINE 0 0 0 sdf ONLINE 0 0 0
该例子中:
- /dev/sdc, /dev/sdd, /dev/sde, /dev/sdf 是物理存储设备。
- mirror-0, mirror-1 是虚拟的设备 VDEVs。
- mypool 是 pool 存储池。
有很多种布局 VDEVs 的方法来创建一个存储池(zpool)。
基于单个文件的 zpool
在下面的例子中,我们使用单个 2GB 文件作为 VDEV,然后从该虚拟存储设备创建 zpool :
$ dd if=/dev/zero of=example.img bs=1M count=2048 $ sudo zpool create pool-test /home/user/example.img $ sudo zpool status pool: pool-test state: ONLINE scan: none requested config: NAME STATE READ WRITE CKSUM pool-test ONLINE 0 0 0 /home/user/example.img ONLINE 0 0 0
该例子中:
- /home/user/example.img 是基于文件的VDEV。
- pool-test 是存储池。
RAID-磁盘阵列功能
ZFS 提供几个 RAID 选项:
条带,Striped VDEVS
等价于 RAID0。没有校验和镜像用于数据重建恢复。该方法不建议使用,当驱动器失效时会造成数据丢失。下面创建一个条带化的存储池,使用了 4 个 VDEVs:
$ sudo zpool create example /dev/sdb /dev/sdc /dev/sdd /dev/sde
镜像,Mirrored VDEVs
类似于 RAID1,使用 2 个以上的VDEVs。对于 N VDEVs,当小于 N-1 个磁盘失效时数据可以恢复。下面的例子使用 2 个VDEVs创建存储池。
- $ sudo zpool create example mirror /dev/sdb /dev/sdc
条带+镜像,Striped Mirrored VDEVs
类似于 RAID10,对于小的随机读 I/O 比较好。创建镜像对,然后基于镜像进行条带化。 下面创建 2 x 2 条带化的镜像池:
sudo zpool create example mirror /dev/sdb /dev/sdc mirror /dev/sdd /dev/sde
或者:
sudo zpool create example mirror /dev/sdb /dev/sdc sudo zpool add example mirror /dev/sdd /dev/sde
软件磁盘阵列,RAIDZ
类似于 RAID5, 使用可变宽度的条带用于奇偶校验。允许在奇偶校验的情况下得到较大的容量,而又不牺牲太多的性能。允许单个盘失败的情况下不丢失信息。创建 4 个VDEV的RAIDZ:
$ sudo zpool create example raidz /dev/sdb /dev/sdc /dev/sdd /dev/sde
软件磁盘阵列,RAIDZ2
类似于 RAID6,与RAIDZ类似但具有双重奇偶校验。例如,创建 2 parity 5 VDEV 的 pool:
$ sudo zpool create example raidz2 /dev/sdb /dev/sdc /dev/sdd /dev/sde /dev/sdf
软件磁盘阵列,RAIDZ3
3 parity bits,允许三块盘失败而不丢失数据,性能与 RAIDZ2 和 RAIDZ差不多。例如,创建 3 parity 6 VDEV 的pool:
$ sudo zpool create example raidz3 /dev/sdb /dev/sdc /dev/sdd /dev/sde /dev/sdf /dev/sdg
软件磁盘阵列,Nested RAIDZ
类似 RAID50, RAID60, striped RAIDZ volumes。比 RAIDZ更好的执行性能,但是会减少容量,从而增加了使用成本。例如 2 x RAIDZ:
$ sudo zpool create example raidz /dev/sdb /dev/sdc /dev/sdd /dev/sde $ sudo zpool add example raidz /dev/sdf /dev/sdg /dev/sdh /dev/sdi
日志加速,ZFS Intent Logs
ZIL (ZFS Intent Log) 驱动器可以被添加到 ZFS pool 来加速写入的能力,适用于任何级别的ZFS RAID。最好使用快速的 SSD来存储ZIL。从概念上说,ZIL 是一种对于 data 和 metadata 的日志机制,先写入然后再刷新为写事务。实际上, ZIL 更为复杂,参考 described in detail here。一个或多个驱动器可以被用于 ZIL。
例如,加入SSDs 到存储池 'mypool', 使用:
$ sudo zpool add mypool log /dev/sdg -f
缓存加速,ZFS Cache Drives
Cache devices 提供在 memory 和 disk的缓冲层。用于改善静态数据的随机读写性能。
例如,添加缓冲磁盘 /dev/sdh 到存储池 'mypool', 使用:
$ sudo zpool add mypool cache /dev/sdh -f
ZFS 文件系统
ZFS 允许每个存储池最多创建 2^64 文件系统。我们在存储池 'mypool'创建文件系统,如下:
sudo zfs create mypool/tmp sudo zfs create mypool/projects
删除文件系统,使用:
sudo zfs destroy mypool/tmp
每一个 ZFS 文件系统都可以有属性设置,例如设置最多 10 gigabytes的使用限额:
sudo zfs set quota=10G mypool/projects
添加压缩支持:
sudo zfs set compression=on mypool/projects
ZFS snapshot,快照
ZFS snapshot(快照)是 ZFS 文件系统或卷的只读拷贝。可以用于保存 ZFS 文件系统的特定时点的状态,在以后可以用于恢复该快照,并回滚到备份时的状态。
下面的例子中,我们创建 mypool/projects 文件系统的快照:
$ sudo zfs snapshot -r mypool/projects@snap1
可以查看所有的snapshots列表,使用:
$ sudo zfs list -t snapshot NAME USED AVAIL REFER MOUNTPOINT mypool/projects@snap1 8.80G - 8.80G -
现在, 'accidentally' 破坏文件然后回滚:
$ rm -rf /mypool/projects $ sudo zfs rollback mypool/projects@snap1
移除snapshot,使用:
$ sudo zfs destroy mypool/projects@snap1
ZFS Clones,克隆
一个ZFS clon是文件系统的可写的拷贝。一个 ZFS clone 只能从 ZFS snapshot中创建,该 snapshot 不能被销毁,直到该 clones 也被销毁为止。
例如,克隆 mypool/projects,首先创建一个 snapshot 然后 clone:
$ sudo zfs snapshot -r mypool/projects@snap1 $ sudo zfs clone mypool/projects@snap1 mypool/projects-clone
ZFS Send 和 Receive
ZFS send 发送文件系统的快照,然后流式传送到文件或其他机器。ZFS receive 接收该 stream 然后写到 snapshot 拷贝,作为 ZFS 文件系统。 这对于备份和通过网络发送拷贝 (e.g. using ssh) 来拷贝文件系统。
例如,创建 snapshot 然后 save 到文件:
sudo zfs snapshot -r mypool/projects@snap2 sudo zfs send mypool/projects@snap2 > ~/projects-snap.zfs
..然后接收回来:
sudo zfs receive -F mypool/projects-copy < ~/projects-snap.zfs
ZFS Ditto Blocks,重复块
Ditto blocks 创建更多的冗余拷贝。对于只有一个设备的 storage pool ,ditto blocks are spread across the device, trying to place the blocks at least 1/8 of the disk apart。对于多设备的 pool,ZFS 试图分布 ditto blocks 到多个 独立的 VDEVs. 1 到 3 份拷贝可以被设置。设置三份拷贝到 mypool/projects:
$ sudo zfs set copies=3 mypool/projects
ZFS Deduplication,文件去重
ZFS dedup 将丢弃重复数据块,并以到现有数据块的引用来替代。这将节约磁盘空间,大需要大量的内存。内存中的去重记录表需要消耗大约 ~320 bytes/block。表格尺寸越大,写入时就会越慢。
启用去重功能在 mypool/projects, 使用:
$ sudo zfs set dedup=on mypool/projects
为了更多的去重 pros/cons ,参考 http://constantin.glez.de/blog/2011/07/zfs-dedupe-or-not-dedupe 。
ZFS Pool Scrubbing,检修
初始化数据完整性检测,通过 zfs scrub 命令执行。如:
$ sudo zpool scrub mypool
通过zpool status 使用 scrub,例如:
$ sudo zpool status -v mypool
数据恢复,简单的例子
假设有一个 2 x 2 镜像的zpool:
$ sudo zpool create mypool mirror /dev/sdc /dev/sdd mirror /dev/sde /dev/sdf -f $ sudo zpool status pool: mypool state: ONLINE scan: none requested config: NAME STATE READ WRITE CKSUM mypool ONLINE 0 0 0 mirror-0 ONLINE 0 0 0 sdc ONLINE 0 0 0 sdd ONLINE 0 0 0 mirror-1 ONLINE 0 0 0 sde ONLINE 0 0 0 sdf ONLINE 0 0 0
填充数据,然后检查:
$ dd if=/dev/urandom of=/mypool/random.dat bs=1M count=4096 $ md5sum /mypool/random.dat f0ca5a6e2718b8c98c2e0fdabd83d943 /mypool/random.dat
模拟 catastrophic data loss,覆盖 VDEV devices:
$ sudo dd if=/dev/zero of=/dev/sde bs=1M count=8192
初始化 scrub:
$ sudo zpool scrub mypool
然后检测状态:
$ sudo zpool status pool: mypool 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'. see: http://zfsonlinux.org/msg/ZFS-8000-9P scan: scrub in progress since Tue May 12 17:34:53 2015 244M scanned out of 1.91G at 61.0M/s, 0h0m to go 115M repaired, 12.46% done config: NAME STATE READ WRITE CKSUM mypool ONLINE 0 0 0 mirror-0 ONLINE 0 0 0 sdc ONLINE 0 0 0 sdd ONLINE 0 0 0 mirror-1 ONLINE 0 0 0 sde ONLINE 0 0 948 (repairing) sdf ONLINE 0 0 0
...从 pool移除驱动器:
$ sudo zpool detach mypool /dev/sde
..热切换,然后添加一个新的:
$ sudo zpool attach mypool /dev/sdf /dev/sde -f
..然后初始化scrub,修复 2 x 2 mirror:
$ sudo zpool scrub mypool
ZFS 压缩
如之前提到,ZFS支持数据的压缩。通过现代的 CPUs,压缩减少了数据尺寸,从而读写的数据量减少而获得更好的 I/O。ZFS提供了一系列的压缩方法。缺省的是 lz4 (a high performance replacement of lzjb) ,提供了较快的压缩和解压缩效率和较高的压缩比。可以设置压缩的级别。
sudo zfs set compression=gzip-9 mypool
以及设置压缩的类型:
sudo zfs set compression=lz4 mypool
检查压缩比:
sudo zfs get compressratio
lz4 比其它的要快,lz4 是最安全的选项。
来源:oschina
链接:https://my.oschina.net/u/2306127/blog/2250662