事情本身不复杂,线索都在日志里。Qdrant 1.12 批量 upsert 4000 条,代码里为了提速写了 wait=False,紧接着 count 只回 980 条,带过滤的查询也查不到刚写的数据,sleep 两秒再查才补齐,拆成 500 条一批也没改善。
第一反应是「集合刚创建还没 load 到内存」,验证下来不成立。
真正麻烦的地方在于,几个原因的现象几乎一样。wait=False 返回时点还没建好索引。少数情况下是查询打到了只读副本存在复制延迟。
另外,批次内有重复 id 被后写覆盖。
小批量改成 wait=True 对比返回时间
curl -X PUT 'http://localhost:6333/collections/docs/points?wait=true' -H "content-type: application/json" -d '{"points":[{"id":1,"vector":[0.1,0.2],"payload":{"t":"a"}}]}'
随后用 exact 计数核对条数
curl -X POST 'http://localhost:6333/collections/docs/points/count' -H "content-type: application/json" -d '{"exact":true}'
再往下按 id 直接 retrieve 排除索引延迟
curl -X POST 'http://localhost:6333/collections/docs/points' -H "content-type: application/json" -d '{"ids":[1,2,3],"with_payload":true}'
等前面都确认过,再把 wait 做成参数只在离线导入时关闭
python import_points.py --file points.jsonl --wait true
这类改动我都写进变更记录,过两周再出问题时能对上号。
恢复的判定其实很直接。upsert 返回后立刻 count 等于 4000,随机抽 20 个 id 都能 retrieve 到,过滤查询不再缺数据。
容易忽略的是,wait=True 只保证当前节点写入完成,多副本场景还要看 replication_factor 和副本状态。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
