Goldsky Turbo重复投递如何核?分checkpoint、落地主键与重组修正
链小知 · 进阶 · 核验 · 依官方文档整理
从已有管线与接收材料检查重复是否被安全处理,不把200回执或主键配置当完整准确一次。
开始前准备
- 准备自己已有的脱敏配置、日志或状态回执,保留产品版本、对象、字段和日期;缺值不补成成功或零。
1. 固定Turbo输入和接收对象
记录管线、source→transform→sink路径、数据集版本、接收表或endpoint和primary_key。Turbo与legacy Mirror、subgraph、Feeds属于不同入口;本篇按Turbo当前投递契约解释。沿每个transform保留稳定记录键,缺原schema/key时不臆造transaction hash唯一性或删除事件编码。
检查结果:产品、管线路径、接收对象和稳定键有记录;未知schema保持待核。
2. 定位写成功到offset提交的重复窗口
官方至少一次协议先让每个sink flush并ACK同一epoch,全部ACK后再finalizer通知source提交位置。崩溃若发生在落地成功与source提交之间,重启会重放上次已提交位置之后的数据;已写批次的网络重试也可能重复。epoch是checkpoint序号,不是链上事件ID,不能替稳定记录键。
检查结果:重复位置与提交阶段对齐;没有把源offset、epoch和业务记录ID当同一个对象。
3. Postgres有主键才是upsert
sink.primary_key可为逗号分隔列;设置后默认on_conflict=update,无主键是普通INSERT。on_conflict=nothing仅忽略冲突,不会更新;update_where把每列EXCLUDED与现表比较并用AND合成条件,只在update模式生效,nothing会忽略。按原配置核是否允许预期更正;已有表不会自动ALTER新增列,schema变化可能在插入时报错,不能将写失败当无事件。
检查结果:主键、冲突模式和更新条件分别明确;重组更正与schema失败没有被静默跳过。
4. Webhook回执与接收幂等分开
one_row_per_request=true为单对象,false默认批次数组;batch_size默认1000、batch_flush_interval默认1s是flush控制,不是engine checkpoint间隔。2xx确认批次;网络/超时、408、429与5xx无限指数退避,其他4xx立即失败管线。primary_key用于checkpoint/旁路跟踪,不替接收端去重;接收程序须按稳定键去重或让副作用幂等,不能把重试后2xx当只执行了一次。
检查结果:对象/数组、HTTP分支、flush与checkpoint已区分;副作用去重有证据或未知。
5. 把重复处理与重组修正分别验收
重组导致的delete/update沿管线传播;支持主键的数据库sink将其应用为upsert/delete,append-only的Kafka/S3/webhook须由消费者应用修正。恢复后不保证重启前后顺序,去重不能简单忽略同键全部后续更正。缺实际修正payload/消费结果时只确认官方路径,不能推canonical状态已收敛;Postgres聚合sink跨epoch重投不去重,也不能套普通表效果。计量中的创建、更新、删除均算写入,写入数不等独立链上事件数。
检查结果:重复幂等、delete/update、顺序与最终状态各有结果或缺项;未把写入计量当事件数。
怎样确认完成
- 形成输入、官方判定方法、已知结果和未知分支的对照;方法已核,实际运行与本人权限未验证。
常见错误与边界
- 至少一次加幂等目的地才可能达到effectively exactly-once结果;平台没有一个开关替不幂等接收端解决问题。
- checkpoint不持久化中间transform内存状态,重启重放重新派生;链上最终性与投递协议是不同判断。