PG Scrub 全流程核心步骤清单
将scrub,按 “初始化→资源预约→校验执行→一致性对比→收尾”5 大阶段拆解,每个步骤均标注关键日志锚点,方便快速定位对应流程。
一、初始化阶段:判断 scrub 可行性(触发条件校验)
主 OSD 从集群调度逻辑中选中目标 PG,先校验是否满足 scrub 执行条件,避免无效操作。
1.触发 scrub 任务
- 操作:集群 scrub 调度器触发 initiate_scrub,指定 PG(8.19)执行 scrub;
- 日志锚点:osd-scrub:initiate_scrub: initiating scrub on pg[8.19]。
2.校验 PG 状态与环境 - 操作:确认 PG 状态为 active+clean(无数据缺失)、当前负载空闲、时间符合 scrub 窗口;
- 日志锚点:start_scrubbing: + (env restrictions:priority-only:false …)。
3.确定 scrub 类型 - 操作:判断无需深度 scrub(time_for_deep=0),执行轻量 scrub(仅校验元数据);
- 日志锚点:validate_periodic_mode will do shallow scrub (time_for_deep = 0)。
4.本地资源预约 - 操作:标记本地 scrub 资源已占用(当前运行数从 0→1,最大支持 3 个并行);
- 日志锚点:osd-scrub:log_fwd: inc_scrubs_local: 0 -> 1 (max 3)。
5.更新 PG 状态 - 操作:将 PG 状态从 active+clean 改为 active+clean+scrubbing,告知集群该 PG 正在 scrub;
- 日志锚点:pg[8.19… active+clean+scrubbing [ 8.19: ] ]。
二、资源预约阶段:确保副本资源可用
主 OSD 需先向所有副本申请 scrub 资源,避免副本因资源冲突拒绝任务,确保多副本协同。
1.切换状态机至 “预约模式” - 操作:主 OSD 状态机从 PrimaryIdle→ReservingReplicas,准备向副本发起预约;
- 日志锚点:scrubber<Session/ReservingReplicas>: FSM: – state -->> ReservingReplicas。
2.向副本发送预约请求 - 操作:按副本集顺序(osd.0→osd.2)发送 MOSDScrubReserve(QREQUEST) 消息,携带唯一 nonce(防重复);
- 日志锚点:scrubber::ReplicaReservations:send_next_reservation_or_complete: reserving 0 (the 1 of 2 replicas) e:952 nonce:28。
3.接收副本预约同意响应 - 操作:依次收到副本返回的 MOSDScrubReserve(GRANT),确认所有副本资源可用;
- 日志锚点:enqueue_op MOSDScrubReserve(8.19,GRANT,e:952,from:0,…)、granted by 2 (2 of 2) in 13ms。
4.标记预约完成 - 操作:确认所有副本(2 个)均同意预约,从 “预约阶段” 进入 “执行阶段”;
- 日志锚点:scrubber::ReplicaReservations:send_next_reservation_or_complete: remote reservation complete。
三、校验执行阶段:主副本同步执行本地校验
主 OSD 先确认本地数据稳定,再向副本下发具体校验任务,同步执行本地与副本的校验。
1.等待本地数据稳定 - 操作:进入 PendingTimer 状态,等待本地未完成的业务读写(pending_active_pushes)结束;
- 日志锚点:scrubber<Session/Act/PendingTimer>: FSM: – state -->> Session/Act/PendingTimer。
2.确定校验对象范围 - 操作:调用 select_range 选择待校验对象范围(如 [8:98000000::::0,MAX)),拆分 “块级” 任务;
- 日志锚点:select_range range selected: 8:98000000::::0 //// MAX //// MAX。
3.主 OSD 执行本地校验 - 操作:进入 BuildMap 状态,扫描本地指定范围对象,生成 ScrubMap(校验结果);
- 日志锚点:build_scrub_map_chunk [8:98000000::::0,MAX) … done, got 0 items(本地无对象)。
4.向副本下发校验任务 - 操作:向 osd.0、osd.2 发送 replica_scrub 消息,传递校验范围与类型;
- 日志锚点:send_message_osd_cluster replica scrub to osd.0 from_epoch 952。
5.切换至 “等待副本结果” 状态 - 操作:状态机从 BuildMap→WaitReplicas,阻塞等待所有副本返回 ScrubMap;
- 日志锚点:scrubber<Session/Act/WaitReplicas>: FSM: – state -->> Session/Act/WaitReplicas。
四、一致性对比阶段:确认主副本数据一致
主 OSD 收集所有副本校验结果后,对比主副本 ScrubMap,判断是否存在数据不一致。
1.接收副本校验结果 - 操作:依次接收副本 osd.2、osd.0 发送的 rep_scrubmap 消息(即 MOSDRepScrubMap),解码 ScrubMap;
- 日志锚点:enqueue_op rep_scrubmap(8.19 e905 from shard 2) v2、decode_received_map: decoded map from : 0: versions: 619’120 / 905。
2.标记副本结果全部接收 - 操作:生成 PGScrubGotReplMaps 事件,确认 2 个副本结果均已收集;
- 日志锚点:queue a scrub event (PGScrubGotReplMaps(pgid=8.19 …))、FSM: WaitReplicas::react(const GotReplicas&) got all。
3.执行主副本一致性对比 - 操作:调用 scrub_compare_maps 合并所有 ScrubMap 到 “权威集合”,确认主副本均无对象(0 items);
- 日志锚点:b.e.: compare_smaps: authoritative-set #: 0、merge_to_authoritative_set: replica 0 has 0 items。
4.确认无数据不一致 - 操作:判断无需修复(无校验和不匹配、元数据差异),无需触发 MOSDRepair 修复流程;
- 日志锚点:submit_digest_fixes: num_digest_updates_pending: 0。
五、收尾阶段:清理资源与预约下次任务
scrub 完成后,主 OSD 清理临时资源、重置状态,并按策略预约下次 scrub,恢复集群正常状态。
1.等待校验摘要更新 - 操作:进入 WaitDigestUpdate 状态,确认本地校验摘要(如元数据摘要)无待更新项;
- 日志锚点:on_digest_updates #pending: 0 。
2.标记 scrub 任务完成 - 操作:生成 PGScrubScrubFinished 事件,触发 ScrubFinished 状态机事件,输出 “scrub ok” 日志;
- 日志锚点:log_channel(cluster) log [DBG] : 8.19 scrub ok。
3.记录 scrub 关键指标 - 操作:记录耗时(26ms)、扫描对象数(0/0)、无错误(errors:0/0);
- 日志锚点:set_scrub_duration: to 26ms、scrub got 0/0 objects … errors:0/0。
4.清理本地资源 - 操作:释放本地 scrub 资源(当前运行数从 1→0),清除临时校验状态;
- 日志锚点:osd-scrub:log_fwd: dec_scrubs_local: 1 -> 0 (max 3)、clear_pgscrub_state。
5.重置 PG 状态 - 操作:将 PG 状态从 active+clean+scrubbing 改回 active+clean,恢复业务读写能力;
- 日志锚点:pg[8.19… active+clean] scrubber<Session/Act/WaitDigestUpdate>: reset_internal_state。
6.释放副本资源 - 操作:向所有副本发送 MOSDScrubReserve(RELEASE) 消息,通知副本释放预约资源;
- 日志锚点:scrubber::ReplicaReservations:release_all: releasing [0, 2]。
7.预约下次 scrub 时间 - 操作:按集群策略计算下次执行时间(如 2025-09-13T08:21:43.141),加入调度队列;
- 日志锚点:scrub-queue:adjust_target_time: … Adjusted:2025-09-13T08:21:43.141。