Repository navigation
v6.27.0 LockFairness — OverGraph 锁公平:消除写队列 503 与 /health 劣化
v6.27.0 LockFairness — 消除 OverGraph 全局锁饿死
根因
OverGraphStore._session_lock 是单把全局互斥锁,串行化所有图操作。检索侧
_community_expansion 为每个相关社区各调一次 get_community_members,每次都取锁 →
持锁时间长 → 写线程 _persist_entities(梦境管道)取不到锁 → 写队列积压至上限 →
WriteQueueFullError → HTTP 503;/health 自身也要查图,同样排队 → 19~23 秒。
py-spy 5 次采样实证:检索线程持锁 active / 写线程反复 blocked。
修复
| 文件 | 改动 |
|---|---|
graph/overgraph_store.py |
threading.RLock → _WriterPriorityLock(写线程优先;同线程可重入 + 跨线程互斥);新增 bind_writer_thread() 与有界 health_probe(timeout=0.5) |
retrieval/query_router.py |
N 次 get_community_members → 1 次批量取回;无批量原语的 store 回落逐社区查询,检索语义不变 |
api/app.py |
把 WriteQueue 的 worker_ident 绑给写优先锁 |
api/routes/system.py |
/health 连通性探测改用有界 health_probe,超时降级 degraded |
core/write_queue.py |
新增只读 worker_ident property(不动背压/看门狗) |
验证
| 项 | 结果 |
|---|---|
| 新增验收测试 | tests/test_overgraph_lock_fairness.py(6 用例 / 21 断言 / 真并发) |
| RED→GREEN | 暂存实现 → 6 failed;恢复 → 6 passed |
| 全量回归 | 1544 passed / 2 skipped / 5 deselected / 0 failed |
| 压测(8 读者 + 50 写) | 写队列 503 = 0 次;/health P95 = 0.301s(基线 23.2s) |
| 生产实测(重启后) | 503 = 0 次;/health 0.12~0.30s |
备注
- 交付方:太极 / DSH(Hermes 负责诊断 + 验收标准 + 独立核验)
- 既有测试
tests/test_v529_concurrency_fixes.py的锁断言同步升级为行为等价
(同线程可重入 + 跨线程互斥),断言强度不减 scripts/stress_overgraph_lock_fairness.py:AC2/AC3 压测脚本