我正在通过点对点 T1 线路发送增量 ZFS 快照,现在的情况是,在下一次备份开始之前,一天的快照几乎无法通过线路传输。我们的发送/接收命令是:
zfs send -i tank/vm@2009-10-10 tank/vm@2009-10-12 | bzip2 -c | \
ssh offsite-backup "bzcat | zfs recv -F tank/vm"
我有足够的 CPU 周期可用。是否有更好的压缩算法或替代方法可用于传输更少的数据?
答案1
听起来你已经尝试了所有最好的压缩机制,但仍然受到生产线速度的限制。假设运行更快的生产线是不可能的,你有没有考虑过降低备份运行频率,以便有更多时间运行?
除此之外,是否有某种方法可以减少写入的数据量?如果不知道您的应用程序堆栈,很难说该怎么做,但只需做一些事情,例如确保应用程序覆盖现有文件而不是创建新文件,可能会有所帮助。并确保您没有保存不需要的临时/缓存文件的备份。
答案2
自从这个问题发布以来,情况发生了变化:
1:ZFS 现在支持压缩复制,只需在 zfs send 命令中添加 -c 标志,磁盘上压缩的块在通过管道传递到另一端时仍保持压缩状态。可能仍需要获得更多压缩,因为 ZFS 中的默认压缩是 lz4
2:在这种情况下,最好使用的压缩器是 zstd (ZStandard),它现在具有“自适应”模式,可以根据 zfs send 和 zfs recv 之间的链接速度更改压缩级别(在支持的 19+ 级别之间,加上新的更高速 zstd-fast 级别)。它会尽可能地压缩,同时将等待从管道中输出的数据队列保持在最低限度。如果您的链接速度很快,它就不会浪费时间进一步压缩数据,如果您的链接速度很慢,它将继续努力进一步压缩数据并最终为您节省时间。它还支持线程压缩,因此我可以利用多个核心,而 gzip 和 bzip 则不能,除了 pigzip 等特殊版本。
答案3
这是我在做和你完全相同的事情时学到的东西。我建议使用 mbuffer。在我的环境中测试时,它只在接收端有帮助,如果没有它,发送速度就会变慢,而接收速度会赶上来。
一些例子: http://everycity.co.uk/alasdair/2010/07/using-mbuffer-to-speed-up-slow-zfs-send-zfs-receive/
带有选项和语法的主页 http://www.maier-komor.de/mbuffer.html
来自我的复制脚本的发送命令:
zfs send -i tank/pool@oldsnap tank/pool@newsnap | ssh -c arcfour remotehostip "mbuffer -s 128k -m 1G | zfs receive -F tank/pool"
这会在远程主机上运行 mbuffer 作为接收缓冲区,以便尽可能快地发送。我运行了一条 20mbit 的线路,发现在发送端使用 mbuffer 也没有帮助,而且我的主要 zfs 盒正在使用其所有内存作为缓存,因此即使给 mbuffer 1g 也需要我减少一些缓存大小。
此外,这实际上不是我的专业领域,我认为最好让 ssh 进行压缩。在您的示例中,我认为您使用的是 bzip,然后使用 ssh,默认情况下使用压缩,因此 SSH 正在尝试压缩压缩流。我最终使用 arcfour 作为密码,因为它对 CPU 的占用最低,这对我来说很重要。使用其他密码可能会获得更好的结果,但我绝对建议让 SSH 进行压缩(或者如果您确实想使用它不支持的压缩,请关闭 ssh 压缩)。
真正有趣的是,在本地主机上发送和接收时使用 mbuffer 也会加快速度:
zfs send tank/pool@snapshot | mbuffer -s 128k -m 4G -o - | zfs receive -F tank2/pool
我发现 4g 对于本地主机传输来说似乎是最佳选择。这表明 zfs 发送/接收并不喜欢延迟或流中的任何其他暂停,这样才能发挥最佳作用。
这只是我的经验,希望这能有所帮助。我花了一段时间才弄清楚这一切。
答案4
这是对您的具体问题的回答:
你可以试试压缩,但它的工作方式与 compress/bzip/gzip 略有不同:
rzip 需要读取整个文件,因此无法在管道中运行。这将大大增加您的本地存储要求,并且您将无法运行备份并通过单个管道将备份发送出去。也就是说,生成的文件,至少根据这测试,要小得多。
如果您的资源限制是您的管道,那么您无论如何都会全天候运行备份,因此您需要不断复制快照并希望您能跟上。
您的新命令将是:
remotedir=/big/filesystem/on/remote/machine/
while
snaploc=/some/big/filesystem/
now=$(date +%s)
snap=snapshot.$now.zfssnap
test -f $snaploc/$snap
do
sleep 1
done
zfs send -i tank/vm@2009-10-10 tank/vm@2009-10-12 > $snaploc/$snap &&
rzip $snaploc/$snap &&
ssh offsite-backup "
cat > $remotedir/$snap.rzip &&
rzip -d $remotedir/$snap.rzip &&
zfs recv -F tank/vm < $remotedir/$snap &&
rm $remotedir/$snap " < $snaploc/$snap &&
rm $snaploc/$snap
您将需要更好的错误更正,并且需要考虑使用类似 rsync 之类的程序来传输压缩文件,这样如果传输在中途失败,您可以从上次中断的地方继续。