事情本身不复杂,线索都在日志里。三个 Agent 共用 Redis 里同一个 session key,各自把整个任务状态序列化后 SET 回去,最后一步读到的版本总是缺字段,前面的检索结果和工具输出都丢了。

第一反应是「key 设计成单个 JSON,字段一多就互相踩」,验证下来不成立。

把日志和配置对完,能解释这个现象的基本就这几处。整段 SET 覆盖,没有按字段合并。少数情况下是没有版本号或乐观锁,后写直接盖掉先写。

不容易想到的是,TTL 到期后多个 Agent 同时重建,写回顺序不可控。

动手时先看 key 里现在剩下哪些字段

redis-cli --raw GET session:88 | python -m json.tool

随后改成 hash 结构,每个 Agent 只写自己的字段

redis-cli HSET session:88 step1 '{"docs":[1,2]}'

接着用 WATCH 加 MULTI 做乐观锁更新

redis-cli --eval merge_state.lua session:88 , '{"step":2}'

给状态加 version 字段,冲突时重读再写

python -c "print({'version':3,'retry_on_conflict':True})"

恢复的判定其实很直接。三个 Agent 交替写入后字段一个不少,version 单调递增,重放同一批任务不再出现状态缺失。

容易忽略的是,共享记忆的写入粒度要小,按字段合并加版本校验是底线,整段覆盖在并发下必然丢数据,靠重试也补不回来。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189