
JuiceFS 元数据备份与恢复实战指南dump/load 命令、自动备份与跨引擎迁移【免费下载链接】juicefsJuiceFS is a distributed POSIX file system built on top of Redis and S3.项目地址: https://gitcode.com/GitHub_Trending/ju/juicefs导读JuiceFS 是一个构建在 Redis 与 S3 等对象存储之上的分布式 POSIX 文件系统其元数据集中存储在元数据引擎Redis、MySQL、TiKV 等中数据本体则保存在对象存储里。本文基于当前仓库中的 元数据备份和恢复文档 展开系统讲解如何通过dump命令将元数据导出为统一格式的备份文件、如何借助load命令将备份恢复到任意元数据引擎以及客户端每小时自动备份、备份清理、加密文件系统恢复、子目录检视等进阶用法。读完本文你将掌握一套完整的元数据导出—恢复—迁移—排查工作流并理解其底层实现原理。为什么需要统一的元数据备份格式JuiceFS 支持 多种元数据引擎例如 Redis、MySQL/MariaDB、PostgreSQL、SQLite、TiKV、etcd、FoundationDB 等且各引擎内部的数据管理格式各不相同——Redis 使用 key-value 结构关系型数据库则使用多张表存储。若直接依赖各数据库自带的备份工具如 Redis RDB、MySQLmysqldump恢复对象只能是同一种数据库无法跨引擎迁移也难以统一管理。为此JuiceFS 提供了两个管理命令定义于 cmd/dump.go 与 cmd/load.godump将所有元数据以统一格式写入 JSON 或二进制文件用于备份load将备份文件恢复或迁移到任意元数据存储引擎。由于导出格式是统一且通用的所有元数据引擎都能识别并导入因此这套导出导入流程天然支持跨引擎迁移例如从 Redis 迁到 MySQL、从社区版迁移到企业版反之亦然。版本说明JuiceFS v1.0.0 开始支持元数据自动备份v1.0.4 开始支持通过load命令恢复加密的元数据备份v1.3.0 开始支持二进制格式的元数据备份和恢复。备份文件格式JSON 与二进制dump支持两种输出格式二者的设计目标不同格式类型结构特点适用场景体积大小内存占用版本要求JSON 格式完整目录树结构易读中小规模文件系统问题定位较大较高所有版本二进制格式扁平化结构高效紧凑大规模导入导出和迁移约为 JSON 的 1/3 1GiB1 亿文件v1.3.0JSON 格式以嵌套的目录树FSTree、Trash形式组织数据结构清晰、便于人眼阅读和用jq等工具分析二进制格式v1.3.0 引入则以扁平化的 Segment段序列存储体积更小、内存占用更低并支持多线程并发导入导出适合超大规模文件系统。从源码看二进制备份格式pkg/meta/backup.go定义如下文件整体结构为BakSegment... BakEOS BakFooter即若干数据段、一个结束标记BakEOS 0x747083与文件尾部的 Footer 索引每个 Segment 由type length data三部分组成其中 data 是 Protobuf 编码的消息体pb.Format或pb.BatchFooter 记录每种 Segment 类型的数量Num与全部 offset 列表因此可以随机定位并读取任意一个 Segment——这正是load --stat --offset能按偏移查看指定段内容的基础段类型覆盖了format、counter、node、edge、chunk、sliceRef、symlink、sustained、delFile、xattr、acl、stat、quota、parent、changeLog等见 pkg/meta/backup.go。需要说明的是在dump命令中使用--binary时--subdir、--fast、--skip-trash会被忽略见 cmd/dump.go因为它们只对 JSON 格式有意义。手动备份dump 命令详解基本用法使用juicefs dump即可将元数据导出到文件参数为META-URL [FILE]# 导出为 JSON 格式 juicefs dump redis://192.168.1.6:6379/1 meta-dump # 导出为二进制格式 juicefs dump redis://192.168.1.6:6379/1 meta-dump --binary上例中meta-dump是导出的备份文件名文件名和扩展名可以随意调整。特别地若扩展名为.gz如meta-dump.gz导出数据会使用Gzip算法压缩v1.3 版本之后还支持Zstandard压缩使用.zstd作为扩展名。从 cmd/dump.go 的dumpMeta实现可以看到写入文件时采用先写临时文件dst.tmp成功后重命名的原子策略避免中途失败留下半成品压缩级别均使用BestSpeed以追求速度。完整参数一览dump命令支持的选项cmd/dump.go参数说明默认值--subdir仅导出指定子目录的元数据空整棵树--keep-secret-key导出时保留对象存储的密钥信息警告可能导致密钥泄露false--threads导出使用的线程数10--fast将全部元数据加载到内存以加速导出仅 JSON 格式 DB/KV 引擎有效false--skip-trash跳过回收站trash中的文件false--binary导出为二进制格式false行为与安全说明dump命令默认从根目录/开始深度遍历目录树下所有文件将每个文件的元数据信息按 JSON 格式输出对应 pkg/meta/dump.go 中的目录树序列化逻辑出于数据安全考虑对象存储的认证信息Access Key / Secret Key默认不会导出可通过--keep-secret-key显式保留。对应实现在 pkg/meta/backup.go导出format段前若未指定KeepSecret会调用f.RemoveSecret()将密钥置为removedjuicefs dump的价值在于以统一格式导出完整元数据便于管理和保存且不同的元数据存储引擎都能识别并导入。一致性注意事项:::note 注意juicefs dump不提供全局时间点快照功能。若导出过程中业务仍在写入最终结果会包含不同时间点的信息对于特定应用比如数据库这可能意味着导出文件不可用。如果对一致性有更高要求可能需要在导出前确保应用停写。对大规模文件系统如果直接在线上环境进行导出可能影响业务稳定性建议在业务低峰期操作或搭配--fast等加速手段。:::与数据库自带备份相辅相成在实际应用中dump命令与数据库自带的备份工具应共同使用、相辅相成。比如Redis 有自己的 RDB 持久化备份MySQL 有mysqldump。juicefs dump解决的是元数据引擎层面之上的统一格式备份而数据库原生备份则能提供基于存储引擎的物理快照能力两者互补。自动备份客户端每小时自动执行从 JuiceFS v1.0.0 开始不论文件系统通过mount命令挂载还是通过 JuiceFS S3 网关及 Hadoop Java SDK 访问客户端都会每小时自动备份一次元数据并拷贝到对象存储。这意味着即便你不主动执行dump元数据也会被持续保护。备份存放位置备份文件存储在对象存储的meta/目录中它是一个独立于数据存储的目录在挂载点中不可见也不会与数据存储之间产生影响用对象存储的文件浏览器即可查看和管理。文件名格式为dump-2006-01-02-150405.json.gzUTC 时间见 pkg/vfs/backup.go例如调整备份频率--backup-meta自动备份的频率可以在挂载文件系统时通过--backup-meta选项调整其定义在 cmd/flags.go默认值为1h设置为0表示禁用备份。例如要改为每 8 小时备份一次juicefs mount -d --backup-meta 8h redis://127.0.0.1:6379/1 /mnt备份频率可以精确到秒支持的时间单位如下h精确到小时如1hm精确到分钟如30m、1h30ms精确到秒如50s、30m50s、1h30m50s。注意--backup-meta的取值不能小于 5 分钟校验逻辑见 cmd/mount.go。从底层实现pkg/vfs/backup.go可以看出自动备份流程是这样的客户端循环休眠interval/10后先读取根 inode 上的lastBackup扩展属性xattr判断上次备份时间若距上次备份已超过设定间隔则执行备份。备份成功后会更新该全局时间戳因此多客户端共享挂载时不会发生备份冲突——JuiceFS 维护了这个全局时间戳确保同一时刻只有一个客户端执行备份操作当不同客户端设置了不同的备份周期时以周期最短的设置为准。大文件系统自动跳过与参考数据值得一提的是备份操作耗时会随着文件系统内文件数的增多而增加。当文件数较多默认为达到一百万且自动备份频率为默认值 1 小时的情况下JuiceFS 会自动跳过元数据备份并打印相应告警日志见 pkg/vfs/backup.go。此时可以选择挂载一个新客户端并设置较大的--backup-meta参数来重新启用自动备份。作为参考当使用 Redis 作为元数据引擎时备份一百万文件的元数据大约需要 1 分钟消耗约 1GB 内存。:::caution 注意 使用--read-only只读挂载时元数据不会自动备份。 :::备份清理策略自动备份文件不会无限累积JuiceFS 会按照以下规则定期清理对应 pkg/vfs/backup.go 中的rotate函数保留 2 天以内全部的备份超过 2 天不足 2 周的保留每天中的 1 个备份超过 2 周不足 2 月的保留每周中的 1 个备份超过 2 个月的保留每个月中的 1 个备份超过 2 年的备份会被删除。清理只在备份成功后异步触发go cleanupBackups(blob, now)见 pkg/vfs/backup.go避免因清理失败或误删影响可用性。元数据恢复与迁移load 命令详解使用load命令可以将dump导出的元数据恢复到一个空数据库中。注意命令描述中的警告cmd/load.go不要同时使用新旧两个元数据引擎否则可能破坏卷的一致性。# 从 JSON 文件导入 juicefs load redis://192.168.1.6:6379/1 meta-dump # 从二进制备份导入 juicefs load redis://192.168.1.6:6379/1 meta-dump --binary导入元数据时JuiceFS 会重新计算文件系统的统计信息包括空间使用量、inode 计数器等最后在数据库中生成一份全局一致的元数据。这一点从 pkg/meta/dump.go 的loadEntries实现可以印证读取时不是直接信任备份中的计数器而是遍历目录树后重建 countersUsedSpace、UsedInodes、NextInode、NextChunk等并统计 chunk 引用refs。如果你对 JuiceFS 的元数据设计有深入理解还可以在恢复前对元数据备份文件进行修改以此来进行调试。跨引擎迁移示例Redis 到 MySQLdump导出的 JSON 数据统一且通用所有元数据引擎都能识别和导入。因此你不但可以把备份恢复到原有类型的数据库中还可以恢复到其它数据库实现元数据引擎迁移。例如将元数据从 Redis 迁移到 MySQL从 Redis 导出元数据备份juicefs dump redis://192.168.1.6:6379/1 meta-dump.json将元数据恢复到一个全新的 MySQL 数据库juicefs load mysql://user:password(192.168.1.6:3306)/juicefs meta-dump.json另外也可以通过系统的管道STDIN/STDOUT直接迁移无需落盘juicefs dump redis://192.168.1.6:6379/1 | juicefs load mysql://user:password(192.168.1.6:3306)/juicefs从 cmd/load.go 可以看到当只给load传一个参数META-URL时它会从 STDIN 读取备份流从而支持这种管道式迁移。恢复后需要补回对象存储密钥需要注意的是由于dump导出的备份中默认排除了对象存储的 API 访问密钥不论恢复还是迁移元数据完成操作后都需要使用juicefs config命令把文件系统关联的对象存储认证信息再添加回去例如juicefs config --secret-key xxxxx mysql://user:password(192.168.1.6:3306)/juicefsconfig命令的实现见 cmd/config.go它读取当前 format 配置--secret-key、--access-key、--session-token、--bucket等字段会更新到元数据引擎中。事实上load完成后若检测到SecretKey仍为removed会打印告警提示用config命令修正见 cmd/load.go。load命令的其他参数包括--encrypt-rsa-keyRSA 私钥路径、--encrypt-algo加密算法默认aes256gcm-rsa、--binary、--stat、--offset、--threads加载二进制元数据的线程数默认 10仅--binary生效。加密文件系统的备份恢复对于加密的文件系统所有文件都会在本地加密后才上传到后端对象存储包括元数据自动备份文件也会加密后才上传至对象存储。这与dump命令不同dump导出的元数据永远是明文的。因此对于加密文件系统恢复自动备份的元数据时需要额外设置JFS_RSA_PASSPHRASE环境变量并指定 RSA 私钥和加密算法export JFS_RSA_PASSPHRASExxxxxx juicefs load \ --encrypt-rsa-key my-private.pem \ --encrypt-algo aes256gcm-rsa \ redis://192.168.1.6:6379/1 \ dump-2023-03-16-090750.json.gz从 cmd/load.go 的open函数可以看到解密链路先通过object.ParsePrivateKeyFromPem解析 PEM 格式私钥若私钥本身加密则读取JFS_RSA_PASSPHRASE环境变量作为口令缺失时返回明确的错误提示再调用object.NewDataEncryptor构造解密器最终以加密对象存储的方式读取备份文件object.NewEncrypted。--encrypt-algo支持aes256gcm-rsa与chacha20-rsa两种算法。若传入的备份文件同时带有.gz/.zstd压缩后缀还会按后缀自动解压。元数据检视与问题排查导出子目录元数据除了可以导出完整的元数据信息dump命令还支持通过--subdir导出特定子目录中的元数据直观查看指定目录树下所有文件的内部信息inode、属性、chunk 分布等常被用来辅助排查问题juicefs dump redis://192.168.1.6:6379/1 meta-dump.json --subdir /path/in/juicefs对应实现中dump会先对元数据客户端执行Chroot(meta.Background(), metaConf.Subdir)将根切换到指定子目录见 cmd/dump.go再按整棵树的方式导出。另外也可以用jq等工具对导出文件做进一步分析。二进制备份内容分析与排查二进制备份还支持直接查看类型统计、Segment 信息等无需先导入数据库# 查看备份元数据类型统计信息 juicefs load meta-dump --binary --stat # 查看备份元数据 Segments 信息获取 offset juicefs load meta-dump --binary --stat --offset-1 # 查看备份元数据指定 Segment指定 offset信息 juicefs load meta-dump --binary --stat --offset123416309示例输出Backup Version: 1 ----------------------- Name | Num ----------------------- acl | 0 chunk | 1111179 counter | 6 delFile | 0 edge | 1112124 format | 1 … Segment: format Value: { Name: test2, UUID: 15b92123-1395-40e4-a5aa-edb38918985a, Storage: file, Bucket: /home/hjf/.juicefs/local/, BlockSize: 4096, Compression: none, EncryptAlgo: aes256gcm-rsa, TrashDays: 1, MetaVersion: 1, MinClientVersion: 1.1.0-A, DirStats: true, EnableACL: false }--offset-1会列出所有 Segment 类型对应的偏移量--offset具体值则读取并打印该偏移处的单个 Segment 内容。这些功能由 cmd/load.go 中的statBak、showBakSummary、showBakDetail实现前者借助 Footer 索引展示各类型 Segment 的数量及 offset后者通过fp.Seek(offset, io.SeekStart)直接定位并反序列化指定 Segment。注意二进制备份为 PBProtobuf格式也可以自定义工具对备份进行校验和查看。总结围绕 JuiceFS 的元数据管理本文完整覆盖了dump/load命令的两种备份格式JSON 与二进制、手动备份与每小时自动备份、备份清理策略、跨元数据引擎迁移、加密文件系统的恢复以及二进制备份的检视排障。关键要点如下手动备份用juicefs dump支持.gz/.zstd压缩自动备份由挂载客户端默认每小时执行可用--backup-meta调整0可关闭恢复与迁移用juicefs load只能恢复到空数据库备份默认不含对象存储密钥恢复后需用juicefs config补回加密文件系统的自动备份文件是加密的恢复时需提供 RSA 私钥与JFS_RSA_PASSPHRASE大规模场景优先使用 v1.3.0 的二进制格式体积约为 JSON 的 1/3支持并发导入导出与按 Segment 定位检视。相关实现可继续深入阅读cmd/dump.go、cmd/load.go、pkg/vfs/backup.go、pkg/meta/backup.go、pkg/meta/dump.go。【免费下载链接】juicefsJuiceFS is a distributed POSIX file system built on top of Redis and S3.项目地址: https://gitcode.com/GitHub_Trending/ju/juicefs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考