拓冰建站拓冰建站
首页 / 资讯中心 / 正文

RustFS 扫描器数据用量发布契约:分布式 Scanner 到硬配额权威状态的证明机制全解析

RustFS 扫描器数据用量发布契约分布式 Scanner 到硬配额权威状态的证明机制全解析【免费下载链接】rustfs2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system supporting migration and coexistence with other S3-compatible platforms such as MinIO and Ceph.项目地址: https://gitcode.com/GitHub_Trending/rus/rustfs导读本文以 scanner-usage-publication.md 为骨架系统讲解 RustFS 中后台 Scanner扫描器如何把一次分布式 namespace 扫描的产物安全地发布为可以被硬配额hard quota准入决策消费的权威数据用量快照。文中将完整拆解七层栅栏fence协议、持久化对象生命周期、观测快照observed snapshot与用量地板usage floor降级机制并结合crates/scanner与crates/ecstore的真实实现代码给出源码级佐证。读完本文你将掌握 RustFS 分布式扫描发布协议的设计动机、每个持久化对象的安全语义以及为什么缺失数据绝不等于零是该契约的不可动摇底线。适用场景什么时候需要关注这份契约这份契约文档明确标注了它的适用边界——当你正在修改以下任何一类行为时都必须以本文定义的协议为约束scanner 数据用量的持久化data-usage persistence配额可见的用量快照quota-visible usage snapshotsscanner 周期状态cycle state脏用量追赶dirty-usage catch-up以及观测到的 scanner 快照在什么条件下可以被对外服务served snapshot 条件。文档声明的事实源头Source of truth集中在 crates/scanner/src/scanner/usage_store.rs、crates/scanner/src/scanner/cycle_state.rs、crates/scanner/src/scanner/backlog.rs、crates/scanner/src/scanner/leadership.rs、crates/scanner/src/data_usage_define.rs以及配额降级行为所在的 crates/ecstore/src/bucket/quota/checker.rs。这也是一份配套决策记录 scanner-usage-authority-decision.md2026-09-03 定案的直接落地文档后者确认了 RustFS 将 scanner 数据用量作为硬配额准入的权威来源。所有权模型一个完整发布的三个身份谁有资格发布权威快照协议的第一个核心论断是一个 scanner 周期只有在同时满足两个条件后才拥有权威发布authoritative publication的所有权持有集群 scanner 领导权声明cluster scanner leadership claim证明存储发布纪元storage publication epoch没有发生移动。其中领导权声明持久化在 scanner 周期状态中而数据用量发布的准入权publication admission却归属于ECStore——因为只有 ECStore 知道 rebalance、decommission 或其他数据移动data-movement操作是否改变了 scanner 结果所允许描述的代际generation。从源码看claim_scanner_leadershipleadership.rs通过带前置条件的条件写入save_config_with_preconditions结合 ETag 的If-Match/If-None-Match来抢占DATA_USAGE_BLOOM_NAME_PATH即.bloomcycle.bin上的领导权并在写入后调用complete_scanner_leadership_claim完成用量纪元栅栏usage epoch fence而每次发布前都会调用scanner_publication_admission_for_epoch验证存储纪元一旦数据移动造成纪元变化发布立即以Deferred(ScannerCycleDeferReason::DataMovement)推迟见 usage_store.rs。关键语义scanner 可以在没有发布所有权的情况下计算用量但绝不允许把计算结果变成权威的配额可见状态。三身份缺一不可一个完成的发布因此具有三重身份任何一重身份在提交前发生变化该结果就只能是重试候选或观测结果而不是权威基线身份作用scanner leader 纪元leader epoch拥有该周期存储发布纪元storage publication epoch栅栏住数据移动被替换用量对象上的逐对象 CAS 修订per-object CAS revision防止丢失更新实现层面CAS 修订由DataUsageCacheRevision承载data_usage_define.rsMissing状态映射为If-None-Match: *Etag状态映射为If-Match: etag。写入失败返回PreconditionFailed时发布循环会按SCANNER_PERSIST_CAS_RETRIES上限重试而读取既有对象时还会做三重比对——既有数据是否与候选完全相同AlreadyDurable、是否同纪元同周期PriorCycleDurable、是否因更晚的scanner_epoch/scanner_cycle/last_update而属于过期更新跳过。root_publication_confirmation_tests还专门验证了根发布确认必须同时满足Committed提交状态与非空 ETag且该确认状态绝不跨 CAS 尝试保留。PUT 尾部的特殊性移动独占准入普通 PUT 的 rename fanout 会跟踪实例作用域内的在途工作in-flight work但quorum ACK 并不会释放它底层磁盘任务要等 rename 工作真正结束才释放所有权即使请求调用方已被取消。这里有两个刻意设计扫描准入保持仅移动受限movement-only持续的 PUT 不会停止 namespace 遍历与 scanner 驱动的生命周期发现scan 结束后本地发布检查与远端发布租约remote publication leases会拒绝未决的 fanoutbegin/end namespace 代际会在整个 fanout 范围内使扫描与已缓存计划失效协调者在取得远端租约后、发布权威聚合之前会重新核对完整活动摘要full activity digest从而抓住scan 最后一次探测之后、租约取得之前才收尾的尾部写入。这份设计不增加任何 namespace 锁或移动锁。同时要清醒认识到它的代价一个已验证过的旧快照仍然可能先于一个刚发起的写入持续或停滞的 PUT 尾部会延迟权威用量发布延迟恢复依靠既有重试计划而非新的即时唤醒协议各 set 与前缀缓存读者继续保持近似缓存approximate-cache语义若未决尾部长期存在且无代际变化还可能延迟周期推进与对已最新缓存的重新扫描——在存储 I/O 无限停滞的情况下协议不承诺生命周期进度。最后是升级约束该 PUT 尾部保护要求每个写入节点都已升级它不证明失败的尾部副本已经愈合也不把同样的在途跟踪扩展到 multipart 或其他 namespace 变更路径。栅栏体系为什么需要七层独立栅栏协议使用相互独立的栅栏因为它们排除的是不同类型的陈旧输入。除非替换方案能证明排除效果完全相同否则不得合并或删除任一栅栏。完整栅栏表如下栅栏所有者排除对象Scanner 领导权声明scanner竞争中的 scanner leader 与陈旧的周期写入者存储发布纪元ECStore跨越 rebalance、decommission 或其他数据移动代际计算的用量发布租约经 ECStore 面向活动探针的 scanner 对等节点尚未确认该候选的远端脏用量或维护状态CAS 修订底层配置对象存储用量快照、scanner 缓存或周期状态对象的丢失更新每个 set 的新鲜度scanner 聚合混合陈旧与当前 set 结果的合并用量快照分层注册表代际scanner 分层核算针对不同暖层注册表核算的字节用量地板身份scanner 发布与 ECStore 配额降级空值或遗留值变成貌似可信的权威配额输入失败必须闭合fail closed无法为自身读取面证明所需栅栏的读者必须失败闭合或走文档定义的观测路径。绝不允许为缺失或损坏的权威对象合成一个空用量快照——这一点在 cycle_state.rs 的注释中也有呼应A missing usage snapshot is an uninitialized state, not an empty snapshot缺失用量快照是未初始化状态不是空快照领导权栅栏可以在不捏造默认值的情况下继续推进权威快照由第一次完整 scanner 发布创建。缓存执行身份结构摘要不足以复用结果执行摘要execution digest与缓存身份结构性扫描计划摘要structural scan-plan digest在普通 bucket 写入下可以保持稳定因此作用域扫描可以保留不受影响的基线 bucket但它不足以证明同一个周期内可以复用已完成的扫描结果。Bucket 工作采用由两部分组合的执行摘要结构计划structural plan完整活动快照full activity snapshot。同时把 bucket 的脏代际dirty generation纳入其缓存身份。已完成的 set 缓存携带与其结构计划分开存储的同一执行摘要。持久化的 set-root 快路径fast path要求执行身份相等外加既有的来源source、周期cycle、leader、分层tier与缓存结构检查。起始缓存修订与慢扫描保护一个 set 扫描还会记录它开始时的缓存修订。当持久化执行结果不同、需要替换时要求这些修订保持不变——否则一个慢扫描可能覆盖掉更新的已完成结果。既有的缓存锁、条件保存与移动准入仍然负责栅栏住提交。向后兼容语义可选的scan_execution_digest字段被追加到 map 编码的缓存元数据中遗留缓存仍然可读但没有该身份就无法满足同周期 set-root 复用旧读者可以忽略新增的 map 键但旧写入者不执行该栅栏——可读不是混合版本发布安全的保证。持久化对象清单兼容性契约的组成部分以下对象都是兼容性契约的一部分移除任何一个都需要兼容窗口与专门的清理条目对象所有者生命周期每个 bucket 与 set 下的.usage-cache.binscanner 磁盘遍历由 scanner 依据对象元数据重建数据缺失导致该 bucket/set 重新扫描数据损坏不构成完整基线.bloomcycle.binscanner 周期状态由 leader CAS 更新状态缺失从未初始化周期开始损坏或未来版本状态在自动重试前先被隔离quarantine.usage.v2.json与.usage.jsonscanner 权威发布.usage.v2.json是主完整用量快照.usage.json仅在携带有效持久化身份时作为遗留/伴随基线读取两者都不能绕过 v2 纪元栅栏仅当基线身份与完成字段均通过校验读者才可将其视为权威.usage.observed.jsonscanner 观测路径当无法证明权威发布但仍值得输出诊断快照时写入永远不是硬配额权威bucket-metadata/.usage.jsonscanner 用量地板承载降级权威用量窗口期间配额使用的持久化逐 bucket 地板静态保持直到下一次完整 scanner 发布.bloomcycle.bin.recovery-required.jsonscanner 周期恢复带重试证据隔离无效周期状态只有 scanner 恢复代码可更新或清除它.scanner-cycle.lockscanner 运行时锁串行化周期级工作锁对象缺失本身不是用量证据.scanner-pause-backlog.jsonscanner 暂停与追赶账本在权威发布被数据移动栅栏住期间跟踪脏用量、已发现生命周期工作与全量扫描追赶从不授予发布准入对象路径常量在 data_usage_define.rs 中集中定义DATA_USAGE_OBJ_NAME_PATH、LEGACY_DATA_USAGE_OBJ_NAME_PATH、DATA_USAGE_OBSERVED_OBJ_NAME_PATH、DATA_USAGE_BLOOM_NAME_PATH、DATA_USAGE_BLOOM_RECOVERY_PATH{bloom}.recovery-required.json、DATA_USAGE_RECOVERY_PATH{usage}.recovery-pending.json均挂载在 RustFS 内部元数据桶RUSTFS_META_BUCKET下。从源码看v2 主快照与遗留快照的关系处理得非常精细usage_store.rs 的read_data_usage_persist_baseline以 v2 primary 修订为 CAS 栅栏——当 primary 在升级中断期间变成无基线身份的合法 JSON 时可以改用同代或更新的持久化伴随对象.bkp、遗留路径及其备份但更旧的遗留快照不得跨越 primary 的纪元栅栏只有当候选快照满足data_usage_info_has_persisted_baseline_identity且其scanner_epoch不小于无效 primary 的纪元时才被接受。此外还允许一种bootstrap pending占位状态作为合法基线身份——在持续写入流不断使每个周期被取代源码注释提到 issue #6852的站点上它可能是唯一存在的权威对象观测快照必须以它为基线才能发布。.scanner-pause-backlog.json的实现位于 backlog.rs其模块文档明确写道该账本复制在权威数据用量发布路径之外因此在发布被数据移动栅栏住时仍能推进但它绝不授予发布准入。账本以ScannerPauseBacklogPhase状态机Idle/Paused/CatchingUp/RetryExhausted驱动配合一套限流阈值最小追赶间隔 5 分钟、追赶窗口 1 小时、每窗口最多 4 次尝试、连续失败上限 5 次、暂停时长告警阈值 24 小时、延迟周期告警阈值 3、积压条目告警阈值 10,000每 5 分钟刷新一次。账本会跨 set 副本进行共识校验commit record 必须被所有幸存 set 完全一致地保存才具备候选权威性并在每 60 秒间隔输出rustfs_scanner_pause_backlog_*系列指标与告警原因。观测快照诊断与可用性层而非配额权威观测快照observed snapshots是诊断与可用性层。仅在以下两个条件同时满足时才可对外服务快照明确报告自己是部分/观测性的partial or observational消费方不会基于它做出硬配额、持久性或删除决策。管理端用量视图可以暴露带完整性标记completeness flags的状态让运维在权威发布受阻时仍能看到进度但配额强制绝不允许把观测快照当作当前用量权威。观测快照的写入路径在 usage_store.rs 中清晰可见当usage_snapshot_converged Some(false)时目标路径从.usage.v2.json切换到.usage.observed.json写入观测快照前必须有一个有效的权威基线身份来自 v2 primary、其.bkp、遗留快照或 bootstrap 占位否则发布以observed_baseline_missing/observed_baseline_identity_missing/observed_baseline_decode_failed等状态拒绝或失败——观测快照的发布同样不豁免权威基线要求。用量地板降级窗口的可用性回退当权威快照不可用时配额准入可以回退到持久化用量地板persisted usage floor。这是可用性回退不是新鲜计数实时写入不会推进地板值超限幅度只受下一次完整 scanner 发布之前已接受的写入约束若不存在有效的持久化地板配额保持不可用并失败闭合。配额侧的降级实现在 crates/ecstore/src/bucket/quota/checker.rs 的get_real_time_usage中优先走内存中的权威用量get_bucket_usage_memory降级窗口源码注释引用 issue #5716内再通过lookup_degraded_bucket_usage_baseline读取持久化的逐 bucket 基线任何地方都没有持久化基线的 bucket 继续失败闭合QuotaError::UsageUnavailable。该文件内还有针对无持久化元数据的 bucket 必须放行配额检查、让请求到达 NoSuchBucket 答案issue #5307 回归与升级后降级到遗留快照基线issue #5716 回归的两组专门测试。可用性决策权威快照、地板与失败闭合的三段式契约决策日期为 2026-09-03。RustFS 决策记录 scanner-usage-authority-decision.md 给出完整论证配额是写路径准入决策用尽力而为的 scanner 数据服务配额会把暂时的 scanner 滞后变成执法不足under-enforcement因此必须保留权威用量的可用性叙事而不是删除使之权威的证明层scanner 用量地板就是这个可用性叙事——它是冷启动、升级恢复与不完整周期修复场景下的下界。可用性契约可以概括为权威快速路径读取完整的内存中或持久化的 scanner 用量升级/发布中断期间配额可以按持久化的逐 bucket 用量地板准入地板仅在中断窗口内是建议性的必须收敛回完整的 scanner 发布既无权威用量又无有效地板的 bucket 失败闭合。把该决策改为软配额soft quota模型属于产品变更而非 scanner 重构需要分阶段移除权威专属层并处理上述持久化对象的兼容性。删除与恢复规则只有所有者才能处置对象契约对删除与隔离权限做了严格限定只有对象的所有者才能删除或隔离它scanner可在扫描证明替换内容有效后重建每个 set 的.usage-cache.binscanner 周期恢复可隔离无效的.bloomcycle.bin且仅在有效周期状态持久化后清除标记scanner 发布只能通过前述发布栅栏替换.usage.v2.json或遗留伴随对象配额消费者可以读取用量地板但不得删除或修复它运维人员只能通过受支持的 scanner 重置面重置 scanner 用量状态该重置面会记录重置路径并强制全量重建。恢复机制的实现细节印证了这些规则cycle_state.rs 中无效周期状态通过ScannerCycleRecoveryMarkerblocked/cleanup-pending状态分类限corrupt/future_schema带 primary revision 与重试计数写入.bloomcycle.bin.recovery-required.json最大自动重试 5 次超过后进入paused状态转为稀疏后端探测另有.usage.v2.recovery-intents/前缀下的恢复意图记录accepted/running/completed/failed状态机含 actor SHA-256 与幂等键由run_scanner_usage_recovery_intent执行scanner-usage-full-rebuild全量重建动作。贯穿始终的底线语义缺失、无法解码或无身份的数据绝不转换为零而是按读取面分别报告为未初始化uninitialized、恢复必需recovery-required、仅观测observed-only或不可用unavailable。既有修复即不变量契约的派生结论契约最后强调若干既有 scanner 修复并非独立补丁而是该契约的必然推论不完整的 scanner 用量不得成为完整的 admin 或配额基线——因为完整性与地板身份本身就是发布所有权的一部分脏用量与维护确认必须栅栏住发布——远端节点若有未确认的工作可以使候选结果失效对应发布租约栅栏遗留或备份用量对象只有在携带有效基线身份、且不跨越主纪元栅栏时才能帮助恢复可用性。测试侧同样能印证这些不变量crates/scanner/src/scanner/tests/下有针对发布语义的专门测试目录例如scoped_ack_publication.rs作用域 ACK 发布、quota_reset_preservation.rs配额重置保留、recovery_control.rs恢复控制以及crates/scanner/src/scanner_io/publish_gate_tests.rs发布闸门是理解本契约各栅栏触发条件的良好入口。总结RustFS 的 scanner 用量发布契约本质上是如何让一个分布式后台扫描的输出安全地成为写路径硬配额决策的权威输入的完整证明体系领导权、存储纪元、发布租约、CAS、set 新鲜度、分层注册表与用量地板七层栅栏各自排除一类陈旧输入.usage.v2.json、.bloomcycle.bin、.usage.observed.json、用量地板与暂停账本各司其职且不可互相替代观测快照提供诊断可见性但永不成为配额权威地板提供降级可用性但只是静态下界而缺失不等于零、失败必须闭合贯穿了从扫描、发布到配额准入的全链路。对于任何需要修改 scanner 用量持久化、配额可见快照、周期状态或脏用量追赶行为的开发者这份契约及其事实源头源码就是必须遵守的边界——打破任何一个栅栏都意味着把陈旧或跨代际的用量重新变成了貌似可信的配额真值。【免费下载链接】rustfs2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system supporting migration and coexistence with other S3-compatible platforms such as MinIO and Ceph.项目地址: https://gitcode.com/GitHub_Trending/rus/rustfs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门