Restic: 实施压缩

创建于 2014-11-15  ·  167评论  ·  资料来源: restic/restic

此问题是一个跟踪问题,用于跟踪与实施压缩的请求相关的讨论和其他问题/PR。

以下问题/PR 与此主题相关(因此可能会被关闭以支持此主题):

  • 公关#2441
backend backup feature suggestion tracking

最有用的评论

我认为关于添加压缩​​的问题已经有足够的讨论。 我可以看到这是一个备受期待的功能。 在完成新的归档程序代码后,我将接下来解决这个问题(参见 #1494)。

请不要再添加任何评论,谢谢!

所有167条评论

在实现这一点时,添加基准测试,尤其是使用 -benchmem 和 benchcmp 查看内存使用情况!

lz4,lzo,lzma,空。 bz2 比较慢。

snappy 速度快,压缩适中

如果压缩是按块进行的,则应注意不要让静态备份对水印/指纹攻击开放。

这基本上与我们讨论的与 CDC 重复数据删除过程指纹相关的问题相同:
使用“原始”CDC,如果攻击者可以观察到单个块的大小,则可以验证备份中存在“已知明文”文件,方法是在文件上并行使用 CDC 并比较生成的块和单个块的数量。块长度。
如前所述,这可以通过使用秘密值对 CDC 算法进行加盐来稍微缓解,就像在阁楼中所做的那样。

使用盐渍 CDC,我假设在将有问题的文件拆分为多个块后,每个单独的块都会发生压缩。 Restic 块在 512 KB 到 8 MB 的范围内(但不是均匀分布的 - 对吧?)。

  • 攻击者知道 CDC 算法使用秘密盐,因此攻击者会生成一系列块,包括文件的前 512 KB 到 8 MB,每个有效块长度一个。 攻击者还能够确定压缩块的长度。
  • 然后攻击者使用压缩算法压缩该块。
  • 攻击者将结果块的长度与静态备份集中的第一个块进行比较。
  • 如果找到匹配的块长度,则攻击者对下一个块、下一个块、下一个块、……和下一个块重复练习。
  • 我相信,对于足够大的文件,并考虑到 CDC 算法“偏向”(缺乏更好的词)生成大约 1 MB 的块这一事实,这足以确定某个大块文件存在于备份中。

一如既往,一种偏执且高度不科学的意识流。

想法?

有趣的。 我不明白您描述的攻击如何取决于是否使用压缩,是否有必要? 这种攻击在压缩和不压缩的情况下都有效吗?

目前我正在考虑如何实现#56。 您对将几个 blob 捆绑到一个文件中有何看法?

CDC 实施的确切工作原理对我来说有点不清楚:

  • 您是在精确的字节边界上拆分还是将 512 KB - 8 MB 的块“四舍五入”为某物的倍数?
  • (真正的问题是:是否有 (15 * 512 * 1024) / (16 因为 AES-CTR) 可能的块大小,或者更少?)
  • 我也很好奇在给定足够多的已知文件块的情况下重建种子的可行性 - 我猜不是很可行?

回答你的第一个问题:
使用种子 CDC,“指纹”取决于(内容 + 秘密种子),但不同之处在于,在分块之后进行压缩时,假设您可以区分各个块,您就有了指纹/水印(某个块的压缩率)完全取决于内容,在这种情况下是已知的明文。

例子:
如果水印文件包含 64 MB(8-128 个块)的 "AAAA" ,然后是 64 MB 的 "ABCABCABCABC",然后是 64 MB 的随机数据,那么前 16-256 个块将非常小(因为这些序列压缩得很好,其中 8-128 个块的压缩效果相当差)。
攻击者还可以反向工作,从最后一个(第 24 - 384 个)块开始并压缩 512KB-8MB,直到攻击者找到一个可以压缩到完全相同的块大小的大小。 一旦找到,原始明文的“下一个”512KB-8MB 被压缩,以找出哪个长度压缩到倒数第二个块的长度(第 23 - 383 个),依此类推,直到攻击者遇到作为“AAAA”字符串结果的小块。
这并不能让对手肯定地确认带水印的文件存储在备份中,但我认为,如果有足够的数据,从统计上讲,它可以创建非常清晰的结果。

我看到了一些潜在的解决方案,也许你有更多的想法:

  • 允许关闭某些目录的压缩和/或重复数据删除(可能是最容易实现的)
  • 随机压缩字典(还没有真正考虑过这个,但这似乎是一个有趣的想法)
  • 防止攻击者了解单个压缩块的长度,例如通过填充(可能非常昂贵)或将几个小块捆绑在一起并填充剩余的(更复杂,但更有效)

谢谢你的解释,我现在明白你的情况了。

在 restic 中可能没有关闭重复数据删除的选项,因为鉴于程序的当前结构,这真的很难做到,restic 是围绕 CDC 构建的。 添加压缩支持目前的优先级较低,而不是 alpha 版本的目标。

你的第三个想法将在#56(将多个块捆绑在一起)中实现,我现在正在研究这个。 我可能会向doc/Design.md添加更多关于分块器如何工作的文档。

再次感谢您提出这个场景!

我不确定我是否遵循@cfcs - 压缩大小是不是就像一个非常糟糕的散列? 给定压缩文件大小,生成该文件大小的可能输入的数量是无穷无尽的。 但可能我只是不明白。

反正。 我只是想无耻地向您指出我制作的经过修改的 deflate/gzip 库。 您可能会感兴趣,我采用了恒定时间压缩模式,它可以对任何数据实现 ~150MB/s/核心吞吐量,这使得它在备份场景中几乎不可见。 还有一个并行的 gzip 包,可以在多个内核上 gzip 压缩更大的文件。

@klauspost :请记住,我们正在讨论单个而不是文件的压缩大小。 平均块大小为 1MB 的 100GB 文件将有大约 100 x 1024 个块,每个块都会泄漏文件的某个部分的压缩率。 这会导致比单个压缩文件的大小更多的统计数据,即使 CDC 盐(以及块的确切对齐边界)未知,也可以将已知明文与压缩和分块文件进行比较。

不过,151 已合并,所以现在这可能不是问题。

我认为,考虑到我们有种子分块器(通过自定义的 per-repo 多项式)和 blob 打包(攻击者看不到单个块,但只能看到块组和块的数量),我认为这种信息泄漏只是次要的在一个组中,通过明文标题长度)。 我认为出于速度或隐私问题而完全禁用压缩是一个好主意,但默认值(实施时)可能是“启用”。

@klauspost我一定会看看你的图书馆,谢谢你指出!

我同意你上面的观察, @fd0 ,但我想补充一点,我认为可能有另一个重要的用例来选择性地禁用特定目标文件/目录/设备的压缩,例如在备份多媒体格式时压缩的、具有高熵的二进制文件不能很好地压缩,或者在对加密卷进行增量备份时。

@cfcs - 好的 - 从你的文字中我认为你暗示你可以推断出数据。 因此,要对此产生任何影响,您将需要原始数据,这种情况很少见。

关于不可压缩文件,这就是我提到我放入 deflate 的恒定时间 Huffman only 模式的原因,顾名思义,它以相同的速度压缩所有数据,并自动回退到存储未压缩的数据。 因此,如果内容被压缩,则最大开销约为 0.04%。

这里有一些基准。 最适用于备份的可能是“中等压缩”,它是 10GB 混合内容 - 可压缩和不可压缩。

仅默认为 gzip Huffman 并可以选择指定更多 CPU 消耗的压缩级别可能是有意义的。

在我看来,为数据和树对象分别有选择地启用/禁用压缩可能很有价值。 特别是大树对象应该压缩得很好。

我查看了一些插入压缩有意义的“点”。 最透明和通用的地方将是存储库和后端之间的某个地方。

我简要地查看了修改Repository.EncryptRepository.DecryptTo ,但我们没有类型,并且不同的大小会使事情变得一团糟。

我的提议是将压缩和 _encryption_ 实现为“后端”,它们都写入底层后端。 这将使压缩和加密对存储库透明。

我们需要分离加密的原因是加密数据不会压缩(您可能知道)。

存储库。存储库

压缩算法只能在初始化时设置,并且假定除配置外的所有内容都使用该算法进行压缩。

存储库配置文件

无法压缩配置。 我们添加一个字符串,指示用于所有内容的解压缩类型。 空 ("") 未压缩。 否则它是所使用的压缩库的包名的最后一部分。

请注意,可以在每次运行/类型之间更改压缩级别。 有一个 repo 没有问题,其中一些快照/类型是 deflate 级别 0(存储)和一些级别 9(最佳压缩) - 只要解压缩器是相同的。

type Config struct {
    Version           uint        `json:"version"`
    ID                string      `json:"id"`
    ChunkerPolynomial chunker.Pol `json:"chunker_polynomial"`
+   Compression       string
}

添加压缩作为创建参数:

-func CreateConfig(r JSONUnpackedSaver) (Config, error) {
+func CreateConfig(r JSONUnpackedSaver, compression string) (Config, error) {

在 LoadConfig/CreateConfig 之后替换后端。 这是它的外观示例:

// SearchKey finds a key with the supplied password, afterwards the config is
// read and parsed.
func (r *Repository) SearchKey(password string) error {
    key, err := SearchKey(r, password)
    if err != nil {
        return err
    }

-   r.key = key.master
-   r.keyName = key.Name()
    r.Config, err = LoadConfig(r)
+   r.be, err = FindCompressor(r.Config.Compression, Encryption(key, r.be))
    return err
}

压缩实现

压缩器可以对某些类型实现选择性/可调压缩。 由于它被视为“后端”,因此压缩后的大小永远不会对存储库可见。 压缩器必须具有所有设置。

问题

帮助/修复:“打包”文件似乎是一个问题,因为加密在每个文件处重新启动。 如果加密移动到后端,加密将针对整个 blob,而不是针对每个文件。 我认为这是一个问题,我没有好的解决方案。

TODO:找到一些将参数/配置发送到压缩器的好方法。 第一次实现不需要。

TODO:我们关心磁盘大小吗? 如果上面实现了,存储库将不知道它。

感谢您分享您的想法,这是我的:

我认为压缩和加密需要相互结合,我会考虑这个。 目前,我不喜欢将压缩/加密层彼此完全抽象的想法。 正如您已经描述的那样,我们必须注意不要做愚蠢的事情,例如压缩加密数据。 此外,为了速度和/或安全问题,我们应该提供禁用压缩的选项。 关于加密:稍后可能会有非加密模式用于 restic,但现在加密不是可选的。

此外,打包文件本身就是一个抽象级别(例如,可以重新打包内容),这不适用于抽象加密。

我认为Repository对象太复杂了,在解决这个问题之前需要进行大修。 我现在真的没有准备好的计划。

关于不同的压缩算法和选项:我认为我们应该为数据选择一个算法(包括一组参数),也许应该为压缩 JSON 树结构选择第二个算法,但仅此而已。 对于所有可选的东西(例如不同的可配置压缩算法和/或参数),我想有一个合理的考虑,权衡增加的复杂性和额外代码量的好处。

请不要误会我的意思,我想向restic添加功能,但特别是对于修改磁盘格式的更改,我需要非常好的论据。 在添加压缩的一般情况下,我可以看到好处,但磁盘格式的复杂性和更改必须是可管理的。

您将需要不同的算法和参数(不仅仅是每个 repo,甚至每个备份运行),没有“最适合每个用例”的压缩。

举个实际的例子:

我从我的公司服务器备份到我家里的备份服务器。 dsl 上行链路约 700kbit/s。
为此,我想要最好的压缩(如 lzma + 高级别)。 cpu 在晚上有很多空闲时间,等待糟糕的连接接受下一个数据包。

当我在家时,我也将笔记本电脑备份到同一个存储库,在那里我有一个无线“N”连接。 当然,我不想通过在那里使用 lzma + high level 来减慢连接速度,而是我想要一些非常快且根本不会减慢速度的东西 - 比如 lz4。 我仍然想要压缩,不使用 lz4 会占用大约 2 倍的空间。

我想要lzma在这里但lz4在那里(改写:-))

恕我直言,这就是所有自行车棚……让我们选择一个合理的默认值,不要暴露太多配置,这只会带来很多复杂性,但收益甚微,恕我直言。

我认为Repository对象太复杂了,在解决这个问题之前需要进行大修。 我现在真的没有准备好的计划。

很公平。 我开始浏览repository.go 并找到了所有可以插入压缩/解压缩步骤的地方,而增加的复杂性并不是一件好事。 通过将其实现为backend接口,您可以突然取消所有加密,并使其成为后端链的一部分。 您可以进行通用测试以确保后端部分的对称性,包括压缩和加密。

关于加密:稍后可能会有非加密模式用于 restic,但现在加密不是可选的。

这就是后端链接使它如此出色的原因。 您只需省略加密(或创建一个直通后端),它就可以无缝工作。

在添加压缩的一般情况下,我可以看到好处,但磁盘格式的复杂性和更改必须是可管理的。

这是我能看到的最少侵入性的方式。 如果有办法解决“打包文件”问题,未压缩的存储库仍然完全向后兼容; 老客户将能够像以前一样对它们与新客户一起操作。

压缩的 repos 显然不会,但只有当 repo 被压缩时,我们才能将version更改if cfg.Version > RepoVersion { ,但这没有兼容性问题。

恕我直言,这就是所有自行车棚……让我们选择一个合理的默认值,不要暴露太多配置,这只会带来很多复杂性,但收益甚微,恕我直言。

同意。 大多数算法(lzma/deflate)在相同的解压格式中具有很大的灵活性。

为了测试可压缩性,有 DataSmoke: https :

此外,pcompress 选择了一系列不错的压缩算法: https :

壁球压缩抽象库有一个很好的算法列表和一个基准: https :

这里有一个文本压缩基准: http :

简单的方法是始终在crypto/crypto.go加密/解密函数中进行过滤。

gzip-compression-v1.patch.txt它是可以应用于头部的概念验证差异。

感谢您尝试@mappu ,但在实施之前,我们需要就策略达成一致。 开放性问题(来自我的头脑)至少是:

  • 什么时候应用压缩? (数据?元数据/JSON?)
  • 我们应该实现哪种算法? 我认为@klauspost对我们有一些建议:)
  • 我们如何在不破坏客户端的情况下将其存储在存储库中?

什么时候应用压缩? (数据?元数据/JSON?)

数据显然是的。
元数据/json,也许它毫无意义,但我认为它可以帮助大型元数据文件,因为 JSON 数据主要是 ASCII 并且会受益于算术编码/霍夫曼阶段(gzip 有)。

由于数据/元数据始终是加密的,我认为添加到加密/解密例程是一种捕获所有用法的简单方法,没有这个“我开始查看 repository.go 并找到了您将插入压缩/解压缩步骤的所有位置,增加的复杂性并不是一件好事。” 来自@klauspost
此外,由于 blob 存储名为 hash(plaintext) 而不是 hash(ciphertext) {{显然是 dedup 所必需的,否则随机 IV 会破坏 dedup}},因此在不损害 dedup 的情况下这样做是安全的。

我们应该实现哪种算法? 我认为@klauspost对我们有一些建议:)

不关心虽然我同意@ThomasWaldmann它应该是可配置的。 至少对于--best--fast用例。

我建议 gzip 只是因为它是纯粹的 go,它在 golang 标准库中,并且受到谷歌的性能关注。 xz 是强得多的慢压缩。 lz4 的快速压缩要弱得多。 gzip 是平衡的并且易于调整,即使它不会达到任何一个极端。

我们如何在不破坏客户端的情况下将其存储在存储库中?

存储库应该只在一个方向兼容。 我觉得如果旧的restic不能读新的repo也没关系,只要新的restic可以读旧的repo。

也许您可以在 MAC 之后添加标签字节。 不存在 - 没有压缩(旧的休息)。 然后,字节还可以指示使用了哪种压缩算法。 0x01 gzip 0x02 lz4 左右。

似乎存在与阁楼相同(或更糟)的问题(当前格式中没有使用压缩类型/参数字节)。

在阁楼 (borg) 中,我很幸运,因为旧格式仅支持 gzip,并且可以从前 2 个字节中检测到 gzip 格式。 所以我保留了没有额外字节的 gzip(与旧的 repos 相同)并添加了类型字节(用于无压缩或其他压缩),这些字节与前 2 个 gzip 字节永远不会有歧义。

显然,如果旧格式只是原始的任意数据,您就不能这样做。

不可以。但是还有其他方式来表示此信息。 例如,如果加密块开头的 IV 恰好是“新格式”(1 :: 2^xyz 碰撞机会),则解析为新格式。 它不是那么“干净”,但我认为在实践中很好。

正如它在 nmdc 锁握手中使用 EXTENDEDPROTOCOL 完成的那样。

哦不,我们不会做这样丑陋的事情,我们也不需要。 如果我们决定实现这一点,包文件为每个 blob 都有一个字段type 。 这是一个uint8 ,目前只为datatree ,我们可以轻松添加compressed datacompressed treehttps://github.com/restic/restic/blob/master/doc/Design.md#pack -format

目前,我不认为此功能具有高优先级。

将新的 blob 类型添加到包格式可以进行数据压缩,但不提供索引压缩。 由于索引可以变大,而且JSON有很好的压缩率,而且索引可能没有本地缓存​​,所以我认为压缩索引也很重要。

new-restic 与 old-repo 一起使用很重要,以便轻松升级。 它应该是无缝的(首选)或具有restic upgrade-repo工具(非首选)。

那么这个怎么样?

所有restic命令已经先加载+解密config

  • 如果第一个config字节是{ (它是 json 对象的第一个字节),那么整个 repo 是旧格式(未压缩)
  • 否则,第一个config字节是 {tag byte} 并且整个 repo 是新格式。 解密数据开头的 {tag byte} 表示压缩格式。 示例 0x00 未压缩 0x01 gzip

谢谢你的提议。 我认为没有必要压缩配置,因为这只是一个非常小的文件,并且可以始终保持 JSON 格式,我们可以根据需要添加字段,例如是否压缩索引文件。

我昨天在寻找一个好的备份解决方案时发现了 restic。 我的主要担忧之一是限制我的数据占用多少空间。 特别是如果我将数据发送到我付费的地方,比如 S3。 Dedup 肯定会有所帮助,但我预计压缩将成为备份解决方案的重要组成部分......在https://github.com/restic/restic/issues/21#issuecomment -185920429 你( @fd0 )说这个是低优先级,你能解释一下为什么吗? 有我可以在任何地方查看的路线图吗?

另外,+1。 ;)

目前我正在删除旧的备份数据(#518)。 同时获得正确和安全的压缩并不容易,我需要更多地考虑如何将其集成到存储库格式中。

我们将实施压缩(毕竟这个问题是关于什么的),它还没有完成。 restic 是一个相当新的项目,请耐心等待:)

此问题与#116 相关。 由于加密,我们无法使用其他工具压缩备份,不是吗? 在压缩和使加密可选之间有什么优先级? (我打赌先压缩!)
_很抱歉对此施加压力,您说得对,必须小心存储库格式!_

这很容易回答:将首先实施压缩。

这是因为我目前没有任何让加密成为可选的计划。 我认为也很难做到正确。 我们需要考虑完整性,因为这不应该是可选的,但(至少目前)它与加密紧密耦合。

@fd0感谢您回答我的问题。 让我希望我的开发技能能够帮助解决这个问题。 但是我几乎没有接触过 go,而我的其他大多数 xp 都在 webdev 或 sysadmin 脚本中。

我完全同意你需要确保压缩是“正确和安全的”。 如果那会耽误事情,那就这样吧。 :微笑:

我在这里在 restic 中实现了 snappy 压缩: https :

这只是一个提议。 基本上,我为包中的 blob 添加了快速压缩/解压缩,并使用了一些 blob 类型字节作为标记。 我还在包索引中添加了一个字段:PLength(明文长度),在此之前未存储但计算为“bloblength - crypto.Extension”。

我注意到,对于我的一些备份,它不仅占用更少的空间,而且运行速度更快(处理的数据更少)。

所有restic测试都通过。 它可以在以前的 restic 存储库上工作,但普通的 restic(master 的)无法处理新的 blob。

我使用了 snappy (https://github.com/golang/snappy),因为我认为它对@fd0 的速度目标的影响较小。

为 master 上的压缩着陆增加了 50 美元的赏金

Bountysource

如上所述,应该有一种自动化的、不可配置的方式来避免尝试压缩不可压缩的文件,如媒体、加密或已经压缩的文件。 某些容器格式(如 PDF)的内容有时可压缩,有时不可压缩,从而加剧了该问题。

最简单的方法是使用一些透明地处理此问题的算法,例如@klauspost 在第一条评论中提到的恒定时间压缩模式。

否则将需要文件类型列表:一个永远不会被压缩的黑名单,一个总是被压缩的白名单,一个尝试压缩文件的一小部分的其余部分的启发式方法,如果大小没有减少则放弃超过给定的阈值。

不确定这在块上的映射效果如何,而不是在文件级别。

我反对将它添加到加密/解密通行证中。
我们不想混合不同类型的数据,因为其中一些数据可能是可预测的,并且由此产生的包/blob 长度可能会泄露有关不可预测/秘密数据的明文的信息。
我认为它应该是每个文件,即使这使它“不太好”。 然而,这样做的好处是不必对成吨的包文件(每个文件中只有一个 blob 很重要)进行杂散解压缩来读取文件。

@teknico

如上所述,应该有一种自动化的、不可配置的方式来避免尝试压缩不可压缩的文件,如媒体、加密或已经压缩的文件。

我修改后的 deflate 包实现了跳过已经压缩的数据,并且以每核约 250MB/s 的速率执行此操作。 Go 1.7 deflate 仅支持最快的压缩级别。

Snappy 和 LZ4 支持类似的跳过功能。

最简单的方法是使用一些透明地处理此问题的算法,例如恒定时间压缩模式。

它绝对应该是一个选择。 在 Go 1.7(现在称为 HuffmanOnly 和我的等效版本)中,无论输入如何,此模式都支持每核约 200MB/s。 然而,与“最佳速度”相比,压缩受到严重阻碍,“最佳速度”通常以 80 MB/s/核的速度运行。

@cfcs

我认为它应该是每个文件,即使这使它“不太好”。

一般我同意。 我将不得不阅读restic。 每个包大小的二进制大小是否可用非加密?

@klauspost看起来您的一些改进已合并到 Go 1.7 DEFLATE“BestSpeed”模式中,对吗? 也许这将是一个合理的默认值。

使用 DEFLATE 格式的优点是有许多不同的压缩器可以产生兼容的比特流,因此它对解压缩器是完全透明的。

由于 restic 的工作原理(将文件拆分为 blob,之后仅处理 blob),添加压缩的最简单方法是在 blob 级别上。 也许我们可以添加一些启发式方法来决定是否应该压缩 blob,但这可以是第二步。

Blob 被组合成包文件,然后存储在存储库中。 包文件包含许多(单独加密的)blob,后跟一个(加密的)标头,后跟(未加密的)标头长度。 没有解密密钥的攻击者只能看到密文、头部长度和文件长度。 因此,基于包文件的大小和标头长度,攻击者可以计算特定包文件中 blob 的平均大小,仅此而已。 索引文件还包含所有数据(大小、加密大小,然后可能是压缩大小),但这些也是加密的。 我认为这里没有任何风险。

“可压缩”测试试探法既容易出错,又相当昂贵。 我估计很难超过 200 MB/s/核心 - 这是 AMD64 上的dedup 包中的 order 1 查找速度。

此外,这在很大程度上取决于所使用的压缩机。 Snappy 将无法压缩随机 base 64 数据,但例如 deflate 可以,所以我会将这部分留给压缩器 - 我们为 Snappy、LZ4 和 deflate 内置了它。

@fd0抱歉,我的意思是每个 blob,而不是每个文件。
除非我们选择轻量级算法,否则压缩会占用大量 CPU,很可能会成为瓶颈(仅次于 AES,未来有望由 AES-NI 解决)。

@fd0 - 我做了一个快速的“可压缩性估计器”: https :

borg 1.1 将有 2 个“压缩决定器”:

  1. 根据路径模式匹配决定每个文件( *.zip*.mp3/htdocs/photos/* ,...)
  2. 如果未决定,则按块决定,使用 lz4 作为可压缩性测试 - 如果压缩,则使用所需的压缩(lz4、zlib、lzma)再次压缩,如果没有,则不要压缩。

@klauspost嗯,这个测试在我的机器上还不错:

BenchmarkCompressibility-4           100      10345544 ns/op     810.84 MB/s

基准代码在这里: https :

Lz4 没有熵编码器,所以它会误报很多次
大概?

我认为我们需要三种模式(全局):

  • 使用线性时间压缩器压缩所有数据 blob(默认)
  • 无压缩
  • 最大压缩(适用于具有大量 CPU 能力但带宽很小的人)

我想总是压缩树对象 (JSON),所以我们应该为 ASCII 文本选择合适的算法。

否则我将与@viric合作构建一个原型,然后我们可以推理一个具体的实现。

想法?

@klauspost嗯,这个测试在我的机器上还不错

我总是忘记新的 Go 编译器可以做得多么糟糕。 至少是我预期的两倍。

我认为我们需要三种模式(全局):

尽管有更高效的压缩器(主要是 LZMA),但 Deflate 在这三个方面都做得很好。 没有压缩的放气当然是不需要的,但当然速度快且开销最小,所以可以使用通用的放气方法,以后可以指定其他方法。

我已经开始研究另一种加速,它在速度和压缩方面都介于 1 级和霍夫曼之间。 但是,目前时间有点宝贵,我仍然需要测试Go 1.7的一些最终

如果你只想要一个单一的压缩算法,你应该看看新的竞争者 zstd: https :

它由与 lz4 相同的开发人员开发,具有比 gzip 更好的压缩率,同时速度快 3 倍以上: https ://code.facebook.com/posts/1658392934479273/smaller-and-faster-data-compression-with

zstd 看起来很有前途,尽管我无法在 Go 中找到实现。

官方网站http://facebook.github.io/zstd/#other -languages 链接到此 Go 实现: https :

或者你的意思是纯 Go 实现?

是的,意味着一个纯粹的 Go 实现。 目前,restic 不依赖于任何 C 代码,理想情况下我想保持这种方式。

是否有任何实施压缩的预测?

实现压缩取决于更改存储库格式(计划/想法在 #628 中),这需要非常小心。 所以,不,添加压缩时没有确定的日期;)

有什么我们可以做或贡献的东西来帮助实现这一目标吗?

我不这么认为,抱歉:wink:,它只是需要时间。

所以我想我可以再使用一次#790 的测试台。 在我的 restic 构建中,我删除了所有加密,然后再次进行了完整备份。 它的大小与加密大小相同——这并不奇怪。 但后来我压缩了存储库,我发现的是:

35G backup-unencrypted
6.4G    backup-unencrypted.tgz2

有什么不同! 为了比较,这里是单个数据库转储压缩的大小:

1.7G    single-backup.sql.gz

我上面有29个。 与常规备份相比,节省约 100 倍!

由于我找到了所有添加加密的地方,我想我可以添加非常简单的可配置压缩,并使用股票gzip实现,将来有可能使用不同的压缩引擎。 有异议吗?

(我可能会给自己两周的晚上来决定成功或失败。)

感谢您的研究并在此处发布结果! 我期待类似的结果。 老实说:我不会合并任何会删除加密的东西,甚至不会让它成为可选项。 这是我们以后可以做的事情,但必须仔细计划。

起初添加压缩似乎很容易,但事实并非如此。 我们需要非常小心,不要意外地使 restic 容易受到意外攻击(这在 TLS 协议中连续发生了几次(是的,我知道这是一种不同的情况))。

整个项目中最重要的不是代码:它是存储库格式。 用户信任我们的数据,他们依赖于长时间使用restic后能够恢复数据,因此存储库格式的稳定性至关重要。 所以为了支持压缩,我们首先需要决定(并实现)下一个版本的存储库格式。 讨论在这里: https :

我可以看到您非常渴望实现这一点(甚至贡献代码),但是在我们就存储库格式达成一致并讨论了这个问题的所有角度之前,请不要花任何时间在这上面。 谢谢!

至于删除的加密,我不打算建议合并它。 我这样做只是为了看看压缩是否有效。 是的,这必须经过仔细计划(没有人希望突然失去验证禁用加密的存储库的能力)。

由于我们使用json.Unmarshal我们可以根据需要向配置中添加任意数量的新键。 如果在 JSON 中找不到它们,它们将保留它们的默认值。

算法选择不是重点,理解:但只是为了将来参考, Brotli似乎是一个强有力的竞争者。

据我所知,Brotli 压缩非常慢(iirc 是 gzip 的 60 倍),因此推荐用于读取非常频繁的数据,而不是写入和压缩的数据,这对于备份来说可能并不常见。 但是,是的,我们还没有详细介绍:)

为不同的压缩算法提供了一个很好的概述。

Brotli 总是更快或具有更好的压缩。 取决于压缩级别。

@ibib你是如何得出这个结论的? 在我看来, brotli看起来比大多数其他(在混合数据集上)慢,同时没有达到特别惊人的压缩率。 也许它更适合特定类型的结构化数据?

正如在Squash 基准测试中的比较中列出的那样,需要使用三个参数:

  • 达到的压缩率:压缩的程度对于节省磁盘空间(和后端的 I/O)很重要。

  • 压缩速度:很重要,因为我们每次添加块时都会做这个操作,所以我们真的想要一些可以跟上 AES-NI 和通用 I/O 的东西,以免成为瓶颈。 我们可能不想选择压缩比解压慢的算法,因为我们有与这些新算法相反的 Web 浏览器用例(例如zstdlz4brotli )针对(我们有“经常压缩,很少解压缩”而不是“压缩一次,经常解压缩”)进行了优化。

  • 解压速度:解压速度只有在我们恢复时才相关。 如果我们可以接受缓慢的恢复,我们可以接受缓慢的解压速度。 另一方面,我们也有不想缓慢解压缩的元数据,因此甚至可能需要两种不同的算法。

看起来density是最快的,尽管在压缩率方面并不是特别有效。 就不是瓶颈而言,它似乎可以让我们(平均而言)几乎免费获得 2:1 的压缩比。 如果我们想要 4:1,我们将不得不选择不同的算法,但我们最终将坐在那里等待它。

我们还有两种(至少?)不同类型的数据:索引; 和数据块。 两者的用法不同,我想可以讨论为它们选择不同的算法是否有意义。 我个人认为我们应该坚持使用一种算法(无论我们选择什么),这样重新实现 Restic(用一种新语言或其他语言)不会变得不合理。 这样我们就不会暴露在两个令人兴奋的压缩算法中的错误中,因为这些算法很难测试极端情况。

我不得不不同意你推荐的权衡。 备份可以在方便的时候在后台运行(也许有 nice 10)。 恢复它们是在时间压力下发生的。 我看到的相关权衡是在块大小和压缩比之间。 太小的块不会很好地压缩并增加元数据开销。 太大的块会降低重复数据删除率。 对于大多数压缩算法,更高级别的设置不会提高小输入的压缩率。

此外,更高的压缩率允许用户在同一空间中保留更多版本的数据。

请记住,我使用 snappy 进行的测试的结果是:1)较小的备份大小(压缩,正常),以及 2)更快的备份和恢复(更少的数据加密、HMAC 和传输)。 使用非常便宜的笔记本电脑。

@cfcs我参考了gzip和brotli的比较
image
这里 brotli 总是有更快更好的压缩。

@Crest这很公平,我们可能有不同的用例——我只是不像你那样使用restic 。 我备份我的笔记本电脑并希望它快速完成,这样我就可以带着我的笔记本电脑离开了。 我认为您在谈论备份服务器或其他持续连接的机器的备份,其中备份率不是那么重要。 类似地,我从不需要在时间压力下恢复所有数据; 如果有时间压力(因为你在专业环境中使用它?),我可以有选择地恢复我需要的数据,然后继续做剩下的事情。

您对“多次小投入”提出了很好的观点;

@viric您所指的效果在 Squash 基准测试中的Transfer + Processing部分下进行了考虑:-)

@ibib啊,

@ibib你能链接你从哪里得到那个图表吗?

我一直在用 brotli 和 zstd 做一些测试,我注意到我的结果与壁球基准测试的结果完全不匹配。 然后我明白该基准测试已有 1.5 年的历史。

zstd 对我来说效果很好。 快+高比,它的“水平”让快和高比之间的跨度非常大。 好东西。

Brotli 对我来说工作很慢,没有比更快的 zstd 更好的压缩比。 而 brotli 似乎专注于英文文本的小文件(它包括一个英文词典)。 用于 html 压缩或类似的。

我发现的更多最新基准: https :

所以我用 LZMA 压缩再次将我的测试平台投入到zbackup 中

35G backup-unencrypted
6.4G    backup-unencrypted.tgz
2.5G    zbackup

令人印象深刻,不是吗?

可以说 zbackup 有自己的局限性和缺点。

因此,根据@viric lzbench 链接,最合适的压缩器是不会减慢备份速度的压缩器(高压缩速度?,> 200 MB/秒),实际上具有良好的压缩比(> = 50),对吗?

所以,我已经从按比例排序的表中过滤掉了结果。

我还对 Go 实现进行了 _quick_ 搜索(这就是我将它们保留在表中的原因)。 删除线意味着我没有找到任何实现,这几乎消除了所有内容。 由于这只是一个快速搜索,我保留了结果。 zstd 的例外,它只是一个包装器。

| 压缩机名称 | 压缩| 解压。| 比较尺寸 | 比率 |
| --------------- | -----------| -----------| ----------- | ----- |
| zstd 1.1.4 -1 | 242 MB/秒 | 636 MB/秒 | 73654014 | 34.75 |
| 蜥蜴 1.0 -30 | 258 MB/秒 | 867 MB/秒 | 85727429 | 40.45 |
| 密度 0.12.5 beta -3 | 253 MB/秒 | 235 MB/秒 | 87622980 | 41.34 |
| gipfeli 2016-07-13 | 233 MB/秒 | 451 MB/秒 | 87931759 | 41.49 |
| 精辟 2011-12-24 -9 | 257 MB/秒 | 1263 MB/秒 | 90360813 | 42.63 |
| 精辟 2011-12-24 -6 | 295 MB/秒 | 1268 MB/秒 | 92090898 | 43.45 |
| quicklz 1.5.0 -1 | 346 MB/秒 | 435 MB/秒 | 94720562 | 44.69 |
| 蜥蜴 1.0 -20 | 284 MB/秒 | 1734 MB/秒 | 96924204 | 45.73 |
| 精辟 2011-12-24 -3 | 352 MB/秒 | 1222 MB/秒 | 97255186 | 45.89 |
| lzrw 15-Jul-1991 -4 | 243 MB/秒 | 392 MB/秒 | 100131356 | 47.24 |
| lzo1x 2.09 -1 | 394 MB/秒 | 551 MB/秒 | 100572537 | 47.45 |
| lz4 1.7.5 | 452 MB/秒 | 2244 MB/秒 | 100880800 | 47.60 |
| fastlz 0.1 -2 | 243 MB/秒 | 469 MB/秒 | 100906072 | 47.61 |
| lzo1y 2.09 -1 | 397 MB/秒 | 556 MB/秒 | 101258318 | 47.78 |
| lzo1x 2.09 -15 | 406 MB/秒 | 549 MB/秒 | 101462094 | 47.87 |
| 密度 0.12.5 beta -2 | 480 MB/秒 | 655 MB/秒 | 101706226 | 47.99 |
| lzf 3.6 -1 | 251 MB/秒 | 565 MB/秒 | 102041092 | 48.14 |
| 活泼的 1.1.4 | 327 MB/秒 | 1075 MB/秒 | 102146767 | 48.19 |
| 2015-11-10 -9 | 220 MB/秒 | 696 MB/秒 | 102817442 | 48.51 |
| 精辟 2011-12-24 -0 | 384 MB/秒 | 1221 MB/秒 | 103072463 | 48.63 |
| lzo1x 2.09 -12 | 418 MB/秒 | 550 MB/秒 | 103238859 | 48.71 |
| 蜥蜴 1.0 -10 | 360 MB/秒 | 2625 MB/秒 | 103402971 | 48.79 |
| fastlz 0.1 -1 | 235 MB/秒 | 461 MB/秒 | 104628084 | 49.37 |
| lzrw 15-Jul-1991 -3 | 226 MB/秒 | 449 MB/秒 | 105424168 | 49.74 |
| lzf 3.6 -0 | 244 MB/秒 | 550 MB/秒 | 105682088 | 49.86 |
| lzo1x 2.09 -11 | 424 MB/秒 | 560 MB/秒 | 106604629 | 50.30 |
| lz4fast 1.7.5 -3 | 522 MB/秒 | 2244 MB/秒 | 107066190 | 50.52 |
| 龙卷风 0.6a -1 | 233 MB/秒 | 334 MB/秒 | 107381846 | 50.66 |
| 内存| 8657 MB/秒 | 8891 MB/秒 | 211947520 |100.00 |

LZ4 看起来是最合适的压缩机?

猜你想要 lz4 (>=1.7.0 r129) 和 zstd (>=1.3.0),如果有的话。 我们也将这些用于 borgbackup。

但是 zstd 可以用一个整数调整,从 lz4 速度到更好
比xz压缩。 这将使密集的快乐用户变慢
压缩和快速压缩。 更不用说zstd
解压速度非常快,无论压缩力如何。

lz4 的用途很窄。

2017 年 12 月 16 日星期六上午 09:50:49 -0800,TW 写道:

猜你想要lz4和zstd,如果有的话。 我们也将这些用于 borgbackup。

——
你收到这个是因为你被提到了。
直接回复此邮件或在 GitHub 上查看:
https://github.com/restic/restic/issues/21#issuecomment -352199097

——
(Escriu-me xifrat si saps PGP / 如果您了解 PGP,请写密码)
PGP 密钥 7CBD1DA5 - https://emailselfdefense.fsf.org/

好吧..根据https://github.com/restic/restic/issues/21#issuecomment -250983311 保持 restic 依赖自由,zstd 目前不是一种选择。 此外,还有一些关于专利/许可问题的线索。

至于 xz 和高压缩比,即使是较低的压缩设置,根据表格,最快的压缩速度约为 15MB/秒。

如果降低对快速备份的要求,例如 >=30MB/秒,我们可以添加:

| 压缩机名称 | 压缩| 解压。| 比较尺寸 | 比率 |
| --------------- | -----------| -----------| ----------- | ----- |
| xz 5.2.3 -9 | 1.70 MB/秒 | 56 MB/秒 | 48745306 | 23.00 |
| xz 5.2.3 -6 | 1.89 MB/秒 | 58 MB/秒 | 49195929 | 23.21 |
| xz 5.2.3 -3 | 4.18 MB/秒 | 55 MB/秒 | 55745125 | 26.30 |
| zstd 1.1.4 -8 | 30 MB/秒 | 609 MB/秒 | 61021141 | 28.79 |
| zling 2016-01-10 -2 | 32 MB/秒 | 136 MB/秒 | 61917662 | 29.21 |
| xz 5.2.3 -0 | 15 MB/秒 | 44 MB/秒 | 62579435 | 29.53 |
| zling 2016-01-10 -0 | 38 MB/秒 | 134 MB/秒 | 63407921 | 29.92 |
| zstd 1.1.4 -5 | 88 MB/秒 | 553 MB/秒 | 64998793 | 30.67 |
| lzfse 2017-03-08 | 48 MB/秒 | 592 MB/秒 | 67624281 | 31.91 |
| libdeflate 0.7 -6 | 64 MB/秒 | 609 MB/秒 | 67928189 | 32.05 |
| 2017-03-10 -2 | 98 MB/秒 | 289 MB/秒 | 68085200 | 32.12 |
| zstd 1.1.4 -2 | 185 MB/秒 | 587 MB/秒 | 70164775 | 33.10 |
| 龙卷风0.6a -4 | 91 MB/秒 | 197 MB/秒 | 70513617 | 33.27 |
| libdeflate 0.7 -3 | 96 MB/秒 | 602 MB/秒 | 70668968 | 33.34 |
| xpack 2016-06-02 -1 | 98 MB/秒 | 506 MB/秒 | 71090065 | 33.54 |
| 龙卷风0.6a -3 | 119 MB/秒 | 188 MB/秒 | 72662044 | 34.28 |
| libdeflate 0.7 -1 | 117 MB/秒 | 570 MB/秒 | 73318371 | 34.59 |
| 蜥蜴 1.0 -42 | 90 MB/秒 | 938 MB/秒 | 73350988 | 34.61 |
| zstd 1.1.4 -1 | 242 MB/秒 | 636 MB/秒 | 73654014 | 34.75 |

有多种 deflate 实现,但不确定它们是否具有可比性。
左 xz 供参考
zstd 看起来很有前途。 太糟糕了,没有 Go 实现

@viric zstd 的速度并不完全是 lz4。

但是如果您只想拥有一个压缩器而不是多个压缩器,那么 zstd 会更灵活。

原谅我的迟到。 一些评论:

压缩速度:很重要,因为我们每次添加块时都会做这个操作,所以我们真的想要一些可以跟上 AES-NI 和通用 I/O 的东西,以免成为瓶颈。 我们可能不想选择压缩比解压慢的算法,因为我们有针对这些新算法(如 zstd、lz4、brotli)优化的 Web 浏览器的相反用例(我们有“经常压缩,很少解压缩”)而不是“压缩一次,经常解压缩”)。

不,没有必要以硬件加速的 AES 速度进行压缩。 压缩是关于大小的交易时间。 完全预计压缩备份将需要更长的时间。

例如,我没有在我的个人备份上使用 restic,而是仍然使用 Obnam,因为在我存储它们的其中一台小型服务器上,如果它们没有被压缩,它们将不适合。 备份已经需要几个小时了,而且它们在后台运行,所以我什至没有注意到。

我不在乎 restic 的压缩备份是否需要更长的时间。 事实上,我希望他们这样做,这是我需要做出的权衡。 如果没有这种压缩,restic 对我来说没有用处。

解压速度:解压速度只有在我们恢复时才相关。 如果我们可以接受缓慢的恢复,我们可以接受缓慢的解压速度。 另一方面,我们也有不想缓慢解压缩的元数据,因此甚至可能需要两种不同的算法。

恢复的频率远低于备份,因此解压速度并不重要。 有人提到他们通常是在时间压力下完成的:这是真的,但这并不意味着恢复需要和备份一样快,或者接近备份。

我们还有两种(至少?)不同类型的数据:索引; 和数据块。 两者的用法不同,我想可以讨论为它们选择不同的算法是否有意义。

可能根本没有必要(或不一定是个好主意)压缩索引。 作为索引,它们似乎不太可能首先压缩得很好,因为它们的全部目的是存储唯一数据。

我个人认为我们应该坚持使用一种算法(无论我们选择什么),这样重新实现 Restic(用一种新语言或其他语言)不会变得不合理。 这样我们就不会暴露在两个令人兴奋的压缩算法中的错误中,因为这些算法很难测试极端情况。

我理解这些担忧,但我认为那将是一个错误。 至少,repo 格式必须允许多种压缩算法,以便将来可以添加更新的算法。 可能应该有用于压缩的可插拔模块,以便用户可以选择他们想要使用的模块,例如我可以想象像restic-xzrestic-zstd等 Debian 软件包,用户可以根据需要安装它们使用这些算法。 备份数据的压缩应该被抽象化,以便 restic 将一些数据交给压缩函数并将其压缩回来,而 restic 不应该关心中间发生了什么; 解压也是一样。

如果对快速备份的要求降低,比方说 >=30MB/sec,我们可以添加

这对我来说似乎是合理的。 请记住,本地备份只是一种; 网络备份不太可能受到压缩速度的限制。

但是,同样,这应该可由用户进行调整,以便他们可以根据自己的需要选择合适的解决方案。

为 :beer 增加了 10 美元的赏金::)
image

🍺++

如果其他人愿意贡献,这里是 BountySource 的链接
badge
https://api.bountysource.com/badge/issue?issue_id=6096108

我想知道这是否可以以用户可配置的方式实现,以便用户决定速度与大小的选择。 我更喜欢更高的压缩作为默认值。

让我们决定什么时候到达那里。 为了记录:我可以在速度与大小方面给用户一些控制权。

+1 表示需要压缩实现的 restic。 我正在使用 restic 将 VM 映像备份到 backblaze,并且希望能够在上传之前压缩它们。 在我的用例中,我会用几乎无限的时间/CPU 来减少传输/存储数据的大小。 我意识到速度对某些人来说更重要。 拥有一个可以选择多种算法的可插拔架构是关键。

我很乐意帮助测试,因为这会得到进一步的研究。

@fd0我已经有一段时间没有在 restic 代码库上工作了。 您是否可以快速指导一个好的方法以及我应该看哪里?

@klauspost在技​​术层面上增加压缩并不多,这很容易做到,而是我们如何以向后兼容的方式处理升级 repo 格式。 我目前正忙于重写归档程序部分(以便像#549 这样丑陋的东西消失),之后我想添加压缩,然后切换到 repo v2。

您对我们应该使用哪种压缩算法有什么看法? 我正在考虑支持三种模式:
1) 无压缩
2)“线性时间”压缩(不会增加太多CPU负载)
3)“最大压缩”

也许第一种和第二种模式是一样的,我还不确定

能够使用像 zstd 这样的东西是最棒的,但是作为本地 Go 代码。 Damian 暗示移植 Java 或 C 版本可能没有太多工作:https://twitter.com/dgryski/status/947259359628738560,有什么我可以做的让你有兴趣尝试吗? :)

我已经看过 zstd 格式规范,对我来说实现(好吧)并不容易。 Java 源代码只是解压。

对于快速压缩,LZ4 应该做得很好。 Go 端口非常好。 zstd 会更好,但我会使用久经考验的软件包,除非您想使用 cgo 实现。

对于中间道路,放气压缩仍然是很好的速度/压缩方式。 测试良好等。

高压缩有点棘手。 然而,似乎在github.com/ulikunitz/xz包中有一个原生的 LZMA(2) Go 实现。 README 中有一些关于稳定性和性能的警告。 不需要 xz 包装器,因为您已经有未压缩的散列和大小。 我可以试一试,看看它如何比较。

我查看了来源以找到插入压缩步骤的自然位置。 对我来说有意义的是在此处进行此处进行解压缩。 但我看到了识别和跟踪压缩的挑战。

您还可以查看我制作的“可压缩性估计器” 。 它将快速估计一团数据的可压缩性。 它通常以 >500MB/s 的速度运行,因此可用于快速拒绝难以压缩的数据。

您还可以查看我制作的“可压缩性估计器”。 它将快速估计一团数据的可压缩性。 它通常以 >500MB/s 的速度运行,因此可用于快速拒绝难以压缩的数据。

喜欢可压缩性估计器! 避免尝试压缩不可压缩的数据会获得很大的速度。

Zstd 内置了类似的东西: [1]

Zstd 通过不可压缩的数据更快。 期望> 1 GB/s

虽然我还没有找到任何明确的基准。

xz 包对于 lzma 来说看起来很划算。 使用默认设置进行了一些快速测试:

| 算法 | 水平 | 超大 | 特大| 毫厘| 兆欧/秒 | 比率|
|-----------|-------|------------|-----------|---- ----|--------|--------|
| lz4 | - | 1000000000 | 625968314 | 5454 | 174.85 | 62.60% |
| flatekp | 1 | 1000000000 | 391051805 | 12367 | 77.11 | 39.11% |
| flatekp | 5 | 1000000000 | 342561367 | 20164 | 47.3 | 34.26% |
| flatekp | 9 | 1000000000 | 324191728 | 43351 | 22 | 32.42% |
| lzma2 | | 1000000000 | 291731178 | 149437 | 6.38 | 29.17% |
| lzma | | 1000000000 | 291688775 | 161125 | 5.92 | 29.17% |

非常合理的速度/压缩权衡。 所有都是enwik9上的单核性能 - 中等可压缩文本正文。 显然,我没有时间测试完整的 VM 映像或具有更多混合内容的10GB 语料库之类的东西。

与标准 lzma 相比,lzma2 在其当前的实现中似乎没有提供很多。 由于您正在处理小块,因此差异应该很小。

Zstd 内置了类似的东西

是的,就像 lz4 和 deflate 一样,但是,我没有看到它像专用功能一样快。

毫无疑问,zstd 确实令人印象深刻。 使用 cgo 实现的基准测试:

| 水平 | 超大 | 特大| 毫厘| 兆欧/秒 | 比率|
|-------|------------|-----------|--------|------- -|--------|
| 1 | 1000000000 | 358512492 | 5100 | 186.96 | 35.85% |
| 2 | 1000000000 | 332265582 | 6264 | 152.24 | 33.23% |
| 3 | 1000000000 | 314403327 | 8099 | 117.75 | 31.44% |
| 4 | 1000000000 | 310346439 | 8588 | 111.04 | 31.03% |
| 5 | 1000000000 | 305644452 | 12739 | 74.86 | 30.56% |
| 6 | 1000000000 | 292551252 | 18531 | 51.46 | 29.26% |
| 7 | 1000000000 | 287414827 | 23212 | 41.08 | 28.74% |
| 8 | 1000000000 | 282783804 | 27811 | 34.29 | 28.28% |
| 9 | 1000000000 | 280432907 | 31752 | 30.03 | 28.04% |

如果我错过了什么,请原谅我,但我没有看到之前回答过这些问题。

  1. 我们似乎在谈论块级别的压缩,而不是文件级别的压缩,对吗?
  2. 如果是这样,那显然会限制效率,因为将针对每个块存储和压缩单个文件的多个块中的重复数据。
  3. 但是,这显然也取决于块大小。
  4. 那么,平均块大小是多少? 似乎这是压缩有用程度的一个重要因素。
  5. 如果块大小相当小,也许我们应该考虑对高度可压缩的文件进行全文件、预分块压缩(例如使用@klauspost的估算器)。 例如,一个 50 MB 的文本文件(例如日志文件、大型 Org 模式文件等)很可能作为单个文件进行高度压缩。 但是如果它先分块,然后每个块单独压缩,不共享索引,这将极大地限制压缩(IIUC)的有效性。

谢谢。

如果我们要压缩整个文件,那可能会篡改重复数据删除算法,从而降低其效率。

除此之外,我们不要忘记任何压缩在提供空间方面的巨大优势的同时,也会让我们进行侧信道攻击。 根据压缩数据的大小,人们可以对数据的内容做出有根据的猜测。 我认为这之前已经提到过,但仍然如此。

@alphapapa

我们似乎在谈论块级别的压缩,而不是文件级别的压缩,对吗?

是的,在块级别。

如果是这样,那显然会限制效率,因为将针对每个块存储和压缩单个文件的多个块中的重复数据。 但是,这显然也取决于块大小。 那么,平均块大小是多少? 似乎这是压缩有用程度的一个重要因素。

我们的目标是 1MiB,但它可以达到 8MiB。

如果块大小相当小,也许我们应该考虑对高度可压缩的文件进行全文件、预分块压缩(例如使用@klauspost的估算器)。 例如,一个 50 MB 的文本文件(例如日志文件、大型 Org 模式文件等)很可能作为单个文件进行高度压缩。 但是如果它先分块,然后每个块单独压缩,不共享索引,这将极大地限制压缩(IIUC)的有效性。

起初,我想在块级别上集成压缩,看看它在现实生活中的表现如何。 我们可以稍后重新审视这个想法。

@klauspost 非常感谢您花时间对一些算法/实现和您的建议进行基准测试,我很感激! 虽然拥有 zstd 会很好,但我认为不依赖于cgo对整个项目来说更为重要。 使用可压缩性估计器是个好主意,我喜欢这样。

您提到的添加压缩/解压缩的地方听起来不错,但我们需要在其他地方跟踪元数据。 我认为我们可能会为包头中字节中的位添加含义,请参阅http://restic.readthedocs.io/en/latest/100_references.html#pack -format。 这是需要非常小心地完成的部分。

所以,让我以#1494 结束,然后我们会看到这个问题得到解决。

@sanmai 回复:旁道:我最初提出来的。
提出了各种解决方案,我个人会满足于:

  • 具有用于将压缩列入白名单/黑名单的配置选项(类似于我们用于文件包含的内容)

另一个想法是尝试隐藏包文件中的块边界,从理论上讲,这会使其变得更难,但我觉得您仍然可以对网络写入进行计时,以及将块写入到哪个文件系统范围之类的旁道等等可以用来推断边界,所以我觉得最安全/最简单的方法是建议不要压缩敏感数据。

这太棒了! :啤酒:+ 10美元

只是把它扔在那里,但把 lzma 或任何更通用的压缩算法放在一边,那么仅仅运行长度编码或零压缩呢? 或者这对足够多的人来说还不够有用吗?

(我在这次狩猎中养了一只狗,我经常在大量静音的情况下备份巨大的 WAV 文件。)

+$15

只是把它扔在那里,但把 lzma 或任何更通用的压缩算法放在一边,那么仅仅运行长度编码或零压缩呢? 或者这对足够多的人来说还不够有用吗?

也可用于备份大部分空白/稀疏文件的 VM 驱动器(不确定 restic 是否已经支持备份/恢复稀疏文件)

@bherila restic 尚不支持归档/恢复稀疏文件,这些文件将存储在 repo 中,就好像它们只包含许多零一样。 这些大块的零被去重,所以它不会占用存储库中的太多空间。 但是,对于恢复,您最终会得到一个没有“漏洞”的常规(非稀疏)文件。

我只是想检查一下,是否已经有某种压缩? 我已经备份了几台计算机,其中一台有 50GB 的数据,但我在服务器上得到的数字要低得多:

# du -shc /home/restic/
40G     /home/restic/
40G     total

@Alwaysin这可能是重复数据删除,除非当然排除某些文件。

@rawtaz谢谢,我不知道重复数据删除,一定是这样!

如@rawtaz所述,@iluvcapra 已通过重复数据删除实现了大型重复块的压缩。

@klauspost你看到了吗? https://github.com/mvdan/zstd

是的,但老实说,流解码器是最简单的部分。 我已经完成了 FSE 编码/解码并准备好了霍夫曼编码器。 霍夫曼解码完成后,zstd 流解码器非常简单,完整的编码器是最后一部分。

LZ4 是完全足够的,也将是一个快速的胜利。

为什么不添加 lz4 并创建另一个 PR 来支持 zstd?

为什么不添加 lz4 并创建另一个 PR 来支持 zstd?

@dave-fl 因为我们在修改存储库格式时需要非常小心。 它必须以向后兼容的方式完成。 整个项目最重要的部分是 repo 格式,而不是实现。 人们依靠我们不要搞砸格式,以便他们可以恢复他们的数据:)

我认为我们不能等待太多压缩。 我只是对几个服务器备份存储库进行了一些测试,当我对存储库进行 gzip 压缩时,我什么也没赢! 像@Alwaysin一样,我已经通过重复数据删除赢得了 30% 的胜利。

关于向后兼容的方式,您的意思是 Restic 应该阅读这两种格式或一种从旧格式迁移到新格式的工具? 当 Restic 不在 v1.0.0 时,我相信迁移就可以了。

我只是对几个服务器备份存储库进行了一些测试,当我对存储库进行 gzip 压缩时,我什么也没赢!

嗯,这是意料之中的:repo 中的所有数据都是加密的,因此根本无法压缩。 如果使用压缩,则必须加密进行压缩。

我不明白使用 LZ4 如何使事情不向后兼容。 压缩就是压缩。 为什么不支持多种格式?

你说得对,我没想到。
但是,当我对源代码进行 gzip 压缩时,我的获胜率不超过 30%,重复数据删除在具有许多重复项的大目录上已经非常有效。 但当然,两者都可以令人印象深刻。
使用 zpaq 进行压缩和重复数据删除,我赢得了更多,而不是那么多。
我非常愿意测试一个带有压缩的分支,如果它不兼容也没关系!

我不明白使用 LZ4 如何使事情不向后兼容。 压缩就是压缩。 为什么不支持多种格式?

如果 2 个客户端使用相同的 repo,但其中 1 个使用不支持压缩的旧版本 restic,会发生什么? 需要在考虑所有可能的极端情况的情况下仔细设计此功能。

我不希望压缩超过一半的工作解决方案,这可能会破坏以前的备份。

我认为关于添加压缩​​的问题已经有足够的讨论。 我可以看到这是一个备受期待的功能。 在完成新的归档程序代码后,我将接下来解决这个问题(参见 #1494)。

请不要再添加任何评论,谢谢!

@dimejo

我敢说 zstd 的 CGO 版本看起来有点便携:)

我看到了根据规范编写 zstd 的 golang 实现是多么可行,非常简短。

zstd 主要是所有内部算法,但(可选)依赖于xxHash-64 校验和进行错误检查,并且有golang 端口。 由于可选位是可选的,因此您不必实现这些部分即可获得对 restic 中读取器/写入器的 zstd 支持。 zstd 支持“字典”的概念来优化压缩——我不确定这将如何与限制交互,但将是一个有趣的研究领域,以压缩档案的特定部分,例如 JSON 或元数据流。 否则,该实现也可以跳过,因为它是可选的。

当然,它变得更棘手的地方是熵编码。zstd 使用了一种称为有限状态熵(FSE,[ANS] 的变体(https://en.wikipedia.org/wiki/Asymmetric_numeral_systems#,其中也只有一个C实现,其他熵编码位用huffman编码实现,其中有几种实现,包括标准库中的两种:一种在compress.flate中,另一种在net.http2.hpack中,即比较奇怪。

据我所知,其他所有东西都粘在上面……一些霍夫曼树、序列、帧和块。 块和框架的构建方式也有一些有趣的属性,它们可以很好地映射到静态 blob,这可能可以将存储库作为一个整体进行压缩,同时将 blob 保持在内部分开,尽管我还没有详细研究过. 它还可能使存储库格式和压缩之间的耦合变得不可接受。

zstd 在很大程度上比 gzip 或 xzip 复杂,与分别为 36k 和 12k 相比,大约有 70k 行代码(根据 cloc)。 然而,这包括许多测试:当这些被忽略时,实现本身与 gzip (~34k) 相当。

所以,总而言之,在 go 中实现它只是时间问题。 我相信这样的引擎也可以利用 golang 的并行性,因为 zstd “框架”彼此独立。 但是,我不清楚如何使用框架:我测试的大多数流只有一个( zstd /etc/motd )或两个( zstd isos/Fedora-Workstation-Live-x86_64-27-1.6.iso )框架(由binwalk -R "\x28\xb5\x2f\xfd" ),所以可能不会有这样的收获,因为是相互关联的并且可并行性较低......

无论如何,除非这里有人想真正坐下来移植它,否则一切都没有实际意义,但我想我会分享我在阅读这篇文章时的发现......考虑到 zstd 是 LZ77 系列压缩机的 LZMA 部分的扩展,它应该移植不是不可行的......

关于压缩的任何更新? 我知道很多人都想等待zstd ,但是实施lz4lzolzma会有什么问题?

如果有更新,这个问题将被更新。

不过,让我们在此期间尽量尊重作者的要求:

请不要再添加任何评论,谢谢!

@fd0 ,只是想指出 zstd 算法https://github.com/klauspost/compress/tree/master/zstd似乎有一个纯 Go 实现。 我自己没有尝试过。 但这让我对 restic 中的压缩支持的可能性感到兴奋。

我不知道 Go zstd 的东西(速度?代码质量?维护?),但是 C zstd 的东西几乎是备份工具所需要的,因为它支持从快速/小到慢/高压缩的广泛范围。

如果我们还没有在 borgbackup 中使用所有其他压缩算法(lz4、zlib、lzma)并且现在开始添加压缩,那么我猜我们可以只使用 zstd 而没有。

根据喜好/偏好,默认值可以是无(就像以前一样)或非常快的 zstd 级别(总体上仍然使大多数备份更快,因为要传输的数据较少)。

你好,
在我看来,压缩不是 Restic 必须具备的功能。 我比较了使用 Duplicati(带压缩)和 restic(不压缩)完成的数据备份,总体使用空间非常相似。
我只需要 restic 来获得快速可靠的增量备份。 没有必要打破这一点......
恢复也很重要,restic 适用于灾难恢复。 Duplicati 是一场噩梦,因为如果你丢失了本地数据库,修复任务需要几天时间......

谢谢@fd0并感谢所有贡献者!

@filippobottega如果您在实验中没有看到大的差异,这意味着:

  • 您的数据不是(很多)可压缩的(但通常情况并非如此),或
  • 那个副本有一些与压缩无关的更差的存储效率(例如,由于不同的存储格式、粒度、算法等等……),因此压缩节省由其他方面的损失来补偿。

两者并不意味着压缩毫无意义。

@ThomasWaldmann由于第一个原因,我认为没有太大区别。
今天的数据已经以多种方式进行了压缩:docx、xlsx、pptx、zip、7z、jpeg、tif 等都是压缩格式。 而且 iso 图像包含压缩文件。 出于这个原因,我认为压缩在 restic 中毫无意义。

@filippobottega您对人们使用静态备份的数据的看法有点狭隘。 SQL 转储、源代码、数据集、原始图像等怎么样? 重复数据删除在减少备份之间的增量大小方面做得很好,但是它没有减少数据集的原始大小。 在未压缩格式的情况下,这可能意味着许多千兆字节。 更不用说存储未压缩格式然后压缩 + 重复数据删除可能会产生比对已压缩文件进行重复数据删除更好的结果。

SQL 转储是我的第一个想法,但 Restic 也备份我的邮件服务器,并且基于我从 Duplicati 移动到 Restic 时拍摄的一些 RAR 快照,它似乎获得了更好的整体压缩。

我可以看到使压缩成为可选并具有默认文件类型列表的用例,但压缩可以为我节省合理的资金。

@mrschyte

您对人们使用 restic 备份哪些数据的看法有点狭隘。

现在,没有必要变得个性化。 他的观点和你的一样有效,值得考虑。 我发现我备份的大部分数据由于文件格式的原因已经被压缩。

SQL 转储怎么样

你真的存储未压缩的 SQL 转储吗? 在备份它们之前,我将它们全部归还,因为我不需要原始存储它们。

源代码、数据集、原始图像等

我认为压缩备份的唯一有效用例是具有大量重复的大型未压缩文件_正在积极使用,因此尚未压缩存储_。 根据我的经验(包括多年管理其他人的数据),很少有数据属于这一类。 至少,在这些情况下还不足以产生巨大的影响。

但是它对减少数据集的原始大小没有任何作用。

可以说,这不是备份程序的工作。 它不应该触及原始数据。

更不用说存储未压缩格式然后压缩 + 重复数据删除可能会产生比对已压缩文件进行重复数据删除更好的结果。

许多压缩算法依靠复制来完成它们的工作(请参阅 flate 的字典),所以我不相信这一点_一般_,尽管我同意这至少在某些时候是正确的。

(我并不是说 restic 中的压缩在正确完成时是 _bad_,我只是认为它不必成为优先事项——尤其是与挥之不去的性能问题相比——我们应该尊重@fd0的时间限制和关于视力的愿望。)

@mholt我一般都会同意,但是做一个根备份(通过一些转储甚至迭代 / 的内容),对我来说产生了一个很好的压缩比。 不是必需的,因为使用的总量已经很小,但我节省了大约 50%,对于最终用户而言,“免费”总是很好。

试试这个测试。

  1. 获取 SQL 转储或其他一些未压缩的文件。 压缩它然后
    使用restic备份它。
  2. 从 SQL 数据库中删除一个表,进行第二次转储,然后压缩它,
    然后使用restic来备份它。

我相信你会发现,因为压缩是在之前完成的
重复数据删除您几乎将完全击败 restics 重复数据删除算法。
但是,如果 restic 可以在对您进行重复数据删除后处理压缩
应该得到更小的整体输出。

在使用 DataDomain 等工具的企业存储行业中,它总是
建议将数据以未压缩的形式提供给存储设备
格式化并让设备进行重复数据删除,然后进行压缩。 这
应用这些工具的一般顺序是重复数据删除,
压缩,然后加密。 想一想这个....你
真的想把所有额外的 CPU 都用在多次压缩相同的数据上
时间只是为了它被删除并基本上被丢弃? 它的
普遍认为最好先通过重复数据删除来减少数据集
在花费进行压缩的潜在繁重任务之前。

2019 年 8 月 2 日星期五下午 1:29 Brandon Schneider通知@github.com
写道:

@mholt https://github.com/mholt我一般都会同意,但是做
根备份(通过一些转储甚至迭代 / 的内容),
对我来说产生了很好的压缩比。 不是必需的,因为总
used 已经很小,但我节省了大约 50%,这总是很好
就最终用户而言,拥有“免费”。


您收到此消息是因为您订阅了此线程。
直接回复本邮件,在GitHub上查看
https://github.com/restic/restic/issues/21?email_source=notifications&email_token=AC3I762ZVGTTJL4TF3ODZILQCRVIXA5CNFSM4AXPP352YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJLOTDN5G43VMVBW63LNMVXHJL00000000000000000005GA
或静音线程
https://github.com/notifications/unsubscribe-auth/AC3I767IQQD3CZBIWM37C6TQCRVIXANCNFSM4AXPP35Q
.

你真的存储未压缩的 SQL 转储吗? 在备份它们之前,我将它们全部归还,因为我不需要原始存储它们。
可以说,这不是备份程序的工作。 它不应该触及原始数据。

感觉这种观点阻碍了数据的高效存储? 每个程序和导出操作都应该实现自己的即席压缩格式的想法是我试图摆脱的,因为它可以防止重复数据删除/压缩/等处理除预定义的每个文件(或目录 tarball)范围之外的任何内容. 单独压缩文件会失去在不同文件/转储/等之间找到共性的能力,随后您将失去重复数据删除的所有好处。 保持未压缩状态允许文件系统(zfs、btrfs 等)为您完成这一切,而且更好,因为它可以跨文件夹、快照等进行压缩和重复数据删除,并在保留与需要工作的工具的兼容性的同时将其抽象化与未压缩的数据。

压缩可以被看作是对 top restic 的重复数据删除的额外优化,但如果单独进行,它们似乎彼此不兼容......建议在备份文件之前应该压缩和预处理文件会将所有内容带回到工作流程中,您也可以只需使用 rsync/rclone 代替,那么为什么首先使用 restic 呢?

感觉这种观点阻碍了数据的高效存储? 每个程序和导出操作都应该实现自己的即席压缩格式的想法是我试图摆脱的,因为它可以防止重复数据删除/压缩/等处理除预定义的每个文件(或目录 tarball)范围之外的任何内容. 单独压缩文件会失去在不同文件/转储/等之间找到共性的能力,随后您将失去重复数据删除的所有好处。 保持未压缩状态允许文件系统(zfs、btrfs 等)为您完成这一切,而且更好,因为它可以跨文件夹、快照等进行压缩和重复数据删除,并在保留与需要工作的工具的兼容性的同时将其抽象化与未压缩的数据。

它不仅是高效的数据存储,也是现有的工作流程。 我想要一个备份产品来可靠有效地备份我的数据,而不是在系统的其他方面强制执行工作流。 有效地存储备份(保留,可能无限期)更为重要,而实时工作数据应以最佳格式存储,以便积极使用。

现在有些情况下在存储之前进行压缩是有意义的,尤其是在慢速存储系统上非常可压缩的数据,但根据我的经验,这是例外而不是规则。

+1 压缩真的对我有帮助! 作为一名软件工程师,我备份了我的整个主文件夹,其中包含大量未压缩的源代码(在动态语言中,如 ruby​​ 或 python,它几乎总是源代码——甚至是大多数依赖项)。

在家里,我备份了我的整个 / ,再次包括许多从压缩中受益的东西,例如二进制文件、man 文件、资源文件等。

当然,我可以压缩所有它们,并在备份它们之前进行许多转换,但这会破坏仅运行一个非常简单的命令并能够轻松获得备份的许多便利恢复东西。

现在当然有很多类别的文件不能很好地压缩,但是没有人说应该强制压缩它们。 有很多方法可以解决这个问题——白名单哪些文件类型应该被压缩,哪些文件不应该被列入黑名单,或者甚至是最简单的一种:尝试压缩,如果结果大小没有改善,则存储未压缩(我相信 ZFS在启用磁盘压缩时使用此方法)。

最后,压缩是经典空间与时间权衡的一个例子:你想支付更多的 cpu,还是更多的存储? 在我的情况下,存储在我的成本中占主导地位,所以我认为如果我的四核加热得更多一点,然后我的文件托管费用更少,那就太好了。

最后,我向云提供商备份了 4 TB 以上的数据,但无论如何我的上传速度都很慢,所以作为额外的压缩,我的备份过程会更快,而不是更慢——我的 CPU 可以跟不上我糟糕的 VDSL 连接.

是的,我可以同意这里的所有其他人。 压缩非常重要,我真的看不出为什么 restic 不应该有它。

@mholt我完全同意你的看法。 每一个字。
在我的工具链中,压缩先于静态重复数据删除,因为例如,我使用 TFS 作为源控制,并且所有源都已经在 SQL 备份中压缩,应用程序映像在 msi 安装文件或 7z 存档中压缩。 我只需要一种快速而简单的方法来获取每天的增量并将其发送到云中以实施安全的灾难恢复计划。
我认为@fd0需要集中时间解决问题,而不是试图为产品添加其他复杂性。

只是在使用auto,zstd压缩和 restic(无压缩)的 borg 之间进行了一些比较,首先在/ ,然后在/home ,不包括 VM 图像和docker 图像(因为我也不在现实世界的备份中备份它们)。 测试机是我日常的软件开发机,里面有很多二进制文件,一些压缩图片和音频文件,还有相当多的纯文本源代码,应该压缩得很好:

/ :1053136 个文件,92.9 GiB

  • 博格,无:17:27 分钟,64.1 GiB
  • 博格,zstd:19:29 分钟, 40.6 GiB
  • 静止:09: 45分钟,62.4 GiB

/home :221338 个文件,58.3 GiB

  • 博格,zstd:09:06 分钟, 30.7 GiB
  • restic:四点36分钟,39.4吉布
    我在这里省略了没有压缩的 borg,因为就存储空间而言,它与 restic 大致相同。

首先,我要赞扬 restic 在该测试用例上的速度几乎是原来的两倍。 除了 borg 变慢之外,可能有趣的是,压缩仅将整个备份持续时间增加了约 2 分钟(+11%),但显着减少了/情况下要存储的数据(-35 %)。 对于我的主目录,存储节省大约为 20%。

(这种情况下测试是在外盘上进行的。备份到远程存储时,备份的时间主要取决于上传带宽,至少在CPU和IO速度远高于网络的情况下。我测试过this 和 borg 压缩实际上比 restic 快,因为压缩导致传输的数据更少)。 总而言之,我非常赞成 restic 获得压缩支持,理想情况下使用自动检测来检查块是否从压缩中受益。

@nioncode如果我的计算是正确的,你备份大约 100/150MB/s。 这低于 zstd 可以压缩的内容。 由于压缩是异步的,所以不应该真的有任何减速。 它甚至可能更快一点,因为要写的东西更少。

我知道归档 VM 可能是一个用例,但我试图避免这样做。
我正在尝试从 iso 和安装文件开始自动化整个 VM 构建。
在灾难恢复的情况下,我希望能够使用安装文件、文档和数据库备份的备份来恢复整个 VM。 我试图在没有用户交互的情况下做到这一点。
通过这种方式,我可以避免压缩和备份 VM 中包含的大量垃圾文件(如临时文件)、未压缩的文件(如 exe 和 dll)等。
我知道,这并不简单,但我可以避免压缩和重复删除相同且无用的 GB 文件,从而节省磁盘空间和带宽。

让我们不要把这个关于谁做事怎么做的话题搞得一团糟。 已经足够了。

压缩是许多人(包括我自己)想要的功能,它可以在中等速度的互联网连接情况下节省备份存储和上传时间,对某些人来说甚至可以节省 30% 或更多。

然而,并不是每个人都需要它,有些人已经以一种聪明的方式调整了他们的工作流程来处理它——或者只是有钱或带宽,或者两者兼而有之,根本不在乎。

不管怎样,双方都说了。

@bjoe2k4或担心在加密之前压缩数据的负面安全影响,这会

除非压缩成为强制性的,否则压缩的安全问题只是用户可以做出的权衡。 我将采取更快的备份并减少每月和一次性成本超过这一理论风险(这种风险可能无法利用,因为我的数据集很大且变化不可预测,因此噪音会淹没任何尝试生成压缩信号)。

我不相信有人在谈论强制压缩。

我的特殊用例是备份大量 CSV 和 SQL 转储。 这些文件非常可压缩……我不想/不能预压缩它们。

我真的很想拥有压缩功能,因为我为每 GB 在线存储付费

由于这个讨论现在变得更加活跃,我想与我的一些朋友的修补版restic分享我的一些发现。 他们为 restic 添加了压缩(据我所知或多或少是快速和肮脏的),我会通知他们这篇文章,以便他们可以在有人感兴趣时评论实现细节。
我的用例是一些非常丑陋的银行软件,它有自己的数据库格式。 出于监管原因,我们必须使用该软件,而我们拥有的数据是几 TB 的相当大的文件,可以压缩到原始大小的 90%。 因此,很明显,压缩可以为我们节省很多备份存储、备份时间和恢复时间。
我在比较 restic 上游时的发现、带压缩的补丁 restic 和我们当前使用 tar 的备份解决方案可以在这里找到: https ://gist.github.com/joerg/b88bf1de0ce824894ffc38f597cfef5f

| 工具 | 备份时间 (m:s) | 恢复时间 (m:s) | 备份空间 (G) | 备份空间 (%) | 备份 (MB/s) | 还原 (MB/s) |
| --------------------------- | ----------------- | ------------------ | ---------------- | ---------------- | ------------- | -------------- |
| 焦油 | 4:42 | 5:19 | 11 | 9.6% | 404 | 第357话
| Restic S3 本地上游 | 10:04 | 30:56 | 102 | 89.5% | 189 | 61 |
| Restic S3 本地压缩 | 5:43 | 19:28 | 8.6 | 7.5% | 第332话 98 |
| Restic 本地上游 | 8:33 | 26:06 | 102 | 89.5% | 第222话 73 |
| Restic 局部压缩 | 5:21 | 16:57 | 8.6 | 7.5% | 第355话 112 |
| Restic S3 远程上游 | 17:12 | 46:06 | 102 | 89.5% | 110 | 41 |
| Restic S3 远程压缩 | 5:27 | 21:42 | 8.6 | 7.5% | 第349话 88 |

我认为 restic 会通过任何类型的可选压缩获得大量收益,因为它几乎可以减少所有内容。

并非每个文件都有有趣的压缩率。 压缩视频文件可能毫无价值,但压缩 SQL 转储肯定是毫无价值的。 这就是为什么像 Btrfs 这样的文件系统首先尝试压缩文件的前 128KB,如果压缩率很高,则会压缩整个文件。 它绝对不完美,但速度很快,如果决定单独压缩文件,它应该适用于大多数用例。

对于那些反对提供压缩作为选项的人,我的用例是我备份大部分可压缩文件类型的混合,我无法控制其内容并且期望我必须压缩数据是不合理的在执行备份操作之前,多台机器(在压缩到新存档的情况下会占用更多本地磁盘空间,或者如果在适当位置压缩则使相关应用程序无法使用文件)。

我更希望能够使用 restic 作为我的 DR 备份工具,但我目前正在使用 borg(缓慢、大量的 ram 要求等),因为它实现的压缩 + 重复数据删除为我每次备份操作节省了许多千兆字节的网络传输和在整个备份集的云中轻松超过 1 TB 的存储空间(我按月付费)。 如果restic支持压缩,我将能够将备份保留更长时间或降低我的存储成本。

您好@joerg ,感谢您分享您的测试。
您是否尝试过使用 restic 备份 Tar 压缩任务的输出?
我很好奇比较“Restic S3 Remote Compress”和“Tar”+“Restic S3 Remote Upstream”。
此外,你所说的似乎不是真的:

我认为 restic 会通过任何类型的可选压缩获得大量收益,因为它几乎减少了所有内容

从测试结果来看,restic 所需的 CPU 时间似乎是本地备份的 2 倍,还原时的 6 倍。 与 Tar 相比并不好。

tar 不是压缩算法。 当然它很快。
编辑:哦,顺便说一句。 如果你 tar 一个目录,它不会在每个文件中使用多个线程,也不会一次处理两个或更多文件,而是会扫描目录并添加一个文件,然后转到下一个。 很慢。 但问题是存档文件不是为添加多线程而设计的。

从测试结果来看,restic 使用的 CPU 时间似乎在本地备份中慢了 2 倍,在还原时慢了 6 倍。 与 Tar 相比并不好。

我不完全确定你的观点。 当然,restic 比 Tar 慢,但是有压缩的 restic 总是比没有压缩的 restic 快,所以 restic 显然会受益。

Tar 是与“此硬件上的最佳案例”的有用比较,但它缺乏 restic 的大多数其他功能(想到快照和重复数据删除)。 添加压缩似乎只会缩短备份时间、恢复时间和存储成本,所有这些对于备份产品都很重要。

@joerg你的朋友可以打开一个 Pull Request 并公开他们的压缩补丁吗? 他们使用哪种压缩算法?

@joerg @thedaveCA
我很抱歉,我误解了@joerg断言的含义。 显然,有压缩的静止比没有压缩的静止要好。 现在我的问题是:与带有压缩的 restic 相比,Tar + restic 是否更好?

请注意,我们使用的不是裸 tar 档案,而是使用特殊并行 zip 实现的 gzip tar 档案,否则归档 TB 数据将需要几天时间,而不是现在“只需”几个小时: https://gist.github。 com/joerg/b88bf1de0ce824894ffc38f597cfef5f#tarpigz
@shibumi我把这个问题和我的帖子告诉了他们,所以现在取决于他们是否愿意参与其中以及参与的程度。 就个人而言,我希望他们会打开那个拉取请求......

压缩不能用于加密。 它让攻击者可以猜测加密存储库是否包含某个文件,因为文件的一部分(块)被压缩到与所使用的加密密钥无关的相同大小。 这是加密协议的一个众所周知的漏洞,这就是为什么从 TLS 1.3 中删除了压缩。

让我们不要创建一个已知的问题,哪里没有,好吗?

(我认为这个问题已经提到过,甚至可能一次都没有。这个问题仍然是开放的,我觉得因为这个原因,它应该一劳永逸地关闭。)

你为什么要发送垃圾邮件? :(已经讨论了很多次,几乎是题外话。您不会被迫启用压缩!!

此外,我认为您的攻击想法要求攻击者能够控制要压缩和加密的数据(不过我不确定!)。 https://en.m.wikipedia.org/wiki/CRIME

但无论如何,即使是出于安全考虑,有人可能只想对自己控制的存储使用压缩,以简单地节省存储空间。

甚至具有削弱加密的可选功能也会引起错误的安全感。 Restic 声称是一个 _secure_ 备份程序。 添加可选的压缩将使此承诺无效,因为您有时无法确保安全,只能全职,始终。 肯定会有 CVE 报告。 谁希望他们的软件如此“流行”?

但我认为以永远不会与加密一起使用的方式添加压缩是一个可行的选择。

FWIW 在 2017 年我做了一个演示,我从 Restic 中剥离了加密,并表明压缩可以非常有效。 百倍有效。 IIRC 压缩可以像加密一样作为某种包装器添加,但我很久没有查看代码,所以现在事情可能更难或更容易。

其实CRIME需要知道密文的长度,这在restic中基本是不可能的。
也没有“安全”的备份程序。 如果第三方可以访问备份文件,则总是有可能有人篡改或更糟,读取数据。
所以说压缩会使情况变得更糟,这只是愚蠢的。

实际上 CRIME 需要知道密文的长度

犯罪需要,但你不需要。 想象一下,您是一名调查记者,收到了您的消息来源提供的一组绝密文件。 你用加密备份它们,没有人会知道你有这些文件。

现在想象一下你不够聪明来启用压缩,现在其他所有人,碰巧也有这些文件,只是从压缩然后加密的块的大小来判断,会知道你在这个档案中拥有这些绝密文件,而没有甚至需要知道加密密钥。 这远非安全。 人们可能会因为这个“特征”而入狱,受到折磨,或者更糟。

没有“安全”的备份程序

这然后需要更新。

Fast, secure, efficient backup program

还要注意默认安全。

restic 只存储打包的块,所以块的大小并不明显
没有钥匙的人。

2019 年 8 月 9 日星期五上午 02:09:23 -0700,Alexey Kopytko 写道:

压缩不能用于加密。 它让攻击者可以猜测加密存储库是否包含某个文件,因为文件的一部分(块)被压缩到与所使用的加密密钥无关的相同大小。 这是加密协议的一个众所周知的漏洞,这就是为什么从 TLS 1.3 中删除了压缩。

让我们不要创建一个已知的问题,哪里没有,好吗?

——
你收到这个是因为你被提到了。
直接回复此邮件或在 GitHub 上查看:
https://github.com/restic/restic/issues/21#issuecomment -519844526

——
(Escriu-me xifrat si saps PGP / 如果您了解 PGP,请写密码)
PGP 密钥 7CBD1DA5 - https://emailselfdefense.fsf.org/

对于想要了解更多关于这些安全问题的人,有一篇很好的论文描述了它http://www.iacr.org/cryptodb/archive/2002/FSE/3091/3091.pdf
据我所知,如果文件被分块然后压缩和加密,则可能存在缺陷。 但是如果文件在分块之前被压缩,它就像任何其他文件一样是一个二进制文件,那些明文攻击就变得无用了。

但是如果文件在分块之前被压缩,它就像任何其他文件一样是一个二进制文件,那些明文攻击就变得无用了。

那是正确的。 但是,如果我理解正确的话,这不会完全有助于有效的重复数据删除,因为压缩算法可能会为文件的每个版本使用不同的词汇表,从而导致非常不同的二进制结果。 这显然不会重复数据删除。 否则,只有压缩结果块才有意义。

restic 只存储打包的块,所以块的大小对于没有密钥的人来说是不明显的

那是一种解脱。

我的观点仍然成立:当程序将压缩和加密一起实现时,有很多方法可以将隐藏的弱点添加到程序中,所以最好不要添加一个。 甚至加密_专家_决定 TLS 也选择删除压缩。 猜猜他们有类似的推理。

顺便提一句。:

However, it is important to note that these attacks have little security impact on, say, a bulkencryption application which compresses data before encrypting

...
此外,CRIME在您有多个不同版本的加密文件时才有效。
即多次备份运行(到不同的存储库,攻击者在那里获得了所有备份)
它也只是一部分数据量工作。

犯罪需要,但你不需要。 想象一下,您是一名调查记者,收到了您的消息来源提供的一组绝密文件。 你用加密备份它们,没有人会知道你有这些文件。

现在想象一下你不够聪明来启用压缩,现在其他所有人,碰巧也有这些文件,只是从压缩然后加密的块的大小来判断,会知道你在这个档案中拥有这些绝密文件,而没有甚至需要知道加密密钥。 这远非安全。 人们可能会因为这个“特征”而入狱,受到折磨,或者更糟。

那是胡说八道。 因为它只适用于小样本量。 也有可能在没有压缩的情况下入狱。 尤其是在某个时间点,当攻击者获得您的备份文件时,他将来可能会对其进行暴力破解。
将来可能会出现其他安全问题,等等......
讨论变成了毫无意义的恐吓。

@sanmai ,我没有得到这个例子

想象一下你是一名调查记者……现在想象一下你不够聪明,无法启用压缩,现在其他所有人,碰巧也拥有这些文件,仅从压缩然后加密的块的大小来判断,就会知道您在此存档中拥有这些绝密文件,甚至无需知道加密密钥。

什么意思? 有人可以通过查看大小来猜测加密快照具有这些文件吗? 这假设文件是​​单独压缩的,或者与其他已知文件一起压缩。 但是,同样的猜测可以用未加密的 shapshot 来完成。

实际上,在备份之前对文件进行 gzip 怎么样? 这是否也会造成安全漏洞?

我认为这个例子完全是无稽之谈:如果您声称您可以确定快照是否包含您已知的某些(任意)文件的压缩版本,那么您也可以确定它是否包含未压缩的文件。

我不相信压缩会显着降低加密的安全性。

大多数压缩侧信道攻击涉及几个因素:
1)攻击者可以控制输入
2)攻击者可以观察输出的大小
3) 输入数据的微小变化会导致输出大小发生可测量的变化
4)攻击者可以改变输入并重试数十万次

与基于 Web 的系统不同,在绝大多数涉及静态备份的情况下,(1) 和 (2) 很少同时成立。 此外,对于基于块的压缩 (3) 并不能真正保证,并且对于大多数备份机制 (4) 肯定不成立。 因为备份频率通常是一天左右,所以需要数千年的时间才能操作数据并监控压缩的输出大小以发现任何显着差异,并且假设没有其他数据发生变化,在大多数情况下将是。

如果您在输出大小可见的情况下进行备份,那么您可能需要考虑禁用压缩。 否则,实际上没有针对它的实际攻击,并且启用它不会降低安全性。

无论如何,restic 已经进行了重复数据删除,这将它暴露在与压缩侧信道相同的理论攻击中,据我所知,没有人抱怨过这一点。

事实是,有成百上千的用户将从没有任何缺点的压缩功能中受益。 我们可以将这个 5 年前的问题留给正在研究它的开发人员吗?

老实说......我更喜欢restic的概念......但我在我的用例(大量CSV文件和SQL转储)中进行了测试并且不得不切换到borg。

我测试了四代增量备份,我的文件得到了 7:1 的压缩率,再加上重复数据删除,我达到了 > 20:1。 我不能忽视这一点,因为我已经说过我为每 GB 的在线备份存储付费。

root<strong i="7">@xxxx</strong>:~# borg list
2019-08-08_14:37                     Thu, 2019-08-08 14:37:10 [5e113a8102f2bd7e40d100343f849dc73843d145011c7214d5fa0895927eb6d1]
2019-08-08_22:28                     Thu, 2019-08-08 22:28:21 [17d815d000212a576610b2fd5688ab87cce00039bb89f63722c6a7819dec1821]
2019-08-09_02:00                     Fri, 2019-08-09 02:00:23 [217c53b07f30dfbca584c49468cfa624a2445a005890220509c97715f7007e81]
2019-08-10_02:00                     Sat, 2019-08-10 02:00:10 [5dd45b8ccf0aa382bf00d5b08e1d5d88daae014f0a1a42b3e2b0fc368623bba0]
root<strong i="8">@xxxx</strong>:~# borg info
Repository ID: xxxx
Location: ssh://xxxx
Encrypted: Yes (repokey)
Cache: /var/lib/borg/cache/xxxx
Security dir: /var/lib/borg/security/xxxx
------------------------------------------------------------------------------
                       Original size      Compressed size    Deduplicated size
All archives:               69.02 GB             11.24 GB              2.80 GB

                       Unique chunks         Total chunks
Chunk index:                    9227                41812

什么意思? 有人可以_猜测_加密快照具有这些文件吗? 这假设文件是​​单独压缩的,或者与其他已知文件一起压缩。 但是,同样的猜测可以用未加密的 shapshot 来完成。

确切地。 将纯文本文件切成相等的部分,然后压缩,然后加密。 再次切片,压缩和加密。 由于加密文件的大小不会以 AES 方式改变,您会看到在这两种情况下,您都有一个像指纹一样相互匹配的范围大小。 他们(我指的主要是伊朗或俄罗斯等压迫性政权的政府)可以合理假设这些文件存在于此处,因此有理由继续折磨嫌疑人。 我不明白为什么你们都被这些想法冒犯了,它们是不是很容易理解? 这本身不是犯罪,是吗?

但正如@viric之前所指出的,从技术上讲,Restic 不受这些漏洞的影响,因为没有加密密钥就看不到块的大小。 但是如果在某个时候添加压缩,Restic 现在可能仍然不受影响,但以后可能会受到影响。

鉴于 Restic 已经进行了重复数据删除,添加压缩是否会使它暴露于任何其他漏洞?

如果您担心攻击者猜测压缩块的大小以推断未压缩的大小,好吧,但是压缩会使情况变得更糟吗? 攻击者不会拥有相同的基本信息吗?

如果攻击者可以看到每个文件的未压缩和压缩大小,那么识别可能会变得更加真实,但这在静态中是不可能的。

最终,重复数据删除已经使您暴露于我可以看到压缩会产生影响的每一种理论攻击,此外,如果这更适合您的情况,当然可以禁用压缩以保持当前的状态。

我只是不明白你为什么讨论关于通过查看加密块的大小来猜测文件存在的假设安全问题..,

你们使用ZIP还是GZ? 那你应该没问题。

你认为伊朗当局可以通过大小猜出我的内容吗? 然后就不要使用压缩(!)。 这并不意味着压缩不可用。

我认为我们已经涵盖了向 restic 添加压缩的所有相关角度,非常感谢您的所有输入。

我认为我们应该添加压缩并默认启用它,但允许用户禁用压缩。 请耐心等待,直到我有更多时间来处理它。

我觉得这个讨论失控了,所以我现在锁定这个问题。 如果您想继续讨论,请前往论坛。 谢谢!

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

stevesbrain picture stevesbrain  ·  3评论

fbartels picture fbartels  ·  3评论

ikarlo picture ikarlo  ·  4评论

jpic picture jpic  ·  3评论

shibumi picture shibumi  ·  3评论