ModelEngine-Group / ModelEngine-Group/unified-cache-management
[Feature]: Posix Store 多后端探测与高可用
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 334
- Forks
- 119
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 82
Description
关联实现 PR:ModelEngine-Group/unified-cache-management#1375
Posix Store 多后端探测与高可用
多个 storage_backends 是同一份 KV 数据的不同访问路径。业务 I/O 负责被动发现故障;后台仅探测不可用路径,确认恢复后重新加入可用列表。
执行流程
- 初始化与选路:逐个检查所有后端的数据目录,并同步执行一次 4 KiB 写入、读回、内容校验、关闭和清理;全部成功才发布可用列表并启动恢复监控线程。任一路径失败(启动时包括
NotFound)立即终止启动,返回并记录后端路径、失败操作及 errno/系统错误文本,或数据校验错误。首选后端固定为BlockIdHasher(block_id) % n,n是配置路径规范化、去重后的总后端数;可用列表为空则返回StoreUnhealthy。选路和健康状态更新目前通过互斥锁同步。 - 被动摘除与重试:一次后端 I/O 成功或发生非
NotFound错误时,记录到该后端的滑动窗口。失败达到阈值就摘除;本次失败 I/O 从相同 hash 起点按配置顺序向后查找,跳过不可用及本次已尝试的路径,末尾回绕开头。NotFound作为缓存未命中直接返回,不计入窗口,也不换路重试。窗口按结果次数统计,不按时间统计。 - 主动恢复:每个 Posix Store 保留一个恢复主线程,按顺序调度所有不健康路径,由一个可复用的子线程执行读写;健康路径不主动探测。复用小 I/O 探测并记录结果,窗口填满且全部成功才恢复。默认窗口 8 次、失败阈值 2 次,因此摘除无需等待满窗,恢复需要连续 8 次成功。迟到的业务成功不能恢复路径,迟到的失败仍会影响恢复窗口。
- 对外健康检查:无论单后端还是多后端,
check_health都只读取可用列表:非空为健康,空为不健康;调用本身不发探测 I/O。
同一 block 的各层读写、查询、提交/删除、热度更新使用同一 hash 选路。健康状态变化不会改变取模基数;只有首选路径不可用时才向后回退,恢复后再次选择原首选路径。例如 n=4、hash 命中 3 时,候选顺序为 3 → 0 → 1 → 2。各实例需要保持相同的后端配置顺序。Posix Store 每次传输独立打开、关闭文件,提交时临时文件与最终文件在同一挂载路径下完成重命名。
超时与迟到 I/O
业务传输每次尝试的超时为 timeout_ms / n,n 是配置路径规范化、去重后的总后端数,包含当前不可用路径。正值最小为 1 ms;timeout_ms=0 仍表示禁用超时。外层任务保留完整的 timeout_ms;尝试超时从实际执行开始计算,排队等待不会直接记为后端故障。AIO、psync 均支持错误和超时后的换路重试。
超时不会取消已经进入内核的 I/O。读重试使用独立缓冲区,迟到结果不会覆盖已完成的读;写重试复用独立保存的数据。同步元数据调用仍沿用原有执行方式,不承诺内核调用在该时限内结束。
启动检查与恢复探测做什么
启动检查和恢复探测复用同一小 I/O 逻辑。在指定路径的数据分片目录创建随机临时文件:写入 4 KiB 固定内容 → 读回并校验 → 关闭、删除。沿用 io_direct;关闭 direct I/O 时先 fsync。读写、校验、关闭、清理错误均视为失败。启动检查遇错直接返回;恢复探测中的错误或超时计入窗口。启动检查同步执行文件系统调用,恢复探测的超时机制不负责中断启动阶段的内核调用。
主线程依次下发探测并等待结果;无超时时,所有后端共用并复用同一个 ucm_health_io 子线程。子线程超时后,本次探测记为一次失败,旧子线程不再接收任务,下一次探测创建新子线程,继续按原有顺序和间隔调度。旧线程的迟到结果不再更新窗口,因此同一后端可以在旧探测尚未结束时,通过新探测的完整成功窗口恢复。
Posix 恢复探测不再限制每条路径只能有一个未结束 I/O,也不使用未结束线程数量上限阻止新探测。超时不会强行终止内核 I/O;连续超时期间,未退出的旧线程可能累积,返回后退出并回收。每次探测使用独立文件名;关闭 Store 时仍会等待未结束的工作线程。
线程命名与绑核
Pipeline 监控线程为 ucm_health_mon,唯一的 Posix 恢复监控线程为 ucm_health_pmon,执行小 I/O 的工作线程为 ucm_health_io。启用 VLLM_CPU_AFFINITY=1 时,全部 ucm_health_* 线程绑定当前 NPU 的 assign_ucm_health 核心;后续探测工作线程继承监控线程的 affinity。沿用原有分配策略:预留最后一个 UCM 核心用于健康检测,只有一个 UCM 核心时共享。
配置与默认值
ucm_connectors:
- ucm_connector_name: UcmPipelineStore
ucm_connector_config:
store_pipeline: Cache|Posix
storage_backends: "/mnt/path0:/mnt/path1:/mnt/path2"
posix_io_engine: aio
io_direct: true
store_health:
enabled: true
health_check_interval_s: 10
health_check_timeout_s: 3
health_window_size: 8
failure_threshold: 2
use_layerwise: true
恢复探测沿用 StoreHealthConfig 默认值,可省略上述健康参数;探测超时必须小于间隔,失败阈值不超过窗口,数值均为正。探测超时 health_check_timeout_s 与业务传输的 timeout_ms / n 独立。enabled 控制外层 Pipeline breaker,不关闭启动读写检查、Posix 内部被动反馈与恢复机制。
保留的补充设计意见
“所有后端可用才可以启动”已实现,并增加实际读写校验;“选路无锁方式实现”仍保留为后续待办。
验证
本次 CPU CTest 66/66 通过,覆盖启动时所有后端的实际读写检查、direct I/O 开关、首个/后续后端缺失、open/write/read/fsync/内容校验失败的错误信息和清理,以及固定 block/层选路、总后端数 hash、顺序回绕、首选路径恢复,以及 AIO/psync 失败和超时换路、NotFound 不重试、迟到读隔离、被动摘除、恢复窗口、单主线程调度、跨后端复用同一子线程、超时换线程、迟到结果隔离,以及旧探测卡住时同一后端仍可恢复。此前 A2 44/44 推理验证针对旧的主动探测版本;本次被动探测版本尚未重跑 A2,不能沿用该结果证明新逻辑。
源码入口
ucm/store/posix/cc/space_layout.cc:选路、被动反馈、恢复循环及CheckHealth。ucm/store/posix/cc/io_engine_aio.h、trans_queue.cc、trans_io.h:AIO/psync 重试、超时与缓冲区所有权。ucm/store/detail/health_window.h:滑动窗口与状态切换。ucm/store/detail/health_check_executor.h:子线程复用、超时替换、迟到结果隔离及退出回收。ucm/store/detail/store_health_config.h:共用默认值与参数校验。
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ucm/store/posix/cc/space_layout.cc, then read the AIO and health components in ucm/store/posix/cc/io_engine_aio.h, trans_queue.cc, trans_io.h, and ucm/store/detail/. Run the reported CPU CTest suite and compare its coverage with the specified startup checks, routing, retries, recovery windows, timeout handling, and thread behavior; done means the 66/66 validation remains passing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend, databases, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 20/100