当前位置:首页>Linux>Linux zfs文件系统:压缩、加密、配额

Linux zfs文件系统:压缩、加密、配额

  • 2026-09-10 17:07:19
Linux zfs文件系统:压缩、加密、配额

字数 1706,阅读大约需 9 分钟

压缩、加密、配额,这三个特性是 ZFS 的"杀手锏",在 LVM + ext4 中要么没有、要么需要外部工具。ZFS 一行命令搞定。

一、压缩(Compression)

1.1 压缩算法

ZFS 支持的压缩算法:

算法
速度
压缩率
适用
off
-
-
关闭
lz4
(默认)
⚡ 极快
中
通用首选
lzjb
快
中
旧算法,新代码不推荐
zstd
较快
较高
新代码推荐
zstd-fast
极快
中
替代 lz4
gzip
慢
高
归档、很少写
gzip-1
 ~ gzip-9
越慢越高
越高
罕见使用
zle
快
0%
仅零压缩(已是压缩数据)

1.2 启用压缩

# 设置压缩(默认 lz4)
$ zfs set compression=lz4 tank/data

# 高压缩比(用于冷数据)

$ zfs set compression=zstd-9 tank/archive

# 关闭

$ zfs set compression=off tank/data

1.3 压缩对性能的影响

常见误解:压缩 = CPU 开销 = 慢

事实:

  • • LZ4:CPU 极快(5+ GB/s),对现代 CPU 来说几乎免费
  • • 实际场景下 LZ4 经常提升性能(因为写更少的数据 → IO 更快)
  • • 数据库(已压缩的块)反而会被 LZ4 浪费一些 CPU

经验:

场景
推荐
文件服务器、文档、图片
lz4
视频(已是压缩格式)
off
 或 zle
文本、源码、配置
zstd
冷数据归档
gzip-9
 或 zstd-19
实时写入(OLTP)
lz4
(保险)
数据库
off
(数据已压缩)

1.4 看压缩效果

# 看压缩率
$ zfs get compressratio tank/data
  NAME         PROPERTY        VALUE  SOURCE
  tank/data    compressratio   1.84x  -

# 1.84x 表示压缩后体积是原始的 1/1.84

1.5 改压缩的注意事项

compression 可以随时切换,已存在的数据不会自动重压缩,只有新写入的数据会用新算法。

要重压缩已存在数据:

# 用 zfs send/recv + 新属性
$ zfs send tank/data@before | zfs recv -o compression=zstd tank/data-new
$ zfs destroy tank/data
$ zfs rename tank/data-new tank/data

二、加密(Encryption)

OpenZFS 2.0+ 原生支持加密。在 OpenZFS 之前,ZFS 上加密需要 LUKS(Linux)或 geli(FreeBSD)。

2.1 创建加密 dataset

# 创建时加密
$ zfs create -o encryption=aes-256-gcm -o keylocation=prompt -o keyformat=passphrase tank/encrypted
Enter passphrase: ********
Verify passphrase: ********

# 用密钥文件

$ dd if=/dev/urandom of=/etc/zfs/key-tank bs=32 count=1
$ chmod 0400 /etc/zfs/key-tank
$ zfs create -o encryption=aes-256-gcm \
             -o keylocation=file:///etc/zfs/key-tank \
             -o keyformat=raw \
             tank/encrypted

2.2 加密算法

# 查看支持的加密算法
$ zfs get -o name,property,value encryption

常用:

算法
性能
兼容性
aes-256-gcm
(推荐)
快 + 完整性校验
新
aes-256-ccm
快
旧版本兼容
aes-128-gcm
极快
性能敏感场景

2.3 加载 key

# 手动加载
$ zfs load-key tank/encrypted

# 用密钥文件

$ zfs load-key -L file:///etc/zfs/key-tank tank/encrypted

# 卸载 key(数据不可访问)

$ zfs unload-key tank/encrypted

2.4 自动加载

# 重启时自动从密钥文件加载
# /etc/zfs/zed.d/zed.rc 或 systemd service

$ zfs set keystatus=available tank/encrypted
$ zfs set keylocation=file:///etc/zfs/key-tank tank/encrypted

生产推荐:

  1. 1. 密钥文件放 TPM2 上(systemd-cryptenroll)
  2. 2. 或者用 网络密钥服务(HashiCorp Vault 等)
  3. 3. 永远不要在 keylocation=prompt 下重启(卡在启动)

2.5 加密与性能

  • • aes-256-gcm 用 AES-NI 硬件加速,性能损失 < 5%
  • • 没有 AES-NI 的旧 CPU 会慢 20~30%

2.6 加密的局限

  • • 加密不能替代备份!密钥丢失 → 数据全无
  • • 加密 dataset 不能直接 zfs send 给未加密 dataset(必须 rekey)
  • • 主密钥与子数据集密钥是层级关系
# 看加密层级
$ zfs get -r encryption,keylocation tank

三、配额(Quota)

ZFS 的配额有四组:

属性
范围
计快照吗?
quota
dataset + 它的所有快照
✅
refquota
dataset 自身(不计快照)
❌
reservation
pool 内预占(计快照)
✅
refreservation
pool 内预占(不计快照)
❌

3.1 硬上限:quota

# 给 alice 限制 10G(含快照)
$ zfs set quota=10G tank/home/alice

# 用户写入超过 10G 会失败

$ cp largefile /tank/home/alice/
cp
: cannot create regular file 'largefile': Disk quota exceeded

3.2 不算快照的硬上限:refquota

# alice 的"主数据"上限 10G,快照另算
$ zfs set refquota=10G tank/home/alice

3.3 预占空间:reservation

# 重要业务预留 50G
$ zfs set reservation=50G tank/db

# 其他 dataset 不会消耗这 50G

$ zfs list -o name,used,reservation,available tank

reservation 保证即使 pool 满,这个 dataset 也有空间。

3.4 看配额使用

# 看 dataset 的 used
$ zfs get used,quota,refquota,reservation tank/home/alice

# 多个 dataset 概览

$ zfs list -o name,used,quota,refquota,available,reservation

3.5 多用户配额管理

# 给每个用户建独立 dataset
$ zfs create -o quota=20G tank/home/alice
$ zfs create -o quota=30G tank/home/bob
$ zfs create -o quota=50G tank/home/charlie

# 一行命令看所有用户用量

$ zfs list -o name,used,quota -r tank/home

3.6 配额嵌套规则

  • • 子 dataset 配额独立于父
  • • 但子 dataset 实际可用空间受双重限制:自己 quota + 父 quota 剩余
$ zfs set quota=100G tank/home
$ zfs set quota=80G tank/home/alice
# tank/home/alice 最大能用 80G(即使 tank/home 还有 100G)

四、用户组配额(User/Group Quota)

ZFS 也支持 用户级和组级配额:

# 设置用户配额
$ zfs set userquota@alice=10G tank/home
$ zfs set userquota@bob=20G tank/home

# 设置组配额

$ zfs set groupquota@developers=100G tank/projects

# 查看

$ zfs userspace tank/home
$ zfs groupspace tank/projects

五、综合实战

场景:家用 NAS 部署

# 1. 创建主 pool
$ zpool create tank mirror /dev/sdb /dev/sdc

# 2. 顶层结构

$ zfs create -o compression=lz4 -o atime=off tank/data
$ zfs create -o compression=lz4 -o recordsize=1M tank/media
$ zfs create -o compression=zstd tank/documents
$ zfs create -o compression=off tank/database

# 3. 用户目录

$ zfs create -o quota=100G -o compression=lz4 tank/home
$ zfs create -o quota=50G tank/home/alice
$ zfs create -o quota=100G tank/home/bob

# 4. 加密私密数据

$ zfs create -o encryption=aes-256-gcm \
             -o keylocation=file:///etc/zfs/key-private \
             -o keyformat=raw \
             tank/private

# 5. 快照策略(用 sanoid / zfs-auto-snapshot)

$ zfs create -o canmount=off tank/snapshots

场景:企业数据库

# 主数据:高性能
$ zfs create -o compression=off \
             -o recordsize=16K \
             -o primarycache=metadata \
             -o logbias=throughput \
             -o mountpoint=/var/lib/pgsql \
             tank/db

# WAL 日志:低延迟(如果用 SLOG)

# (在 pool 上加 log vdev)


# 备份

$ zfs create -o compression=zstd \
             -o recordsize=1M \
             -o mountpoint=/backup \
             tank/backup

六、常见坑

1. compression 影响 zfs send/recv

压缩后数据传给未压缩 dataset 时,会自动重压缩。zfs send 会有 overhead。

2. encryption 不能事后加

# 创建时加密
$ zfs create -o encryption=aes-256-gcm ... tank/secure

# 已有 dataset 加加密?需要 zfs send/recv:

$ zfs send tank/data@before | zfs recv -o encryption=aes-256-gcm tank/data-secure

3. quota + snapshot 的陷阱

quota=10G + 频繁快照 → 用户主数据无法超过 10G(包括快照)。

用 refquota=10G 才能允许"主数据 10G + 任意多快照"。

4. reservation 的滥用

reservation 会"预占"空间,没有真正使用也会消耗 pool 容量。不要无脑给所有 dataset 配 reservation。

七、本篇小结

特性
命令
关键点
压缩
zfs set compression=lz4 tank/data
LZ4 几乎免费
加密
zfs create -o encryption=aes-256-gcm ...
密钥丢失 = 数据丢失
硬配额
zfs set quota=10G tank/data
含快照
ref 配额
zfs set refquota=10G tank/data
不含快照
预占
zfs set reservation=10G tank/data
防止数据被挤

经验口诀:

  • • 压缩:lz4 一把梭,冷数据 zstd-9 压
  • • 加密:必须配密钥管理,生产别用 prompt
  • • 配额:多用户用 refquota,别用 quota
  • • 预占:重要业务 reservation,普通业务不加

最新文章

随机文章