Milestone 2 执行计划:移除只读限制与配套 API 改造路线)
数据工程数据湖大数据对象存储后端【免费下载链接】lakeFSlakeFS - Data version control for your data lake | Git for data项目地址https://gitcode.com/gh_mirrors/la/lakeFS点击查看免费下载本文围绕 lakeFS 的 Uncommitted Garbage CollectionGC未提交数据垃圾回收项目的 Milestone 2 执行计划展开它明确了该里程碑唯一的核心目标——在 GC 作业运行时解除 lakeFS 的只读限制并给出了为实现这一目标所必须完成的一组 API 改造Get/Link PhysicalAddress、StageObject、CopyObject、ref-store 复制对象跟踪与集成测试验证方案。读完本文你可以完整理解 GC 各里程碑的划分逻辑、Milestone 2 的目标与非目标边界以及这些设计在 lakeFS 当前源码中的落地形态PrepareGCUncommittedAPI、Parquet 输出、ugc配置项等。背景Uncommitted GC 与 GC 项目lakeFS 在分支被删除、分支 reset、staged 数据被覆盖或删除后底层对象存储中对应的未提交uncommitted数据并不会被自动清理。这些数据既占用存储也可能引发合规问题。lakeFS 曾尝试多种在线online硬删除方案相关讨论见 design/rejected/hard-delete.md最终采纳的是离线 GC 方案由一个独立的 GC Client如 Spark 作业同时消费 lakeFS 元数据与对象存储中的实际对象列表找出“在 bucket 中存在、但既不在已提交数据中、也不在任何分支的未提交数据中”的对象并删除。GC 的整体设计Clean Run / Optimized Run 两种流程、对象路径约定、PrepareUncommittedForGC等在 uncommitted-gc.md 中给出总体的改动拆解lakeFS 侧、GC 侧、测试策略在 gc-plus-execution-plan.md 中给出。Milestone 2 计划文档 gc-plus-milestone2-execution-plan.md 则是其中承接 Milestone 1 之后的实施排期。Milestone 1 已完成的内容Milestone 2 计划文档首先回顾了第一个 beta 版本交付的范围针对新旧两种仓库结构实现的 Clean Run完整清扫流程不含性能优化Mark Sweep标记与清扫机制集成测试基于 rclone 的最小化 Backup Restore备份与恢复支持。也就是说未提交数据“能被安全清出来”这条主链路已经打通Milestone 2 要解决的是运行期间的可用性约束与配套 API 的补全。核心目标移除 GC 运行期间的只读限制Milestone 2 文档列出的唯一目标是Removing the limitation of a read-only lakeFS during the GC job run移除 GC 作业运行期间 lakeFS 处于只读状态的限制。要理解这个目标的价值需要理解只读限制从何而来。未提交数据的集合是动态变化的GC 作业运行过程中用户随时可能新上传对象、链接link对象、复制/重命名对象。lakeFS 通过PrepareUncommittedForGC在 API 层面演进为PrepareGCUncommitted把所有分支的未提交对象清单导出为数据文件GC Client 再将其作为“保护集”参与集合差运算。如果 lakeFS 在此期间不对外提供任何写入/链接能力即整体只读集合差运算的语义是安全的但代价是 GC 窗口期内所有用户作业停摆——这正是生产环境中不可接受的部分。因此 Milestone 2 的思路是不冻结 lakeFS而是通过一组 API 层面的保证让“GC 正在运行”与“lakeFS 正常写入”可以安全共存。明确排除在非目标之外的事项计划文档用 Non-Goals 清晰地圈定了本里程碑的边界以下事项均不在 Milestone 2 范围内性能优化包括旧仓库结构下的优化 listingissue #4620已提交条目的高效 listingissue #4600基准测试——验证未提交 GC 的性能需求对应 uncommitted-gc.md 中的 Performance Requirements 一节是否仍然满足实现 Optimized Run优化运行流程issue #4489——Milestone 1 只交付了 Clean Run非 S3 仓库的支持Azure 与 GCP 均未列入将已提交 GC 与未提交 GC 合并为单一作业包括为适配统一 GC 而做的配置与行为变更Metrics 与 Logging 的增强部署到 lakeFS Cloud改进 Backup Restore。这一清单对读者很有参考价值它说明 Milestone 2 交付的版本在“运行期可用性”上达标但在吞吐、多云支持与运维可观测性上仍留有后续里程碑的欠账。实施计划依赖关系驱动的 API 改造清单Milestone 2 的 Plan 部分按依赖关系组织全部工作分为两大类lakeFS 服务端的必要改造含破坏性变更与安全性集成测试。1. [Get/Link]PhysicalAddress 改造这是整个计划的基石。lakeFS 的上传流程分为两步先调用GetPhysicalAddress获取一个物理地址可附带预签名 PUT URL客户端直传对象存储后再调用LinkPhysicalAddress将其登记为分支上的 staged 条目。在 Milestone 2 中这组 API 需要引入时间维度的校验issue #4476、#4695 “Validation of cutoff time”。其 GC 语义在 uncommitted-gc.md 中有完整阐述GetPhysicalAddress返回地址的同时返回或内嵌一个校验 tokentoken 有指定有效期且只能使用一次lakeFS 需要跟踪已签发的 token/地址并在过期或被消费后删除LinkPhysicalAddress在建条目前必须校验 token 有效。这样做的直接效果是GC 可以用“token 有效时间窗口”作为过滤条件——已上传但尚未 link 的对象只要仍在窗口期内就不会被误删而窗口期内未完成 link 的对象最终会被 GC 作业清理。这同时解决了“预签名地址泄漏/上传中途失败产生孤儿对象”的问题原文档引用的 issue #4438。当前源码中的落点GetPhysicalAddress与LinkPhysicalAddress的处理入口位于 pkg/api/controller.goGet与 pkg/api/controller.goLink。从源码结构看Get 侧通过Catalog.GetAddressWithSignature生成地址并可用BlockAdapter.GetPreSignedURL下发预签名写 URLLink 侧通过BlockAdapter.ResolveNamespace解析物理地址后再写元数据。hadoopfs 客户端中的 LakeFSLinker.java 展示了客户端如何使用这组接口完成上传后的登记。2. StageObject API 改造StageObject允许客户端把已经存在于对象存储中的对象直接登记为 staged 条目issue #4480。设计要求该操作只允许登记在仓库存储命名空间之外的地址这样通过它加入的对象永远不会被 GC 当作“仓库内的未提交数据”处理也不会被 GC 误判为可删除对象。当前源码中的落点StageObject处理器在 pkg/api/controller.go。可以看到它先按WriteObject权限鉴权再通过ResolveNamespace解析物理地址IdentifierTypeFull并用存储配置的ValidityRegex校验地址合法性随后调用Catalog.CreateEntry落库。地址是否位于仓库命名空间内会通过normalizePhysicalAddress区分为 RELATIVE/FULL 两种地址类型——这正是 GC 侧区分“仓库内数据”与“外部引用”的依据。3. CopyObject API 及外围issue #4477 要求引入一个与 S3 Gateway 能力对等的CopyObjectAPI并连带两个子项issue #4478、#4479S3 Gateway CopyObject通过 Gateway 执行 shallow copy浅拷贝时把被复制对象记录到 ref-storelakeFSFS renameObject 方法Hadoop 文件系统客户端的重命名改用CopyObject DeleteObject组合实现。背景是S3 客户端习惯用CopyObject DeleteObject完成 Rename/Move而 OpenAPI 客户端此前只能用StageObject DeleteObject。在 GC 语义下copy 操作产生了一个“同一物理对象、两条未提交记录”的竞态窗口——GC 若在窗口内把源路径的记录当作已失效而回收物理对象目标路径就会悬空。为此计划文档要求 lakeFS 在 ref-store 中跟踪 uncommitted 对象的复制操作保留有限时长GC 将这份记录并入未提交数据后再做集合差运算从而规避 GC 与 rename 之间的竞态。当前源码中的落点OpenAPI 的CopyObject已实现处理器位于 pkg/api/controller.go它对源路径做ReadObject、对目标路径做WriteObject双重鉴权确认目标分支存在后将复制下沉到Catalog.CopyEntry。值得注意的是ESTI 集成测试 esti/copy_test.go 中的TestShallowCopyNotImplemented断言带shallowtrue参数的 CopyObject 请求会返回501 Not Implemented。这说明 OpenAPI 层的 shallow copy浅拷贝/clone路径在当前仓库中仍未开放只有 S3 Gateway 侧的 shallow copy 生效——这也与 Non-Goals 中“优化运行流程尚未实现”的边界相互印证shallow copy 依赖的 ref-store 复制跟踪与优化 GC 流程属于更靠后的能力。4. 集成测试验证 GC 运行期间 lakeFS 是安全的计划文档第二项是 issue #4830——一组专门验证“GC 运行期间 lakeFS 仍可安全使用”的集成测试。结合仓库现状ESTI 测试套件esti/ 目录基于真实部署的 lakeFS 容器执行端到端场景中已有对应的 GC 相关用例例如 esti/unified_gc_test.go 覆盖 GC 统一流程、esti/copy_test.go 覆盖复制语义边界[Get/Link]PhysicalAddress的链路则被 esti/presign_test.go、esti/multipart_test.go 等多处上传路径测试反复使用。这些测试共同构成了“GC 运行中写入不丢、不坏”的验证层。交付物与时间点计划文档承诺到本里程碑结束将发布一个包含上述全部增量的 lakeFS 版本并给出了当时的计划截止日期2023-01-15。该日期属于计划文档的历史排期信息实际交付节奏以 CHANGELOG.md 中的版本记录为准。从源码看配套能力的最终形态Milestone 2 所依赖的 lakeFS 侧改造在当前代码库中留下了清晰可循的实现痕迹可作为理解该计划如何落地的入口。PrepareGCUncommitted未提交清单导出 API原提案中的PrepareUncommittedForGC在 API 层面演进为内部接口POST /repositories/{repository}/gc/prepare_uncommitedoperationIdprepareGarbageCollectionUncommitted定义见 api/swagger.yml其职责是“save repository uncommitted metadata for garbage collection”。服务端实现链如下入口 Catalog.PrepareGCUncommitted校验仓库存在、非只读若无 mark 则通过Store.GCNewRunID()生成新的 run ID首次调用开新 run后续调用携带 mark 续跑同一 run将扫描结果写入本地临时文件后经uploadFile上传到仓库命名空间下 GC 专属的 uncommitted 目录由Store.GCGetUncommittedLocation计算路径核心扫描逻辑 gcWriteUncommitted用store.ListBranches(...WithShowHidden(true))遍历全部分支含隐藏分支对每个分支取DiffUncommitted跳过 tombstoneDiffTypeRemoved过滤掉位于仓库存储命名空间之外的绝对地址然后把physical_address creation_date逐条写入 Parquet 文件输出数据结构 UncommittedParquetObject 只含两列physical_addressUTF8 字符串与creation_dateINT64 Unix 秒与提案文档“address creation date”的文件内容定义一致。分页标记Mark机制大仓库的未提交清单可能非常大单次 API 调用无法完成。GCUncommittedMark 结构branch/path/run_id/key四字段标记了“下一个待扫描项”实现上通过branchIterator.SeekGE(mark.BranchID)与diffIterator.SeekGE(...)定位续扫起点见 gc_write_uncommitted.go。两个停止条件会生成新的 mark单个输出文件超过prepare_max_file_size已运行时间超过prepare_interval防止单次调用超时。调用方GC Client循环携带 mark 调用直至返回空 mark即完成整个仓库的未提交清单导出。ugc 配置项上述两个阈值对应配置文件中的ugc段定义于 pkg/config/config.go默认值在 pkg/config/defaults.gougc: prepare_interval: 1m # 单次 PrepareGCUncommitted 调用的最长耗时上限 prepare_max_file_size: 20MiB # 单个 Parquet 输出文件的大小上限20*1024*1024 字节这与提案文档中“对象列表按约 20MB 目标文件大小切分”的性能设计5M 未提交对象、1K 分支场景下切分为约 3 个文件精确对应。GC 元数据与保留期管理GC 的 run 管理、起始点starting point选择等能力集中在 pkg/graveler/retention/如garbage_collection_manager.go、starting_point_iterator.go它同时服务已提交与未提交两条 GC 链路。Milestone 2 计划中“合并为单一作业”虽被列为 Non-Goal但保留期基础设施在代码中已经为后续合并铺好了路。小结如何阅读这份计划目标聚焦Milestone 2 只解决一件事——GC 运行时 lakeFS 不再只读其余一切性能、Optimized Run、Azure/GCP、统一 GC 作业、可观测性、Cloud 部署、BR都被显式排除避免范围蔓延手段是 API 契约Get/Link PhysicalAddress 的时效性校验、StageObject 的命名空间外约束、CopyObject 与 ref-store 复制跟踪共同把“GC 与写入并发”的竞态逐个消灭以测试为准绳issue #4830 的集成测试是这个里程碑的验收标准仓库 ESTI 套件中的 GC 与 copy 用例是该标准的持续执行者与源码对照计划中的PrepareUncommittedForGC对应现行PrepareGCUncommittedAPI 与 gc_write_uncommitted.go 的 Parquet 导出实现OpenAPI shallow copy 返回 501 的现状esti/copy_test.go则标示了当前边界——阅读文档时请注意这是 2023 年初的执行计划其中部分 Non-Goals如统一 GC在后续版本中已被推进具体能力以 CHANGELOG.md 与当前源码为准。赞分享数据工程数据湖大数据对象存储后端【免费下载链接】lakeFSlakeFS - Data version control for your data lake | Git for data项目地址https://gitcode.com/gh_mirrors/la/lakeFS点击查看免费下载相关推荐lakeFS 未提交数据垃圾回收Uncommitted GC设计解析基于分片扫描与时间令牌的离线回收方案lakeFS 未提交数据垃圾回收Uncommitted GC设计解析基于分片扫描与时间令牌的离线回收方案 导读 lakeFS 的常规 GCGarbage数据工程数据湖大数据对象存储后端lakeFS Spark Metadata Client用 Spark 读取 Graveler 元数据、导出数据与运行 GClakeFS Spark Metadata Client用 Spark 读取 Graveler 元数据、导出数据与运行 GC 本篇技术指南围绕 lakeFS数据工程数据湖大数据对象存储后端lakeFS GC 两步分离设计Mark 标记与 Sweep 清扫的独立运行机制lakeFS GC 两步分离设计Mark 标记与 Sweep 清扫的独立运行机制 导读 本文围绕 lakeFS 官方设计文档 gc two steps sep数据工程数据湖大数据对象存储后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考