首页
/ rclone Compress 压缩后端实战指南:为任意云端远程叠加 gzip/zstd 透明压缩

rclone Compress 压缩后端实战指南:为任意云端远程叠加 gzip/zstd 透明压缩

2026-09-07 09:58:46作者:贡沫苏Truman

导读

Compress 是 rclone 中一个以"包装(wrap)"方式工作的远程(remote)类型:它把另一个已配置的远程作为底层存储,在上传时对文件进行 gzip 或 Zstandard(zstd)压缩,读取时自动解压,从而让任何云存储远程都具备透明的按文件压缩能力。本文以官方文档 docs/content/compress.md 为主体,结合 backend/compress 的源码实现,讲解它的适用场景、交互式配置、两类压缩算法与压缩级别选择、底层的存储文件布局与命名规则,以及每个配置项的作用和源码级工作机理。读完本文,你将能独立创建一个 Compress 远程,并根据文件类型合理选择算法、级别与缓存参数。

该功能自 rclone v1.54 引入,目前仍处于 实验性(experimental) 阶段。

什么是 Compress 远程:透明压缩而非归档

Compress 的核心思路并不是把多个文件打包成一个压缩归档,而是对单个文件逐个压缩后上传。正如官方文档所述,它最适合"包含大量可压缩大文件"的远程场景——典型如文本日志、CSV 数据导出、JSON 备份等。

从其源码注册信息看(backend/compress/compress.go#L76-L82),它的类型名为 compress,描述为 "Compress a remote",其 Fs 结构体内嵌了一个被包装的底层 fs.Fs

// Fs represents a wrapped fs.Fs
type Fs struct {
	fs.Fs
	wrapper     fs.Fs
	...
}

也就是说,所有读写请求最终都会被转发给 remote 选项中指定的那个底层远程。用户日常使用 rclone 时,只需要把路径前缀写成 compress:,后续的 copysyncmountserve 等命令一律照常工作,压缩与解压对操作者透明。

实验性状态警告

在投入生产使用前,请务必正视官方给出的实验性声明:

  • 该远程目前处于 experimental 状态,可能出现故障或数据丢失;
  • 使用者的任何操作都自行承担风险;
  • 请勿在关键应用中依赖此远程。

这意味着在正式环境大规模使用前,应先在小范围、可重建的数据集上充分验证,并保留原始数据备份。

交互式创建 Compress 远程

创建方式与普通远程无异——运行 rclone config,选择类型 compress,然后回答两个必填问题(目标远程、压缩方式)即可。官方文档给出的完整交互流程如下:

$ rclone config
Current remotes:

Name                 Type
====                 ====
remote_to_press      sometype

e) Edit existing remote
n) New remote
d) Delete remote
r) Rename remote
c) Copy remote
s) Set configuration password
q) Quit config
e/n/d/r/c/s/q> n
name> compress

Option Storage.
Type of storage to configure.
Choose a number from below, or type in your own value.
...
12 / Compress a remote
   \ (compress)
...
Storage> compress

Option remote.
Remote to compress.
Enter a value.
remote> remote_to_press:subdir

Option mode.
Compression mode.
Choose a number from below, or type in your own value of type string.
Press Enter for the default (gzip).
 1 / Standard gzip compression with fastest parameters.
   \ (gzip)
 2 / Zstandard compression — fast modern algorithm offering adjustable speed-to-compression tradeoffs.
   \ (zstd)
mode> gzip

Option level.
GZIP (levels -2 to 9):
- -2 — Huffman encoding only. Only use if you know what you're doing.
- -1 (default) — recommended; equivalent to level 5.
- 0 — turns off compression.
- 1–9 — increase compression at the cost of speed. Going past 6 generally offers very little return.

ZSTD (levels 0 to 4):
- 0 — turns off compression entirely.
- 1 — fastest compression with the lowest ratio.
- 2 (default) — good balance of speed and compression.
- 3 — better compression, but uses about 2–3x more CPU than the default.
- 4 — best possible compression ratio (highest CPU cost).

Notes:
- Choose GZIP for wide compatibility; ZSTD for better speed/ratio tradeoffs.
- Negative gzip levels: -2 = Huffman-only, -1 = default (≈ level 5).
Enter a value.
level> -1

Edit advanced config?
y) Yes
n) No (default)
y/n> n

Configuration complete.
Options:
- type: compress
- remote: remote_to_press:subdir
- mode: gzip
- level: -1
Keep this "compress" remote?
y) Yes this is OK (default)
e) Edit this remote
d) Delete this remote
y/e/d> y

上面示例中的配置要点可以拆解如下:

  • remote:填写一个已经存在的远程,可以带上子目录前缀(如 remote_to_press:subdir),最终所有压缩文件都会写入该前缀下;
  • mode:gzip(默认)或 zstd;
  • level:与所选 mode 匹配的压缩级别,回车使用当前 mode 的默认值。

防止自我引用

源码在 NewFs 中会做一项安全校验(backend/compress/compress.go#L197-L200):

remote := opt.Remote
if strings.HasPrefix(remote, name+":") {
	return nil, errors.New("can't point press remote at itself - check the value of the remote setting")
}

即如果 remote 选项指向了 compress 远程自身(remote 前缀等于当前远程名加冒号),会直接报错 "can't point press remote at itself",避免形成无限嵌套的包装。

压缩算法与级别选择

GZIP:广泛兼容的经典选择

GZIP 是历史悠久、部署最广的压缩算法,在压缩速度与压缩比之间取得均衡。它支持的级别区间为 -2 到 9,其默认值含义与常见的 zlib/gzip 有所不同:

GZIP 级别 含义
-2 仅 Huffman 编码,不进行 LZ 匹配,除非清楚自己在做什么否则不建议使用
-1(默认) 官方推荐,约等价于常规 level 5,是大多数场景下的有效折中
0 关闭压缩(仅封装)
1–9 级别越高压缩率越高、速度越慢;超过 6 后收益通常很小

源码中 GZIP 走的是 gzipModeHandlerbackend/compress/gzip_handler.go),其压缩器基于 github.com/buengese/sgzip 提供的可随机读取的 gzip 实现:

gz, err := sgzip.NewWriterLevel(pipeWriter, f.opt.CompressionLevel)

sgzip 属于"可 seek 的 gzip"实现,它在标准 gzip 流上附加了块索引元数据,这正是 Compress 远程能对压缩文件进行随机读取(按 offset/range 读取)的基础。

Zstandard(zstd):现代高性能选择

zstd 是 Facebook 开源的现代压缩算法,压缩/解压速度出色,且能以精细的级别调节"速度 ↔ 压缩率"平衡。Compress 远程为 zstd 开放了 0 到 4 的级别范围:

ZSTD 级别 含义
0 完全关闭压缩
1 最快压缩、压缩率最低
2(默认) 速度与压缩率的良好平衡
3 压缩率更好,但 CPU 开销约为默认级的 2–3 倍
4 最高压缩率(CPU 开销最大)

源码中 zstd 由 zstdModeHandlerbackend/compress/zstd_handler.go)驱动,编码器来自 github.com/klauspost/compress/zstd

writer, err := NewWriterSzstd(pipeWriter, zstd.WithEncoderLevel(zstd.EncoderLevel(f.opt.CompressionLevel)))

注意这里不是直接用裸 zstd 流,而是经 backend/compress/szstd_helper.go 封装成了 szstd(zstd-seekable-format):文件按 1 MiB 的分块独立压缩,并记录每块的压缩偏移量 BlockData 与原始大小,从而支持按需解压某一范围的数据而无需解压整个文件。

如何选择

  • 追求兼容性:选 GZIP,任何解压工具都能直接打开产物文件;
  • 追求速度与压缩率权衡:选 ZSTD,在 CPU 有限或文件极多时收益更明显;
  • 如果你不确定级别,直接回车使用默认值即可:gzip 默认 -1(≈level 5),zstd 默认 2

存储到远程的文件:数据文件与元数据文件

当你用 rclone lsf 之类的命令直接查看底层远程时,会看到大量带压缩算法扩展名的文件(.gz.zst)。官方文档特别强调了两条规则:

  1. 这些文件是标准的压缩文件,任何解压程序都可以打开并解压;
  2. 但它们携带 rclone 可用的隐藏元数据。你可以随意下载解压这些文件,但绝不要手动删除或重命名——缺少配套元数据文件的文件将无法被 rclone 识别。

从源码中可以还原出远程上的真实布局(backend/compress/compress.go#L46-L50):

gzFileExt           = ".gz"
zstdFileExt         = ".zst"
metaFileExt         = ".json"
uncompressedFileExt = ".bin"

也就是说,上传一个名为 log.txt 的文件后,在底层远程中实际会看到两类对象:

  • 数据文件log.txt.<base64原始大小>.gz(或 .zst),存放压缩后的内容;
  • 元数据文件log.txt.json,存放 JSON 格式的 ObjectMetadatabackend/compress/compress.go#L1073-L1081),记录压缩模式、原始大小、原始文件 MD5、MIME 类型,以及用于随机读取的压缩块元数据:
type ObjectMetadata struct {
	Mode                    int                 // Compression mode of the file.
	Size                    int64               // Size of the object.
	MD5                     string              // MD5 hash of the file.
	MimeType                string              // Mime type of the file
	CompressionMetadataGzip *sgzip.GzipMetadata // Metadata for Gzip compression
	CompressionMetadataZstd *SzstdMetadata      // Metadata for Zstd compression
}

元数据对象与数据对象是成对管理的:Object 同时持有数据对象与元数据对象(backend/compress/compress.go#L1084-L1091);执行删除时 Object.Remove 会同时移除元数据文件与数据文件;执行 ChangeNotify 监视时,只跟踪元数据文件的变更(因为哈希就藏在元数据里)。

命名规则:文件名中的 base64 大小

官方文档说明了命名规则:压缩文件名形如 *.###########.gz,其中 * 是原始文件名,# 部分是未压缩文件大小的 base64 编码。更精确地讲:

文件名中编码原始大小有一个重要原因:它让 rclone 在不下载整个文件的情况下,仅凭文件名即可获知原始文件大小,从而在 ListSize() 等操作中免于拉取元数据。同理,官方要求"文件名不应由 rclone 压缩后端以外的任何东西更改"——改名会破坏这一信息,导致无法识别。

另外值得注意的是:并非所有文件都会被压缩。上传流程会先做可压缩性启发式判断:取前 1 MiB(heuristicBytes = 1048576)数据进行试压缩,只有当 原始字节数 / 压缩后字节数 > 1.1minCompressionRatio,见 backend/compress/compress.go#L42-L44)时才会真正压缩;否则文件以 .bin 扩展名原样存储,返回的"原始大小"用哨兵值 -2 表示(backend/compress/compress.go#L313-L336)。这一点从 uncompressedModeHandlerbackend/compress/uncompressed_handler.go)中 isCompressible 恒返回 false 也能印证。

配置项速查

以下选项在 rclone config 中配置,同时也可通过 rclone config create 命令或环境变量设置。下文以官方文档的选项说明为准,并给出源码注册信息(backend/compress/compress.go#L83-L121)作为补充。

标准选项

--compress-remote(必填)

  • Config 键:remote
  • 环境变量:RCLONE_COMPRESS_REMOTE
  • 类型:string
  • Required:true

要被压缩的底层远程,支持 remote:remote:subdir 形式。

--compress-mode

  • Config 键:mode
  • 环境变量:RCLONE_COMPRESS_MODE
  • 类型:string
  • 默认值:"gzip"
  • 可选值:
    • gzip — Standard gzip compression with fastest parameters.
    • zstd — Zstandard compression — fast modern algorithm offering adjustable speed-to-compression tradeoffs.

源码将 mode 字符串映射为整型常量 Uncompressed=0 / Gzip=2 / Zstd=4,再据此选择对应 handler(backend/compress/compress.go#L285-L295);遇到无法识别的模式名会被当作 Uncompressed 处理,行为上等同"存储但不压缩"。

--compress-level(必填)

  • Config 键:level
  • 环境变量:RCLONE_COMPRESS_LEVEL
  • 类型:string(提示文本随 mode 变化,具体级别说明见上文两个算法小节)
  • Required:true

交互式向导会根据所选 mode 展示对应的级别说明文本。注意:虽然配置键类型为 string,但最终解析进 Options.CompressionLevel intbackend/compress/compress.go#L167-L172)供各 handler 使用。

高级选项

--compress-ram-cache-limit

  • Config 键:ram_cache_limit
  • 环境变量:RCLONE_COMPRESS_RAM_CACHE_LIMIT
  • 类型:SizeSuffix
  • 默认值:20Mi

部分远程(如不支持流式上传、需要预先知道文件大小的后端)不允许上传大小未知的文件。此时压缩后文件的真实大小要到压缩完成后才能确定,因此需要先把压缩结果缓存起来以确定其大小。此参数用于决定缓存介质:

  • 小于该上限的文件在 RAM 中缓存;
  • 大于该上限的文件在磁盘上缓存。

对应实现是 Fs.rcatbackend/compress/compress.go#L561-L606):先用上限大小的缓冲区读取,若文件较小则直接在内存中走普通 Put;否则检查底层远程是否支持 PutStream 流式上传,支持则流式上传,不支持则在磁盘创建临时文件(os.CreateTemp("", "rclone-press-"))缓存后转普通上传。

--compress-description

  • Config 键:description
  • 环境变量:RCLONE_COMPRESS_DESCRIPTION
  • 类型:string
  • Required:false

该远程的描述信息,属于 rclone 各后端通用的描述字段,不参与压缩逻辑。

元数据支持

Compress 会透传读写底层远程支持的任何元数据(metadata)。当底层后端支持时,fs.RegInfo.MetadataInfo 声明 "Any metadata supported by the underlying remote is read and written"(backend/compress/compress.go#L80-L82)。关于 rclone 元数据机制的完整说明见仓库的 Metadata 文档(对应官方文档中的 metadata 页面)。

透明读写背后的源码工作流

上传(Put):先判可压缩性,再决定"压缩上传"还是"原样上传"

Fs.Put 的流程是(backend/compress/compress.go#L729-L746):

  1. 若目标对象已存在,则转为其 Update 流程;
  2. 否则调用 checkCompressAndTypebackend/compress/compress.go#L517-L534),读取前 1 MiB 数据:用 mimetype.Detect 判定 MIME 类型,并用当前 mode 的 handler 试压缩计算压缩比;
  3. putWithCustomFunctions 根据判定结果走 putCompress(压缩上传)或 putUncompress(以 .bin 原样上传);
  4. 数据上传成功后,校验源声明的字节数与实际压缩得到的原始大小一致——因为文件名内嵌了原始大小,大小不匹配会导致文件无法再被正确读取,此时会删除已上传的对象并报错;
  5. 最后 putMetadata 把 JSON 元数据写入 *.json 对象;若元数据上传失败,会回滚删除数据对象。

压缩上传本身也值得关注:gzip/zstd handler 内用 io.Pipe() + 独立 goroutine 边压缩边上传,并在压缩同时用 io.TeeReader 计算原始数据的 MD5 存进元数据。Fs.Hashes() 只声明 MD5(backend/compress/compress.go#L794-L797),而读取哈希时直接返回元数据里存好的原始文件 MD5——这是对外表现为"哈希仍可用"的原因。

下载(Open):只解压所需部分

Object.Openbackend/compress/compress.go#L1345-L1369)的路径为:

  • 未压缩模式(.bin)直接透传给底层对象;
  • 压缩模式则解析 SeekOption / RangeOption 得到 offset 与 limit,使用 chunkedreader(初始块 256 KiB、最大块 8 MiB,见 backend/compress/compress.go#L37-L40)读取底层数据,再交给对应 handler:
    • gzip:offset 为 0 时用 sgzip.NewReader 顺序解压;offset 非 0 时用 sgzip.NewReaderAt 借助块索引定位到目标位置附近开始解压(backend/compress/gzip_handler.go#L53-L81);
    • zstd:使用 szstd 的块表(SzstdMetadata.BlockData)精确定位到需要解压的 1 MiB 块,并行解码所需块后按序拼接,从而实现真正的随机范围读取(backend/compress/szstd_helper.go#L188-L318)。

正因为随机读取能力的存在,rclone cat --offsetrclone servemount 等依赖 range 请求的场景在 Compress 远程上也能正常工作——这也解释了为什么元数据中必须保存每块的压缩偏移量与原始大小。

其他行为:服务端复制/移动、特性掩码与目录操作

Fs 注册了大量可选接口(见 backend/compress/compress.go#L1509-L1531),例如 CopyMoveDirMovePurgeAboutCleanUpPublicLinkChangeNotify 等。其策略是:

  • 多数操作直接透传给底层远程(例如 MkdirRmdirPrecision);
  • Copy/Move 需要特殊处理,因为压缩对象涉及数据文件与元数据文件一对对象的同步拷贝/移动,且文件名受原始大小影响,重名对象需先删除旧文件,所以 rclone 优先尝试底层远程的服务端 Copy/Move 能力;
  • 特性列表通过 Fill → Mask → WrapsFs 与底层远程做"与"运算(backend/compress/compress.go#L254-L272),并对"需要底层支持服务端 Move 才可用的 PutStream"做了特殊裁剪;
  • 值得一提的还有 Fs.PutStream:当发现旧对象是压缩的或新内容可压缩时,上传完成后需要借助 operations.Move 把对象重命名为携带正确大小的文件名(backend/compress/compress.go#L748-L784)。

目录列表:隐藏实现细节

List/ListR/ListP 都会经过 processEntriesbackend/compress/compress.go#L404-L420)对底层条目做"翻译":

  • .json 元数据文件在列表中被隐藏(数据文件才是真实对象);
  • 数据文件被解析回原始文件名,并以"newObjectSizeAndNameOnly"的方式优先用文件名内嵌的原始大小构建对象;只有真正访问(下载、查哈希、看元数据)时才按需加载 JSON 元数据(懒加载,见 loadMetadataIfNotLoaded)。

这正是用户在 compress: 路径下看到的是"干净"的原始目录结构、而直接看底层远程却满是 .gz/.zst/.json 的原因。

验证与测试

仓库通过 backend/compress/compress_test.go 对后端进行验证:

  • TestIntegration 走通用集成测试套件 fstests.Run
  • TestRemoteGzipTestRemoteZstd 分别以本地临时目录为底层,创建 type=compressremote=<tempdir>mode=gzip/level=-1mode=zstd/level=2 的配置并跑完整测试集,覆盖了两种压缩模式下的文件系统接口一致性。

如果你在本地构建了 rclone,也可以用命令直接体验,例如把本地目录压缩进 S3:

rclone config create press compress remote mys3:bucket/press mode gzip level -1
rclone copy ./logs press:archive-logs
rclone lsf press:

第一条命令用非交互方式创建名为 press 的 Compress 远程;第二条命令上传时会自动执行"可压缩性判断 → 压缩/原样 → 写入数据与元数据"的完整链路;第三条命令列出时看到的将是原始文件名而非 .gz 文件。

使用注意事项小结

  • 不要手动删除/重命名底层远程上的 .gz/.zst/.json 文件.json 是 rclone 解析的关键,数据文件与元数据文件必须成对存在;
  • 底层远程必须用其它工具单独查看时,请把它视为"压缩后的仓库",任何绕过 rclone 的写操作都可能导致列表中出现无法识别的孤儿文件;
  • 本已高度压缩的文件(图片、视频、已压缩归档),上传前会被启发式判定为"不可压缩"并原样存储为 .bin,这是设计使然,可避免无谓的 CPU 开销;
  • 若底层远程不支持未知大小上传,请留意 --compress-ram-cache-limit 对内存/磁盘占用的影响;
  • 该远程仍属实验特性,涉及重要数据时应先小规模验证并保留原始副本。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388