參考資料
- 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 后即時生效
- ...