问题出现得很突然,日志倒是留得挺全。文档更新走的是先删后写,删除请求异步执行,写入却同步完成,结果新版本先落库、旧版本后删除,同一 doc_id 在集合里出现两份,检索出来内容互相矛盾。

刚开始盯着「写入没有做幂等,重复消费会再插一条」,折腾了半个多小时,排掉了。

原因不止一个,得分开看。删除与写入没有顺序保证。也可能是主键用了随机 uuid 而不是业务 doc_id。

不容易想到的是,缺少按 doc_id 的条数巡检。

先按 doc_id 统计重复条数

python -c "import json,collections;d=json.load(open('coll.json'));print([k for k,v in collections.Counter(x['doc'] for x in d).items() if v>1][:10])"

再往下改成用 doc_id 作为主键 upsert

python upsert.py --collection faq --id-field doc_id --file docs.jsonl

接着删除改成按 doc_id 条件删除并等待确认

python delete.py --collection faq --where 'doc_id=="A123"' --wait

末了跑一次全量巡检确认无重复

python dup_check.py --collection faq --field doc_id

怎么算真的好了,看的是同一批现象。同一 doc_id 只剩一条记录,巡检报告里重复数为 0,检索结果不再出现新旧两版内容。

先删后写在没有顺序保证时必然打架,能 upsert 就别删;主键一定要用业务 id,用随机 id 等于放弃幂等。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189