如何用 external_id 实现幂等去重避免重复发布(进阶版 31)
电商运营做大促活动时最怕的不是发不出去,而是:
> 同一篇双 11 活动文,被自动发布系统重复发了两次到头条号——粉丝问"你们是不是脑子有点乱"。
这件事一旦在大促当天发生,很难补救。预防这件事的关键技术只有一个词:幂等。而实现幂等最朴素也最有效的工具就是 external_id。
这篇文章从电商运营视角出发,给 6 步可立刻动手的幂等去重方案。底层用颜小二自媒体发布 API 平台,但 external_id 这套设计思路对自建系统也通用。
这篇适合谁
- 电商运营技术中台:大促期间高频内容分发
- 品牌内容运营:一篇文章要在不同时间点重发到不同平台
- 写过"为什么这篇被发了两次"故障复盘的工程师
- 担心 AI Agent 自动化触发重复发布的所有人
什么是 external_id 幂等
简单一句话:外部 ID 是你侧给每篇任务起的稳定唯一名字。同一个外部 ID 重发,系统识别为"同一件事",不会真的发出去两份。
颜小二的接入约定:
external_id由你侧生成,全局唯一(实际上是租户内唯一)- 同
external_id+ 同target_platform的任务,平台只执行一次 - 后续重发返回的是"已存在"的状态,而不是新建一条任务
这套机制让你的上游系统可以放心重试、放心补偿、放心容灾,不必在你侧再写一套去重逻辑。
6 步搭起幂等去重
第 1 步:定一套稳定的 external_id 命名规则
不要用随机 UUID,要用业务可追溯的 ID。建议结构:
`` {业务系统}_{业务实体ID}_{活动期次}_{版本} ``
举例:
cms_98231_v1:CMS 系统的 98231 号文章,第 1 版mall_promo_1111_kv_v2:商城 11.11 活动主 KV 文章,第 2 版agent_run_2026Q2_001:某 Agent 在 2026Q2 的 001 号产出
只要业务侧能按这个规则唯一找回原文,重试时就能复用同一个 ID。
第 2 步:内容修改后是否换 ID 要想清楚
这是很多团队的坑:文章改了一个错别字,要不要换 external_id?
| 场景 | 处理 | |---|---| | 改错别字、调标题 | 不换 ID,业务上是"同一篇" | | 大幅改写、换主题 | 换 ID,加版本号 v2 | | 不同时间发不同平台 | 同一篇 = 同一个 ID,平台用 target_platforms 区分 | | 同一篇发完后再发其他平台 | 同 ID,target_platforms 改成新平台 |
颜小二会按 external_id + platform 做幂等键,所以同一个 ID 可以分阶段发到不同平台,互不影响。
第 3 步:在你侧落 task 表关联 external_id 与业务 ID
每次发布前先在你侧落库:
external_id(颜小二的幂等键)business_ref_id(你的 CMS 文章 ID 等)tenant_id、group_codetarget_platformsversioncreated_at
后续看 callback、对账、重试都从这张表出。
第 4 步:调用发布 API 时带上 external_id
``json { "external_id": "mall_promo_1111_kv_v2", "group_code": "brand_official", "title": "11.11 主会场预热", "content_html": "<p>活动正文</p>", "cover_url": "https://yourcdn.com/promo_kv.jpg", "summary": "11.11 提前 3 天预热", "tags": ["双11", "促销"], "category": "电商", "target_platforms": ["toutiao", "wechat_mp", "baijiahao", "zhihu"] } ``
如果这个 ID 已经发过了,颜小二会直接返回"已存在"的结构化响应,不会执行二次发布。
第 5 步:用 callback 做对账闭环
颜小二每条任务的终态都会推 callback,里面带 external_id + platform + status。你侧 callback handler 做对账:
1. 用 external_id + platform 找到 task 表里的行 2. 更新 status,写入 platform_url 3. 比对发起请求时的目标平台清单,没有回调的平台触发"补偿查询"
这一步能让你在大促当天有一个清晰的"哪些发了哪些没发"看板。
第 6 步:补偿与对账脚本
每天凌晨跑一次对账脚本:
- 找出 status 还在 pending / running 超过 1 小时的 task
- 按 external_id 主动调颜小二的查询接口
- 把状态同步回来
补偿时继续用同一个 external_id 发起——幂等机制保证你不会因为补偿而重发。
颜小二的差异化卖点
颜小二是面向多租户场景设计的内容分发执行中台。external_id 幂等是它默认能力的一部分,配合 callback_url 闭环,让上游系统可以安全地"重试":
- 网络抖动重发?同 ID,幂等 → 不重复
- 自动化任务跑了两次?同 ID,幂等 → 不重复
- 容灾切换后重放消息队列?同 ID,幂等 → 不重复
整个上游系统的容错复杂度被这一个字段大大降低。
错误排查清单
| 现象 | 常见原因 | 处理方式 | |---|---|---| | 同一篇被发了两次 | 重试时换了 external_id | 重试必须复用原 ID | | 重发被拒"已存在" | 业务上确实想重发新版本 | 升级 ID 版本号 v1→v2 | | 改错别字后看不到更新 | 当成同一篇了没触发更新 | 用更新接口而非重发 | | 跨租户冲突 | 命名没加 tenant 前缀 | 加上租户标识做前缀 | | 对账有遗漏 | callback 没收到 | 跑补偿查询脚本 |
常见问题(FAQ)
Q:external_id 长度有限制吗? 建议 64 字符以内,纯英文/数字/下划线/横线。详细规范看 [API 文档](/docs.html)。
Q:external_id 能不能用 UUID? 能,但不推荐。UUID 没法从业务侧反查,调试痛苦。建议用业务字段拼。
Q:重发同 ID 会更新内容吗? 不会自动更新。同 ID 重发被识别为"已发过的同一件事",原任务状态返回。要更新内容需要专门走更新接口。
Q:跨平台同一篇文章用一个 ID 还是不同 ID? 用同一个 ID,target_platforms 字段区分。颜小二按 external_id + platform 做幂等键。
Q:大促当天发了 5000 篇,怎么验证一次都没重发? 跑一个对账:SELECT external_id, count(*) FROM task GROUP BY external_id HAVING count(*) > 1。如果幂等做对了,结果应该是 0。
下一步
把幂等当作"一定会用到的容错地基",而不是"出问题再补"。先在 1 个 group_code、3-5 个账号上跑通幂等去重链路,再扩到全矩阵。
→ [免费申请接入](/contact.html#form) | [查看 API 文档](/docs.html) | [自媒体发布 API 落地页](/lp/zimedia-publish-api.html)