无人值守时也能运行的同步:六条规则

两个 SaaS 工具之间按计划运行、无人看管的自动化数据同步,需要六条规则:游标、投递键、同一时间只有一次运行、有上限的重试、对静默发出告警,以及每次运行都必须证明的已发布规则。每一条都对照了 Tajo 同步运行器今天的实际做法,包括它做得不够的地方。

自动化数据同步

一个自动化数据同步要在无人看管时安全运行,需要什么?

无人值守运行的同步需要六条规则。从游标读取,只有整批数据全部送达后才移动它。给每次写入一个重试时能重新推导出来的键,已完成的键保留七天。让一次运行独占同步,并在每次写入前证明这一点。失败的运行以逐渐拉长的等待重试五次,连续五次运行失败后暂停同步。24 小时内没有任何成功就告警。让每次运行都证明自己就是已发布的那个版本。Tajo 的运行器完整遵守了其中五条。例外是静默:一个本该读取失败、却返回空结果的来源,只能被部分发现。

了解更多
在本页面

2026 年 10 月 8 日,Lance Martin 和 CJ Avilla 发布了一篇关于某个智能体的详解。这个智能体每天早上读取 Slack 和 GitHub,再把一份简报发到 Slack。它运行时没有人盯着。他们最有用的一段,讲的是一种看起来像成功的失败。当某个来源的服务器宕机或令牌过期时,“智能体从那个来源什么也看不到,于是报告‘没有新内容’。”

从 Shopify 到 Brevo 的联系人同步也有同样的失败。两个 SaaS 工具之间的每一个计划同步都有。一次悄悄失败的读取,看起来和一家今天没人注册的店铺一模一样。

他们的文章以六条规则收尾,写给无人值守运行的智能体。以运维同步的人的眼光去读,每一条都是一条 reverse ETL 规则。Worker 挂了,同步没有跟踪了一个联系人如何穿过一次崩溃。本页是它上面一层的检查清单:自动化数据同步的六条规则,Tajo 的运行器今天对每一条做了什么,以及哪里还做得不够。运行器这一侧写在恢复卡住或失败的同步里。

1. 从书签读取,只有批次全部送达才移动它

他们的第一条规则:“从书签读取每个来源,而不是从固定的时间窗口读取。”“最近 24 小时”这样的窗口,在运行晚启动时会留下空白,在运行早启动时会重复读取记录。

Tajo 的同步从一个保存下来的游标开始,按批次读取来源。游标在一个批次结束时移动,而且只在该批次的每条记录都已送达时才移动。失败的运行会保留上一个干净的位置,所以下一次运行会重新读取被中断的批次,而不是跳过它。

订单有自己的书签。计划运行的 Shopify 订单同步从它的第一次计划运行开始,发送自上一次以来发生变化的内容。历史订单只有在有人手动运行同步时才会发送。计划运行和人工启动的运行各自保存游标,所以一次历史回填或一个测试批次都无法把计划游标倒回去。

代价是被中断的批次会被读取两次。让这件事变得安全的是规则 2。

2. 给每次写入一个能挺过崩溃的键

他们的第四条规则规定,只有“在 Slack 确认之后”,一条消息才算已发送,而且只有到那时才更新书签和记录。挂号信就是这样运作的。签收回执寄回来才算送达,而不是离开柜台的那一刻。

Tajo 写入一条记录之前,这条记录会得到一个投递键。这个键是同步、来源、页游标、页内位置和记录本身的哈希值,所以它不包含任何个人数据。它在调用目标系统之前被占用,写入成功后标记为已完成。已完成的键会保留七天。重试,或之后的一次计划运行,会为同一条记录推导出同一个键,发现它已完成,于是不再调用目标系统。

这带来两个代价。七天之后账本就会遗忘,从更早的游标重放可能会再次写入。而一次超时的写入会留下一个实实在在的疑问:对方系统可能已经保存了它,只是没有回应。Tajo 会在之后的某次尝试中重试这次写入,而不是把它记为失败、保留七天。一个能把自己的幂等键交给目标系统的连接器,可以消除这个疑问。做不到的连接器,就留下了出现一条重复记录的可能。

3. 一次运行独占同步,并在每次写入前证明这一点

他们的第三条规则:“在发布前一刻重新检查每一项。”对同步来说,读取和写入之间最可能发生变化的,是谁有权写入。

每个 Tajo 同步都有一个租约,带有自己的令牌,有效期 15 分钟,每五分钟续期一次。运行在调用目标系统之前会检查自己是否仍持有租约,在移动游标之前还会再检查一次。失去租约的运行会停下来,它的页面会显示“运行中途失去了运行名额,为避免重复写入而停止。”与一次正在进行的运行撞上的第二次运行,会直接结束,而不是排在它后面。

记录也会被检查。在读取和写入之间,记录要经过同意过滤。一个在没有可证明同意的情况下要写入营销受众的联系人会被拒绝,而不是靠猜。用帮助页面的话说,失败模式始终是“过于谨慎”,而不是“过度发送”。

4. 重试会过去的失败,停下不会过去的失败

他们的六条规则没有说多久重试一次。同步需要这条规则,因为它最常见的失败是速率限制和供应商那边短暂的故障。

排队中的 Tajo 运行失败后,会有五次尝试。尝试之间的等待依次是 60、120、240 和 480 秒,总共约十五分钟。有些失败永远不会重试,因为再试一次也解决不了。与一次已在进行的运行撞上的运行不会重试,已发布版本或连接已不再有效的运行也不会重试。

连续失败和偶发故障是两回事。如果自同步上次修改以来,最近五次已结束的运行全部失败,Tajo 会暂停这个同步,并在它的页面上显示最后一次错误。一次成功就会让计数清零。没有任何东西会自动重启已暂停的同步;要由一个人修复原因,再重新发布。那篇 worker 挂掉的文章讲了催生这条规则的那次事故。

5. 把静默当作一项发现

“把失败的读取报告为无法读取,绝不要当成平静的一天。”这是六条里最难的一条,也是我们唯一只做到一部分的一条。

做到的部分:报错的读取会让运行失败。被拒绝的令牌或没有响应的服务器,不会向目标系统发送任何东西,会让游标留在原处,并计入连续五次运行失败后的暂停。另外,每小时的第 13 分钟,Tajo 会检查每个有活跃同步的工作区。如果过去 24 小时内没有一次成功运行,包括根本没有记录到任何运行的工作区,它就会告警自己的团队。这就是每小时检查。

没做到的部分:作者描述的那种静默读取,是回答“OK”却没有任何记录的读取。我们的运行器把它算作成功。对于 Shopify 客户这类来源,如果该同步以前产生过记录,另有一项检查会在连续十次成功运行都返回零条记录后警告 Tajo 团队。Shopify 订单按更新时间读取,所以那里出现空运行很正常,这项检查不会运行。一个返回了一些记录、但少于应有数量的来源,则完全不会被发现。

反对意见是这样的:“按 15 分钟一次的计划,十次空运行就是两个半小时。为什么不在第一次就告警?”联系人同步确实默认每 15 分钟运行一次。而一家店铺一刻钟内没有新客户,再平常不过。在第一次空运行时就告警,每晚都会响,而一个总在响的告警没人会看。这条线用速度换取了可信度。它仍然是对静默的一种猜测,而不是作者的那条规则。

6. 一次性决定同步可以写什么,并让每次运行都证明这一点

他们的第五条规则把智能体的偏好设置存放在“一个智能体无法编辑的存储里”。第六条规则在智能体只做读取的地方只给它只读权限,并限制每次运行能花多少钱。两条规则存在的原因都是:智能体会读取别人写的文本,而这些文本可能试图向它发号施令。

对同步来说,偏好设置文件对应的是已发布的规则。发布一个 Tajo 同步,会把它绑定到一个摘要(digest),摘要对应的正是预览过的那条规则。编辑它会让它回到草稿状态,再次运行前要重新经过预览。每次运行在改动任何东西之前,都会检查自己运行的正是那个已发布版本,使用的也正是发布时的连接。没通过这项检查的运行不会重试。方向也是固定的:同步规则只朝一个方向写入,绝不回写到 Shopify。

花费上限在这里没有对应物。我们的同步运行没有按次计算的花费上限。重试上限和暂停限制的是一次失败能持续多久,而不是一次运行要花多少钱。

已经建好的,和还没建好的

截至撰写本文时已经建好的:

  • 一个游标,只在一个每条记录都已送达的批次之后才移动;还有一个计划订单游标,人工启动的运行无法把它倒回去。
  • 每条记录一个投递键,对照保留七天的已完成写入账本进行检查。
  • 每个同步一个租约,在写入前和移动游标前都会检查。
  • 每次运行五次尝试,先等 60 秒,再依次等 120、240 和 480 秒;遇到冲突或发布无效时不重试。
  • 连续五次运行失败后暂停,并显示在同步的页面上。
  • 过去 24 小时内没有任何运行成功时,每小时发出告警。
  • 对写入营销受众的联系人在运行时进行同意过滤,并在每次运行时检查它是否为已发布版本。

还没建好、在你依赖它之前值得知道的:

  • 读取成功但返回零条记录,不会被报告为无法读取。十次运行的警告覆盖了其中一部分。它不覆盖 Shopify 订单,也不覆盖返回记录过少的来源。
  • 24 小时告警发给 Tajo,而不是发给你,十次运行的警告也一样。暂停倒是会显示在同步的页面上。
  • 每小时检查看的是工作区,而不是每个同步。一个健康的同步会掩盖它旁边那个静默的同步。
  • 没有按次计算的花费上限。
  • 没有任何东西会重启已暂停的同步。要由一个人来做。
  • 五次失败后的暂停和 24 小时检查是为整个 Tajo 部署统一设置的,而不是按同步设置。

当这些情况出现在你自己的同步上时,恢复卡住或失败的同步会告诉你看到的是什么、该怎么做。

作者的六条规则,是为一个人每天早上阅读的简报写的。同步根本没有早上的读者,所以它更需要这些规则。第一到第四条和第六条,今天已经是我们运行器里的代码。第五条只写了一半:一个读不到自己来源的同步,应该把这件事说出来。

常见问题

一个自动化数据同步要在无人看管时安全运行,需要什么?

六样东西。一个只在整批数据全部送达后才移动的游标。每条记录一个投递键,重试时会重新推导出同一个键,并对照已完成写入的账本进行检查。每个同步同一时间只有一次运行。有上限的重试次数,运行持续失败时就暂停。一整天没有任何成功时发出告警。还有一条已发布的规则,每次运行都必须证明自己执行的正是它。

为什么同步不应该读取固定的时间窗口,比如最近 24 小时?

因为运行并不准时。启动晚了的运行会留下一段窗口永远覆盖不到的空白,启动早了的运行会把记录读两遍。保存下来的游标让每次运行都从上一个干净批次结束的地方开始,无论运行何时启动。

Tajo 如何防止重试的同步把同一条记录写两次?

每条记录都有一个投递键,它是同步、来源、页游标、页内位置和记录本身的哈希值。键在调用目标系统之前被占用,写入成功后标记为已完成,已完成的键保留七天。重试或之后的运行会推导出同一个键,不会再次调用目标系统。

当来源因为读取悄悄失败而什么都没返回时,Tajo 能发现吗?

只能发现一部分。报错的读取会让运行失败,这次运行会计入连续五次运行失败后的暂停。读取成功但返回零条记录,会被算作成功。对于 Shopify 客户这类来源,如果该同步以前产生过记录,在连续十次成功运行都返回零条记录后,Tajo 团队会收到警告。对于按更新时间读取的 Shopify 订单,这项检查不会运行。

申请抢先体验

请输入您的名字和电子邮箱地址。我们会发送确认 Tajo 访问申请的链接。

获取Brevo

本页的 Markdown: six-rules-unattended-sync.md

正在加载 Markdown…