SeaweedFS 数据完整性校验方案:S3 SHA256 校验与 filer.sync verifySync
文章目录SeaweedFS 数据完整性校验方案S3 SHA256 校验与 filer.sync verifySync一、为什么需要数据完整性校验二、第一阶段客户端上传到 SeaweedFS 的完整性校验2.1 使用 SHA256三、SeaweedFS 的 S3 SHA256 校验四、为什么 ETag 不能直接当 SHA256五、推荐的 S3 上传校验流程六、这里有一个非常重要的区别七、大文件是否仍然需要 Multipart Upload八、第二阶段本地 SeaweedFS 同步到 NAS SeaweedFS九、filer.sync 的问题十、PR #9284增加 -verifySync十一、verifySync 比较什么11.1 MISSING11.2 SIZE_MISMATCH十二、ETAG_MISMATCH十三、verifySync 的比较算法十四、为什么 verifySync 不直接重新计算 SHA256十五、verifySync 的基本使用十六、为什么需要 -modifyTimeAgo十七、verifySync 可以发现哪些问题十八、verifySync 的 JSON 输出十九、一个值得注意的诊断能力mtime二十、两个校验机制的关系第一层S3 SHA256第二层verifySync二十一、最终推荐的数据完整性方案第一级上传时校验二十二、第二级同步过程中依靠 filer.sync二十三、第三级定期 verifySync二十四、完整架构二十五、两种校验的能力对比二十六、需要注意verifySync 不是“绝对意义上的 SHA256 全量校验”二十七、最终结论SeaweedFS 数据完整性校验方案S3 SHA256 校验与 filer.sync verifySync在使用 SeaweedFS 作为图片、ZIP 包等文件的存储系统时仅仅确认“上传成功”是不够的。例如客户端 │ │ S3 上传 ▼ 本地 SeaweedFS │ │ filer.sync ▼ NAS SeaweedFS这里实际上存在两个不同的数据完整性问题客户端 → 本地 SeaweedFS文件上传完成以后需要确认 SeaweedFS 中保存的对象和客户端原始文件内容一致。本地 SeaweedFS → NAS SeaweedFS数据经过filer.sync同步以后需要确认 NAS 上的数据和源 SeaweedFS 中的数据一致。这两个场景虽然都叫“完整性校验”但校验对象和实现方式并不一样。SeaweedFS 最近的两个 PR 正好分别解决了这两个问题[PR #8914SeaweedFS S3 SHA256 校验支持][PR #9284为 filer.sync 增加-verifySync校验模式]因此可以形成一套比较完整的数据完整性验证方案SHA256 客户端文件 ─────────────────► 本地 SeaweedFS │ │ filer.sync ▼ NAS SeaweedFS │ verifySync │ ▼ 检查同步结果一、为什么需要数据完整性校验假设系统每天产生大量检测数据test.zip board_001/ original.jpg defect_001.jpg defect.json index.json客户端将这些数据打包成 ZIP 后上传客户端 │ │ test.zip ▼ SeaweedFS如果接口返回HTTP 200 OK只能说明这一次 HTTP/S3 操作成功完成。它不能直接证明客户端文件 SeaweedFS 中最终保存的数据同样SeaweedFS 再将数据同步到 NASSeaweedFS A │ │ filer.sync ▼ SeaweedFS B即使filer.sync没有报告明显错误也最好能够定期检查A 中存在的文件 ↓ B 中是否存在 文件大小 ↓ 是否一致 ETag ↓ 是否一致所以完整性验证最好分成两个阶段。二、第一阶段客户端上传到 SeaweedFS 的完整性校验2.1 使用 SHA256SHA256 是一种密码学哈希算法。对于一个文件test.zip计算SHA256(test.zip)得到一个固定长度的 256 bit也就是 32 字节的摘要。通常表示成 64 个十六进制字符8f434346648f6b96df89dda901c51713...其核心特点是文件内容相同 ↓ SHA256 相同 文件内容发生变化 ↓ SHA256 几乎必然不同因此可以使用客户端 SHA256 ↓ SeaweedFS SHA256 ↓ 比较判断上传后的对象内容是否一致。三、SeaweedFS 的 S3 SHA256 校验SeaweedFS 的 S3 接口支持 AWS S3 的 checksum 机制。这个问题在 SeaweedFS 的 issue #8911 中也有体现早期通过 S3 上传时指定aws s3cpmyfile.txt s3://mybucket/ --checksum-algorithm SHA256虽然上传可以成功但通过 HEAD 获取对象信息时原来的行为并不能直接得到用户期望的 SHA256而是看到传统的 ETag。PR #8914 正是针对这一类 SHA256 checksum 能力进行完善。因此使用支持该能力的 SeaweedFS 版本后可以通过 S3 checksum 机制获取对象的 SHA256 信息。四、为什么 ETag 不能直接当 SHA256这是实际使用过程中非常容易混淆的一点。很多人第一次看到ETag: b772130fb9ef62ef8ef7b29cbed07113会认为它就是文件的 MD5 或 SHA256。实际上不能这样简单理解。对于普通的单次上传对象ETag 经常表现为 MD5但它并不是 S3 标准意义上的“文件 SHA256”。特别是 Multipart Upload文件 │ ├── Part 1 ├── Part 2 ├── Part 3 └── Part 4最终 ETag 的计算方式可能与单个完整文件的 MD5 完全不同。因此ETag ≠ SHA256更准确地说ETag ↓ 对象标识/兼容性校验信息 ChecksumSHA256 ↓ 明确的 SHA256 checksum如果系统真正要求验证上传后的对象是否和客户端原始文件内容完全一致那么应该优先使用明确的 checksum而不是把 ETag 当成 SHA256。五、推荐的 S3 上传校验流程假设客户端原始文件test.zip首先在客户端计算 SHA256Get-FileHash.\test.zip-Algorithm SHA256得到Algorithm : SHA256 Hash : ABCDEF...... Path : F:\test.zip然后通过 S3 上传aws s3cp.\test.zip s3://test/test.zip --endpoint-url http://172.29.2.244:8333 --checksum-algorithm SHA256上传完成后可以通过aws s3api head-object --bucket test --key test.zip --endpoint-url http://172.29.2.244:8333 --checksum-mode ENABLED查看对象的 checksum 信息。如果服务端返回ChecksumSHA256则可以将它与客户端计算出的 SHA256 进行比较。六、这里有一个非常重要的区别客户端计算的SHA256(原始文件)和 S3 checksum 返回的ChecksumSHA256只有在 checksum 的计算对象、编码方式和上传过程符合预期时才能直接比较。因此不能简单地看到ChecksumSHA256 ! Get-FileHash就立即判断SeaweedFS 把文件存坏了。S3 checksum 在协议层存在特定的表示和校验规则尤其是涉及 Multipart Upload 时更应该区分完整对象 SHA256和Multipart 各 Part checksum这也是为什么在大文件场景下不能只把 ETag 当作文件 SHA256。七、大文件是否仍然需要 Multipart Upload需要。SHA256 校验并不意味着必须把整个文件一次性上传。例如10 GB test.zip完全可以10 GB │ ├── Part 1 100 MB ├── Part 2 100 MB ├── Part 3 100 MB ├── ... └── Part N然后通过 Multipart Upload 完成整个对象。数据完整性和上传方式实际上是两个不同的问题Multipart Upload ↓ 解决“大文件怎么可靠上传” Checksum / SHA256 ↓ 解决“上传后的数据是否正确”所以实际生产系统更合理的组合是大文件 ↓ Multipart Upload ↓ Checksum ↓ CompleteMultipartUpload ↓ 最终对象校验八、第二阶段本地 SeaweedFS 同步到 NAS SeaweedFS第一阶段解决客户端 ↓ 本地 SeaweedFS但是你的实际架构还存在第二条链路本地 SeaweedFS │ │ filer.sync ▼ NAS SeaweedFS这里需要解决的是另外一个问题filer.sync 执行以后NAS 上的数据是否真的和源 SeaweedFS 一致这就是 PR #9284 的-verifySync。九、filer.sync 的问题filer.sync的作用是把一个 Filer 中的文件同步到另一个 Filer。例如生产 SeaweedFS 172.29.2.100 │ │ filer.sync ▼ NAS SeaweedFS 172.29.2.200正常情况下source │ ├── a.zip ├── b.zip ├── c.zip └── d.zip target │ ├── a.zip ├── b.zip ├── c.zip └── d.zip但是实际环境可能发生source target a.zip a.zip ✓ b.zip b.zip ✓ c.zip 缺失 ✗ d.zip d.zip 内容不同 ✗仅仅观察同步程序是否运行并不能完全说明两个集群的数据一致。因此需要一个独立的Verification过程。十、PR #9284增加-verifySyncSeaweedFS PR #9284 增加了-verifySync用于比较两个 Filer 中的目录和文件而不是执行同步。该 PR 已于 2026 年 4 月 29 日合并到 master。它解决的问题非常明确比较 Filer A 和 Filer B验证 Active/Passive 同步目标是否与源端一致。实现方式不是重新下载所有文件而是比较 Filer 中的目录和文件信息。十一、verifySync 比较什么目前主要比较文件是否存在 文件大小 ETag因此可以发现几类问题。11.1 MISSING源端存在/test/a.zip目标端不存在/test/a.zip结果MISSING说明同步后文件缺失。11.2 SIZE_MISMATCH例如Source: a.zip 100 MB Target: a.zip 80 MB结果SIZE_MISMATCH这种情况通常说明文件没有完整同步目标端存在残缺对象同步过程中出现异常目标端存在错误的 stub/entryPR 的实际测试中就发现了多个 size mismatch。十二、ETAG_MISMATCH假设Source: a.zip Size 100 MB ETag ABC123 Target: a.zip Size 100 MB ETag DEF456虽然Size 相同但是ETag 不同于是ETAG_MISMATCH这非常重要。因为Size 相同并不能证明文件内容相同例如Source: AAAA... 100 MB Target: BBBB... 100 MB大小完全一样但是内容已经不同。因此Size ETag 比单纯比较Size 可靠得多。十三、verifySync 的比较算法PR #9284 并不是把两个集群的所有文件全部加载到内存后再比较。它利用 FilerListEntries的名称排序特性对两个目录进行Sorted Merge例如源端A B C D目标端A B D E通过两个指针进行比较A A OK B B OK C D MISSING D D OK EOF E ONLY_IN_B这种方式的时间复杂度为O(N)而内存主要与单个目录中的 entries 数量有关而不是整个集群文件总数。PR 描述中明确采用了目录级 sorted merge并使用并发 worker 递归处理子目录。十四、为什么 verifySync 不直接重新计算 SHA256这是非常重要的设计点。假设 NAS 中有10 TB数据。如果 verifySync 每次都读取 10 TB ↓ 计算 SHA256 ↓ 再读取源端 10 TB ↓ 计算 SHA256 ↓ 比较那么一次完整校验就需要大量磁盘 IO 和网络 IO。而 verifySync 的目的主要是快速发现同步后的文件集合和对象元数据是否存在差异。所以采用存在性 Size ETag进行比较。这是一种Metadata-level verification而不是Full-content SHA256 verification因此两种机制其实是互补的。十五、verifySync 的基本使用例如weed filer.sync\-afilerA:8888\-bfilerB:8888\-isActivePassive\-verifySync\-modifyTimeAgo1h这里-a表示源 Filer。-b表示目标 Filer。-isActivePassive表示按照 Active → Passive 的方向检查。-verifySync表示只验证不执行同步。-modifyTimeAgo1h表示忽略最近 1 小时内修改的文件。这个参数非常重要。十六、为什么需要-modifyTimeAgo假设10:00 源端开始上传 test.zip 10:00:30 filer.sync 正在同步 10:00:40 verifySync 开始检查这时候源端 test.zip ✓ 目标端 test.zip 正在同步如果立即检查SIZE_MISMATCH并不一定意味着数据损坏。可能只是sync 尚未完成因此可以设置-modifyTimeAgo1h表示只检查1 小时以前已经稳定的数据。这样可以避免把正常的同步延迟误报为数据损坏。PR #9284 就针对这种场景提供了 modification-time cutoff。十七、verifySync 可以发现哪些问题可以把结果理解为状态含义OK文件存在、Size 和 ETag 一致MISSING源端有目标端没有ONLY_IN_B目标端有源端没有SIZE_MISMATCH文件大小不同ETAG_MISMATCH文件大小相同但 ETag 不同例如[MISSING] /data/a.zip [SIZE_MISMATCH] /data/b.zip [ETAG_MISMATCH] /data/c.zip这样就可以快速定位同步异常。PR 的实际测试中针对约 24,107 个文件进行验证时发现Missing: 2 Size mismatch: 10 ETag mismatch: 1最终共发现 13 个异常。这也说明verifySync不只是一个理论功能它可以实际发现同步链路中的问题。十八、verifySync 的 JSON 输出PR #9284 还增加了-verifyJsonOutput可以输出 NDJSON。例如weed filer.sync\-afilerA:8888\-bfilerB:8888\-isActivePassive\-verifySync\-verifyJsonOutput每一行对应一个 JSON 对象。这样非常适合接入监控系统 日志系统 自动化脚本 告警系统例如SeaweedFS │ ▼ verifySync │ ▼ NDJSON │ ├── 日志 ├── Prometheus exporter ├── 告警程序 └── 数据完整性报告PR 中明确设计了 NDJSON 输出并在最终输出中提供 SUMMARY 信息。十九、一个值得注意的诊断能力mtimeverifySync不仅报告SIZE_MISMATCH ETAG_MISMATCH还会结合源端和目标端的修改时间进行辅助判断。例如B_NEWER可能提示late_updates_skip_likely而A_NEWER可能提示sync_lag_or_event_miss如果A.mtime B.mtime但ETag 不一致则更值得怀疑chunk-level corruption也就是数据块层面的异常而不是简单的同步延迟。二十、两个校验机制的关系到这里可以看到数据完整性 │ ┌──────────┴──────────┐ │ │ 上传完整性 同步完整性 │ │ ▼ ▼ S3 SHA256 verifySync │ │ 客户端 ↔ 本地 本地 ↔ NAS │ │ ▼ ▼ ChecksumSHA256 Size ETag两者解决的是完全不同的问题。第一层S3 SHA256回答我上传到 SeaweedFS 的文件是不是原始文件Client │ │ SHA256 ▼ SeaweedFS │ │ ChecksumSHA256 ▼ Compare第二层verifySync回答filer.sync 到 NAS 后NAS 上的数据是不是和源端一致SeaweedFS A │ │ filer.sync ▼ SeaweedFS B │ │ verifySync ▼ Compare: Path Size ETag二十一、最终推荐的数据完整性方案对于实际生产环境可以采用三级设计。第一级上传时校验客户端原始文件 │ ├── 计算 SHA256 │ ▼ S3 Multipart Upload │ ▼ SeaweedFS上传完成以后S3 HEAD │ ▼ ChecksumSHA256 │ ▼ 与客户端 SHA256 比较如果不一致上传失败 或者重新上传二十二、第二级同步过程中依靠 filer.sync正常数据流本地 SeaweedFS │ │ filer.sync ▼ NAS SeaweedFS此阶段主要关注同步进度 同步错误 网络中断 同步延迟二十三、第三级定期 verifySync不要只依赖filer.sync 正常运行建议定期执行verifySync例如每小时 ↓ 检查过去 1 小时以前的数据或者每天凌晨 ↓ 执行一次完整校验例如weed filer.sync\-alocal-filer:8888\-bnas-filer:8888\-isActivePassive\-verifySync\-modifyTimeAgo1h然后根据退出状态和 JSON 输出进行告警。二十四、完整架构最终可以形成┌─────────────────────┐ │ 客户端 │ │ │ │ 原始文件 │ │ SHA256 │ └──────────┬──────────┘ │ │ S3 │ ▼ ┌─────────────────────┐ │ 本地 SeaweedFS │ │ │ │ S3 Gateway │ │ Filer │ │ Volume │ └──────────┬──────────┘ │ ChecksumSHA256 │ 上传完整性 │ ▼ ┌─────────────────────┐ │ filer.sync │ │ │ │ 本地 → NAS │ └──────────┬──────────┘ │ ▼ ┌─────────────────────┐ │ NAS SeaweedFS │ │ │ │ Filer Volume │ └──────────┬──────────┘ │ verifySync │ ┌─────────────┼─────────────┐ │ │ │ Missing Size mismatch ETag mismatch │ │ │ └─────────────┴─────────────┘ │ ▼ 告警二十五、两种校验的能力对比项目S3 SHA256verifySync校验方向客户端 → SeaweedFSSeaweedFS → SeaweedFS主要目的上传完整性同步完整性校验文件内容SHA256间接通过 ETag 等元数据检查文件缺失否是检查文件大小不主要依赖是检查 ETag否是是否需要读取完整文件计算 checksum 时需要通常不需要重新读取全部文件是否适合大规模定期检查上传阶段使用非常适合是否适合 Multipart是与同步结果检查配合是否可以发现同步漏文件否是是否可以发现 Size 不一致不作为主要目的是是否可以发现 ETag 不一致不作为主要目的是二十六、需要注意verifySync 不是“绝对意义上的 SHA256 全量校验”这是整个方案中最容易误解的一点。verifySync不是 源文件 → 重新计算 SHA256 → 目标文件 → 重新计算 SHA256而是源 Filer │ ├── 文件是否存在 ├── Size └── ETag │ │ compare ▼ 目标 Filer因此它的优势是速度快 网络开销小 磁盘 IO 小 适合定期扫描大量文件代价则是它不是一次完整的端到端 SHA256 内容重新验证。如果某些极高价值数据需要最高等级的验证可以在verifySync发现ETAG_MISMATCH或者其他异常以后再针对具体文件执行完整文件读取 ↓ SHA256 ↓ 源端与目标端比较形成正常情况下 verifySync ↓ 快速检查 发现异常 ↓ 针对异常文件 ↓ 完整 SHA256 ↓ 最终确认这比每天对整个 NAS 的所有 TB 数据重新计算 SHA256 更合理。二十七、最终结论SeaweedFS 的数据完整性可以设计成两层校验。第一层是上传完整性客户端 │ │ SHA256 ▼ S3 / SeaweedFS │ │ ChecksumSHA256 ▼ 比较用于保证客户端上传到本地 SeaweedFS 的对象没有发生内容错误。相关能力可以参考 SeaweedFS PR #8914。第二层是同步完整性本地 SeaweedFS │ │ filer.sync ▼ NAS SeaweedFS │ │ verifySync ▼ Path Size ETag用于保证filer.sync 完成后NAS SeaweedFS 中的数据集合和对象信息与源端保持一致。SeaweedFS PR #9284 新增的-verifySync正是针对这个问题设计的并支持MISSING、SIZE_MISMATCH、ETAG_MISMATCH等差异检测同时提供-modifyTimeAgo和-verifyJsonOutput等能力。因此对于“本地 SeaweedFS NAS SeaweedFS”的架构比较推荐上传阶段 │ S3 SHA256 │ ▼ 本地 SeaweedFS │ filer.sync │ ▼ NAS SeaweedFS │ verifySync │ ┌───────┴────────┐ │ │ 正常 异常 │ │ ▼ ▼ 完成 告警/修复这样就把整个数据链路拆成了上传完整性 同步完整性 异常后的深度 SHA256 验证对于需要长期保存缺陷图片、原图、ZIP 包以及 JSON 索引的 NAS 存储系统这种方案比单纯依赖“上传成功”和“同步程序没有报错”要可靠得多。参考SeaweedFS PR #8914SHA256 校验支持SeaweedFS PR #9284filer.sync-verifySync