参考資料
- http://docs.oracle.com/cd/E37934_01/html/E36658/toc.html
- https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/zfs.html
内核支持
- 方式一:ZFS 静态編译进内核
-
# 确保内核启用如下三项支持 options ZFS #/usr/src/sys/amd64/conf/MyKernel options NFSD #krpc options UFS_ACL #acl
- 方式二:ZFS 做为模块开机加载
-
# 确保如下两个文件同时存在
# /boot/kernel/zfs.ko
# /boot/kernel/opensolaris.ko
# 必須的两个模块与内核同步編译 MODULES_OVERRIDE= zfs opensolaris krpc acl_posix1e #/etc/make.conf # 设置开机启动 zfs_enable="YES" #/etc/rc.conf.local # 确保 zfs 模块开机加载 zfs_load="YES" #/boot/loader.conf
特性
- ZFS 不通过常规的操作系统工具进行管理,如:pool 中的 diskset 挂载信息不需要写入 fstab
- 包含多个成员的 vdev 创建之后,其結构无法修改,如:无法从 mirror 修改为 raidz2;仅包含单个成员的 vdev 添加设备后可升級为 mirror
- 数据集合(dataset)相当于传统文件系统的挂载点(或者物理分区),不是目录,彼此之间的从属关系不是固定的
- vdev 的成员可以是整个磁盘或某个分区,FreeBSD 平台上两者没有显著的性能差异
- ZFS 提供了磁盘块級别的压縮支持,节省空间并提升写入效率
操作摘要
- zpool(管理逻辑結构:Pool/Vdev/Mem)
- zpool create POOL vdevtype MEM[s] #以一个或多个磁盘或磁盘分区作为成员创建 zfs pool ,vdev 的类型可以为 disk、file、mirror、raidz、log、spare、cache 等
- zpool destroy POOL #消毁 zfs pool
- zpool status [-x] POOL #查詢所有 pool 的健康状态,-x 显示简略信息
- zpool list #显示 pool 列表
- zpool iostat [-v] [N] #显示当前 I/O 负载,-v 显示详细信息,N 处可指定数字,表示每隔 N 秒动态追加新的监控結果
- zpool history [-i] [-l] #显示历史操作记录
- zpool clear #在錯誤修复之后清除旧的錯誤信息
- zpool scrub POOL #校验指定 pool 的 checksum 值并修复损坏的文件, I/O 操作,同一时间仅允许一个 scrub 进程
- zpool offline POOL MEM #停用指定的成员
- zpool remove POOL MEM
- zpool online [-e] POOL MEM #启用指定的成员,-e 选项用于扩展 POOL空间,例如:所有成员均替换成了更大的容量,此操作可使 POOL 识别扩展出的空间
- zpool replace POOL DATASET NEWDISK #替换失效的磁盘或分区,diskset 失效之后,其名称会退化为一串数字(18位 UUID,如:316502962686821739)
- zpool attach POOL VDEV MEM #向当前 pool 中已有的 vdev 中追加一个成员,仅能应用于 mirror 或 disk 两种类型
- zpool detach POOL MEM #从当前 pool 中撤出一个成员,仅能应用于 mirror
- zpool add POOL vdevtype MEM[s] #在已有的 pool 中创建新的 vdev;vdev 一旦创建,则不能从 pool 中撤出
-
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1DISK #若当前 pool 用于启动系统,则在 add 或 attach 之后需要执行此步,DISK 指新添加的成员所在的硬盘(不是分区!)
- zpool split [-n] [-R] POOL NEWPOOL [MEM...] #将一个具备足够冗余能力 POOL 分割成两个,默认将原 POOL 中每个 vdev 的最后一个设备分离出去,新生成的 NEWPOOL 与原 POOL 具有相同的数据,-n 选项指預览結果并不真正执行,-R 选项用于指定 NEWPOOL 的挂载目录,分离到 NEWPOOL 中的成员可以手工指定
- zpool upgrade [-v] [POOL] #不指定 POOL 名称时显示 zfs 版本信息;当 zfs 升級之后,对每个旧版 zfs 系统中的 POOL 执行此命令以应用新特性(此操作不可逆)
- zpool export [-f] POOL[s] #导出一个或多个 pool,用于 zfs pool 整体迁移,-f 强制 umount 所有已挂载的 dataset[s]
- zpool import [-f] [-D] [-m] [-o readonly=on] [-d /PATH] [-R /PATH] POOL #如果要导入的 pool 不在 /dev 下,则需要 -d 指定 pool 所在目录,-D 用于显示及导入被 destroy 的池,-m 用于导入没有日志设备的池(默认不能导入没有 log 的 pool),-R 指定新导入的池的挂载目录(默认是根目录)
- zfs(管理数据集合:Dataset/.../Dataset)
- zfs create [-V SIZE] [-o compression=on]... DATASET #创建 dateset(数据集,存取数据的基本单位),-V 用于在现有 pool 中创建 volume(可以理解为一种虚拟磁盘设备,位于 /dev/zvol/POOL/ 目录下,可以用常规的方式在其上创建其它文件系统)
- zfs rename DATASET POOL/NEWNAME #数据集重命名,可对 snapshot 使用
- zfs mount DATASET
- zfs umount DATASET
- zfs destroy DATASET #消毁 zfs diskset
- zfs snap [-r] DATASET@SNAPNAME #创建 snapshot,@ 之后的部分是快照名称,-r 选项指对当前 dataset 及其子集创建相同名称的快照,快照是只读的,无法修改
注意:快照的作用域仅限于其所对应的 dataset 中直接存储的文件,对逻辑结构视图中的 descendent datasets(子数据集)无效
- zfs rollback [-r] DATASET@SNAPNAME #diskset 将回滚到指定快照创建时的状态,若存在比指定快照更新的快照,则需要指定 -r 选项递归清除这些理更新的快照,然后复到指定快照记录的文件系统状态
- zfs destroy [-r] DATASET@SNAPNAME #消毁快照,-r 指递归清除当前 dataset 及其字集中所有的同名快照
- zfs set mountpoint=/usr/home DATASET #为 diskset 指定挂载点
- zfs list [-r] [-t snapshot/all] #显示 diskset 挂载信息,默认不显示快照信息,添加 -t snapshot 显示,-t all 则同时显示,-r 递归显示当前对象及其所有子对象的信息
- zfs get [PROPERTY]/[all] [DATASET] #显示可用数据集属性(Dataset Properties)
- zfs get snapdir ... #控制当前 dateset 的快照目录(.zfs)是否可以被 ls -a 显示(hidden/visible);若不指定具体的 property,使用 all 选项显示目标对象的所有 dataset 的属性
- zfs get quota/refquota ...#显示指定 dataset 的配置信息
- zfs get reservation/refreservation ... #是示指定数据集的預留空间信息
- zfs get compression ... #显示使用的数据压缩算法,如:lz4、gzip等
- zfs get compressratio ... #显示 dataset 整体的实际压缩比
- zfs get used ... #显示实际占用的空间
- zfs get logicalused ... #显示在不压缩的情况下将占用的空间
- zfs get dedup ... #显示 Deduplication 功能是否启用
- zfs set PROPERTY=VALUE DATASET #为数据集设置属性
- zfs set copies=N DATASET #设置数据 N 份冗余
- zfs set atime=off | on DATASET
- zfs set setuid=off | on
- zfs set readonly=off | on
- zfs set exec=off | on
- zfs set canmount=on | off | noauto
- zfs set type=filesystem | volume | snapshot | bookmark
- zfs set snapdir=visible DATASET #设置 .zfs 目录可以被 ls -a 显示(之后可以从快照目录中直接复制誤删的文件而不需要执行恢复快照操作)
- zfs set compression=lz4/gzip/off/on... DATASET #指定数据压缩方式及开关状态等,zfs 5000 版本及以上可选择 lz4(拥有最高的效率)
- zfs set CUSTOMNAME:PROPERTYNAME=VALUE DATASET #自定义属性
- zfs set quota=10G ... #指定 dataset 的容量上限(hard limit),包括其下的子 dataset 及 snapshot 等
- zfs set refquota=10G ... #同上,但不计算子 dataset 及 snapshot 等的容量
- zfs set quota=none ... #取消配額限制
- zfs set userquota@John=10G #为用户设置配額
- zfs set groupquota@Game=10G #为組设置配額
- zfs set userquota@John=none #取消用户限額
- zfs set reservation=10G ... #为指定dataset 預留的空间,即其本身、子数据集及快照总共最少可以占用的空间,此数值全額计入上层 dataset 的配額
- zfs set refreservation=10G ... #同上,但不包括子数据集合及快照所点的空间,同样静态计入父节点的配額
- zfs set refreservation=none ... #撤消預留空间
- zfs set dedup=off/on ... #是否启用数据合并(以消耗大量内存为代价,追求相同数据仅存一份副本的目标,通常 5G 以上内存才能应对 1T 容量的合并存储需求,默认关闭)
- zfs jail JAIL_ID/JAIL_NAME DATASET #将指定 dataset 分配給 jail 使用(必須设定属性 jailed=on)
- zfs unjail JAIL_ID/JAIL_NAME DATASET #从 jial 中撤出指定 dataset
- zfs inherit [-r] CUSTOMNAME:PROPERTYNAME DATASET #清除主定义属性,-r 递归清除当前 dataset 及其子 dataset 的自定义 property
- zfs diff [-F] POOL/.../DATASET@SNAPSHOT [OTHERSNAPSHOT] #显示快照与当前文件系统之间的差异(若第二个参数指定其它快照,则显示两个快照之间的差异),总共有四种标志:+ - M R,其中 “+” 代表新増的项目,“-” 代表被删除的项目,“M” 指被修改的项目,“R” 指被重命名的项目;-F 选项指显示文件类型:“B” 块设备、“C” 字符设备、“F” 常规文件、“/” 目录、“@” 软链接、“=” 套接字文件
- zfs clone POOL/.../DATASET@SNAPSHOT POOL/.../CLONENAME #克隆指定快照到一份可读写的副本,副本与原快照有从属关系,因此在副本存续期间,原快照无法删除
- zfs promote POOL/.../CLONENAME #反转快照副本与快照的从属关系,执行 promote 之后,副本将成为一个完整的 dateset,快照所对应的文件系统将成为原副本的副本(可以被 destroy),副本的 origin 属性值即其所从属的上級数据集合
- zfs allow John create... DATASET #授予用户操作 DATASET 的特定权限,需要与系统权限綜合考虚方能生效
- zfs allow John allow DATASET #使用户可以将自己拥有的权限分配給其它用户
- zfs send [-v] [-i] [OLDSNAPSHOT] NEWSNAPSHOT #用于远程或本机的跨 pool 备份,将快照所对应的文件系统的所有数据,发送到 STDOUT,通过管道传递給另一个 pool 中的 dateset,-v 显示详细信息,-i 用于増量备份(此时需要指定上一次备份时所用的快照名称:OLDSNAPSHOT)
- zfs receive/recv POOL/.../DATASET #从 STDIN 接收远端传递过来的数据存储到指定位置,recv 是 receive 的缩写
-
#示例 zfs snap -r sendpool/etc@snap_1 #递归创建当前 dataset 及其挂载结构下所有 descendent datasets 的 snapshot zfs snap -r sendpool/etc@snap_2 #本地备份 zfs send sendpool/etc@snap_1 | zfs recv -euv recvpool #-e 选项指在接收端指定的 dataset 下,创建一个以发送端 dataset 挂载视图中的最后一部分(即:basename)命名的新 dataset,用于存储接收的数据;-u 选项指不挂载新创建的 dataset #通过 SSH 远程备份 zfs send -R sendpool/etc@snap_1 | ssh John@10.0.0.2 zfs recv -duv recvpool #-R 选项将源 dataset 及其子数据集下所有的目录与文件(包括 snapshot、clone 等)传递到远程主机,而且,发送端数据集中已经不存在的快照,将在接收端销毁;-d 选项指在接收端指定的 dataset 下,创建一个以发送端 dataset 的完整路径名称(除了最上层的 pool 名称)命名的新 dataset zfs send -i -R sendpool/etc@snap_1 sendpool/etc@snap_2 | ssh John@10.0.0.2 zfs recv -uv recvpool/ #-i 指増量备份,此时不能指定 -d 或 -e #若远程主机不允许 root 登陆 #在发送端执行([可选]授予普通用户 Marry 执行发送及操作快照的权限): zfs allow -u Marry send,snapshot sendpool #在接收端执行(授予普通用户 John 创建、挂载、接收的权限): echo vfs.usermount=1 >> /etc/sysctl.conf zfs allow -u John create,mount,receive recvpool chown John /recvpool
-
zdb
-
zdb -S POOL #显示指定 pool 的数据存储策略
-
# zdb -S zroot Simulated DDT histogram: (DDT:deduplication table) bucket allocated referenced ______ ______________________________ ______________________________ refcnt blocks LSIZE PSIZE DSIZE blocks LSIZE PSIZE DSIZE ------ ------ ----- ----- ----- ------ ----- ----- ----- 1 261K 2.82G 1.32G 1.89G 261K 2.82G 1.32G 1.89G ...... 64 6 72K 28.5K 32K 486 5.48M 2.16M 2.48M Total 276K 3.30G 1.54G 2.14G 297K 4.21G 1.87G 2.49G dedup = 1.17, compress = 2.25, copies = 1.33, dedup * compress / copies = 1.97
-
調优策略
- vfs.zfs.min_auto_ashift
- 此项决定 pool 的逻辑扇区大小,用 2 的 N 次方形式賦值,如:设置为 4K,则此项应賦值为 12,即 212=4096
- 大多数应用场景中,指定为 12 将获得最佳性能(默认为 9,即 512B)
- 用作数据库存储时,保持默认值(9)性能更佳,因为数据库更多的是小数据块的随机读取,更小的逻辑块可减少每次读取的数据量
- pool 一旦建立,logical sector size 便不能更改
- read/write 参数,可通过 sysctl 調整,但調整結果对已经建立的 pool 无效
- vfs.zfs.arc_min
- 为 ZFS 的頁緩存机制(ARC: Adaptive Replacement Cache)預留的最小内存空间,防止内存被其它应用耗光而大幅降低存储系统的性能
- 通常设置为总内存总量的 1/4 至 1/2
- readonly 参数,设置 /boot/loader.conf 后重启方能生效
- vfs.zfs.arc_max
- ZFS 可以用于 ARC 的最大内存量
- ZFS 的性能提升非常依賴内存,在保証服务器主应用内存空间的前提下,尽可能提升此值
- readonly 参数,设置 /boot/loader.conf 后重启方能生效
- vfs.zfs.arc_meta_limit
- ARC 中可用于存储元数据(metadata)的比例,默认为 1/4
- 在面对巨量小文件的场景中,可次此值适当調高,如 ARC/2
- readonly 参数,设置 /boot/loader.conf 后重启方能生效
- vfs.zfs.prefetch_disable
- 是否启用 ARC 大块数据預读,默认为 0,即开启預读
- 在巨量随机读取的环境中,通过关闭預读(设置为:1)减少不必要的数据读取,可大幅提升性能
- read/write 参数,sysctl 后即时生效
- vfs.zfs.vdev.trim_on_init
- 针对 SSD 的 TRIM 功能,有助于延长使用寿命及提升长期性能,默认启用
- read/write 参数,sysctl 后即时生效,不需要一直开启(尤其是新设备),可设置低负载时段定时开启
- vfs.zfs.resilver_delay
- 更换新的硬盘后数据恢复的过程中,两个 I/O 之间的延迟时间,默认为 2 毫秒
- IOPS (I/Os Per Second)=kern.hz / *_delay,kern.hz(Number of clock ticks per second) 默认为 1000,则默认情况下的 I/O 速度 IOPS=1000/2=500
- 若当前已无数据冗余保障,可将此项值調整为 0 不限制 I/O 速度,以提高恢复效率
- read/write 参数,sysctl 后即时生效
- vfs.zfs.scrub_delay
- 执行 scrub 操作时的 I/O 限制,默认延迟为 4 毫秒,IOPS=250
- 空閑时段或調试时可设为 0 提升速度
- read/write 参数,sysctl 后即时生效
- vfs.zfs.scan_idle
- 存储池空閑状态判定时限,默认为 50 毫秒(milliseconds)
- 任一存储池无 I/O 操作超过此值,即判定为 idle 状态,此时 scrub 与 resilver 的 I/O 速度限制将自动解除
- read/write 参数,sysctl 后即时生效
- ...