我经常用 dd 备份数据,大概是从 SSD 上 dd 整个硬盘或者分区的 block device 到机械硬盘(读入端的性能为写出端的 10+倍),并且经过 pigz 压缩 (dd if=/sda bs=xx | pigz >xxxx.img.gz
类似这样)
bs 我经常喜欢设置成较大的值,比如 512M ,1024M ,因为以前似乎印象中设置一个太小的 bs 比如 KB 级的或者 1M 性能会比较差,但是似乎发现一个现象:硬盘不会连续读写,假如设置成 1024M ,是不是 dd 先从源盘读满 1G 的数据,然后再往 pipe 那边扔,等待 pipe 写完之后,再读下一个 1G ?如果是这样的话,就影响吞吐量了,等于有某个时间段管道的某一端是空闲状态。
还有一个现象似乎可以佐证这一点,pigz 能把我的 CPU 跑满,但是看 CPU 占用率的曲线,每隔几秒(大概 10 秒左右?)会有一个 1~2s 的凹槽( CPU 使用率下降,降到 0%),这似乎是在等待读盘/写盘。
我想的是,既然入比出的性能高很多,那如何让 buffer 始终处于满的状态,让输出端( pigz 和写出设备)一直有东西吃,而不是等它们吃完再读入下一个 block ,然后这过程中它们没东西可吃。
总之,如何优化能提高整个 dd 的性能,或者有什么更好的方案吗?
另外我刚在 stackoverflow 看到另一种压缩方案,用 squashfs 流式压缩:
sudo mksquashfs empty-dir squash.img -p 'sda_backup.img f 444 root root dd if=/dev/sda1 status=progress bs=512M'
这样好处是以后 dd 出来的镜像方便挂载(如果直接对 block device 做 gzip 以后确实不太方便使用),目前还没测这个方案性能如何,不知道各位有什么高见?以及现在 squashfs 有多种压缩算法可以选,在这种场景下哪种效能最好呢?
1
billlee 286 天前 via Android
bs 一般设置成 MB 级就不影响性能了。
备份文件用 tar 也好,用 squashfs 也好,都好过用 dd, 因为 sdd 不理解文件系统,会把无意义的空白空间也复制一份。 压缩算法用 zstd 就好了,调压缩级别就可以适合各种不同场景。 |
2
liyafe1997 OP @billlee 不是备份文件,我的目的就是要备份整个 block device
|
3
GrayXu 286 天前
你的发现是对的,dd 同时只操作一个 blocksize ,pipe 本身并没有这么大的 buffer ,dd 等 pipe 拿完所有源数据后再去读新的源数据。但你这个场景下是写入盘 io bound ,提升 dd 的性能(比如说持有两个或者环形 buffer )对整体性能影响不会很大。
但其实平衡 pipe 两端吞吐倒是一个很多讨论过的话题,比如包括 pigz 在内的压缩软件可以动态压缩率来匹配 pipe 的速率 |
4
514146235 286 天前
一般备份这种 block 设备,我会用 qemu-img 转成 qcow2 。
qcow2 支持压缩,也支持 mount 操作。 |
5
liyafe1997 OP @GrayXu 感谢!
我感觉 io bound 不完全在写入盘,主要在 pigz (因为 CPU 所有核能跑 100%?),以及等待读盘的时候浪费的时间。因为从 iotop 和写入盘的硬盘灯闪烁情况来看,写入盘并不是一直跑满的。 |
6
liyafe1997 OP @514146235 感谢!好主意!回头试试性能如何。
|
7
deorth 286 天前 via Android
换 btrfs/zfs ,用文件系统的 send 功能
|
8
liyafe1997 OP @deorth 虽然但是请审题,我说的是备份 block device ,没说备份文件系统
|
9
deorth 286 天前 via Android
@liyafe1997 XY 问题
|