问题出现得很突然,日志倒是留得挺全。文档更新走的是先删后写,删除请求异步执行,写入却同步完成,结果新版本先落库、旧版本后删除,同一 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 等于放弃幂等。报错文案容易误导,真正的原因往往在相邻那一层的日志里。
