FunctionGraph 事件重复投递的幂等设计:原子占位 + 内容指纹
背景
函数工作流(FunctionGraph)触发器在对象存储事件通知场景下是至少一次投递。网络重试、事件重复上报都会让同一个对象事件被处理多次,表现为重复写库、重复发消息。
为什么不能只靠去重表
最直接的做法是处理前查一次数据库,但高并发下查询与写入之间存在竞态,两个实例可能同时判定未处理。去重表必须依赖唯一键约束或原子写,否则挡不住并发。
幂等键设计
用 bucket + object key + ETag 组合成幂等键。ETag 随对象内容变化,同一个键重复事件指向同一份内容,天然适合做去重标识。把幂等键哈希后作为主键写入,重复写入会失败,从而只放行一次。
原子占位实现
以 Redis(DCS)为例:SET idem:{hash} 1 NX EX 86400,返回 OK 说明抢到执行权,返回 nil 说明已处理过,直接返回成功。TTL 覆盖业务最长重试窗口,避免键无限增长。没有 Redis 时可以用 OBS 的条件写:PutObject 到 .done/{hash} 并带 If-None-Match: *,冲突即已存在。
处理顺序
第一步校验事件字段完整;第二步计算幂等键并原子占位;第三步执行业务;第四步写完成标记。业务失败时释放占位键,让重试可以继续,避免死锁式阻塞。
验证方法
用同一份事件连续调用三次函数,观察业务表只有一条记录、消息只发出一条;再用并发工具同时打十个请求,确认只有一个成功占位。最后检查 TTL 过期后旧事件重放能被正确处理。
小结
至少一次投递无法在触发器侧关掉,只能在消费侧做幂等。幂等键要包含内容标识,占位要原子,失败要能释放,这三点做到,重复消费就不再是问题。
- 点赞
- 收藏
- 关注作者
评论(0)