---
title: "无人值守时也能运行的同步：六条规则"
description: "两个 SaaS 工具之间按计划运行、无人看管的自动化数据同步，需要六条规则：游标、投递键、同一时间只有一次运行、有上限的重试、对静默发出告警，以及每次运行都必须证明的已发布规则。每一条都对照了 Tajo 同步运行器今天的实际做法，包括它做得不够的地方。"
url: https://tajo.io/zh-cn/blog/six-rules-unattended-sync/
markdown: https://tajo.io/zh-cn/blog/six-rules-unattended-sync.md
lang: zh-CN
author: "Set Noa"
author_url: https://tajo.io/zh-cn/set-noa/
published: 2026-11-06
updated: 2026-11-06
alternates: {en-US: /blog/six-rules-unattended-sync.md, bg-BG: /bg/blog/six-rules-unattended-sync.md, cs-CZ: /cz/blog/six-rules-unattended-sync.md, de-DE: /de/blog/six-rules-unattended-sync.md, da-DK: /dk/blog/six-rules-unattended-sync.md, es-ES: /es/blog/six-rules-unattended-sync.md, fr-FR: /fr/blog/six-rules-unattended-sync.md, el-GR: /gr/blog/six-rules-unattended-sync.md, hi-IN: /hi/blog/six-rules-unattended-sync.md, id-ID: /in/blog/six-rules-unattended-sync.md, hr-HR: /hr/blog/six-rules-unattended-sync.md, hu-HU: /hu/blog/six-rules-unattended-sync.md, it-IT: /it/blog/six-rules-unattended-sync.md, ja-JP: /jp/blog/six-rules-unattended-sync.md, ko-KR: /kr/blog/six-rules-unattended-sync.md, ar-SA: /ar/blog/six-rules-unattended-sync.md, nl-NL: /nl/blog/six-rules-unattended-sync.md, no-NO: /no/blog/six-rules-unattended-sync.md, pl-PL: /pl/blog/six-rules-unattended-sync.md, pt-BR: /pt/blog/six-rules-unattended-sync.md, ro-RO: /ro/blog/six-rules-unattended-sync.md, ru-RU: /ru/blog/six-rules-unattended-sync.md, sv-SE: /se/blog/six-rules-unattended-sync.md, sl-SI: /sl/blog/six-rules-unattended-sync.md, sr-Latn-RS: /sr/blog/six-rules-unattended-sync.md, th-TH: /th/blog/six-rules-unattended-sync.md, tr-TR: /tr/blog/six-rules-unattended-sync.md, ur-PK: /ur/blog/six-rules-unattended-sync.md, vi-VN: /vi/blog/six-rules-unattended-sync.md, sk-SK: /sk/blog/six-rules-unattended-sync.md}
---

[数据同步](https://tajo.io/zh-cn/blog/?category=data-sync)

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

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

自动化数据同步

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

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

[了解更多](https://tajo.io/zh-cn/blog/six-rules-unattended-sync/#1-%E4%BB%8E%E4%B9%A6%E7%AD%BE%E8%AF%BB%E5%8F%96%E5%8F%AA%E6%9C%89%E6%89%B9%E6%AC%A1%E5%85%A8%E9%83%A8%E9%80%81%E8%BE%BE%E6%89%8D%E7%A7%BB%E5%8A%A8%E5%AE%83)

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

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

他们的文章以六条规则收尾，写给无人值守运行的智能体。以运维同步的人的眼光去读，每一条都是一条 [reverse ETL](https://tajo.io/zh-cn/blog/what-is-reverse-etl/) 规则。[Worker 挂了，同步没有](https://tajo.io/zh-cn/blog/worker-died-sync-didnt/)跟踪了一个联系人如何穿过一次崩溃。本页是它上面一层的检查清单：自动化数据同步的六条规则，Tajo 的运行器今天对每一条做了什么，以及哪里还做得不够。运行器这一侧写在[恢复卡住或失败的同步](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/)里。

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

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

Tajo 的同步从[一个保存下来的游标](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#cursor)开始，按批次读取来源。游标在一个批次结束时移动，而且只在该批次的每条记录都已送达时才移动。失败的运行会保留上一个干净的位置，所以下一次运行会重新读取被中断的批次，[而不是跳过它](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#cursor)。

订单有自己的书签。[计划运行的 Shopify 订单同步](https://tajo.io/zh-cn/resources/help/getting-started/understanding-data-sync/)从它的第一次计划运行开始，发送自上一次以来发生变化的内容。历史订单只有在有人手动运行同步时才会发送。计划运行和人工启动的运行各自保存游标，所以一次历史回填或一个测试批次都无法把计划游标倒回去。

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

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

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

Tajo 写入一条记录之前，这条记录会得到[一个投递键](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#ledger)。这个键是同步、来源、页游标、页内位置和记录本身的哈希值，所以它不包含任何个人数据。它在调用目标系统之前被占用，写入成功后标记为已完成。已完成的键会[保留七天](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#ledger)。重试，或之后的一次计划运行，会为同一条记录推导出同一个键，发现它已完成，于是[不再调用目标系统](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#ledger)。

这带来两个代价。[七天之后账本就会遗忘](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#limits)，从更早的游标重放可能会再次写入。而一次超时的写入会留下一个实实在在的疑问：对方系统可能已经保存了它，只是没有回应。Tajo 会在之后的某次尝试中重试这次写入，而不是把它记为失败、保留七天。一个能把自己的幂等键交给目标系统的连接器，可以消除这个疑问。做不到的连接器，就留下了出现一条重复记录的可能。

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

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

每个 Tajo 同步都有[一个租约](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#lease)，带有自己的令牌，有效期 15 分钟，每五分钟续期一次。运行在调用目标系统之前会检查自己是否仍持有租约，在移动游标之前还会再检查一次。失去租约的运行会停下来，[它的页面会显示](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#failures)“运行中途失去了运行名额，为避免重复写入而停止。”与一次正在进行的运行撞上的第二次运行，会[直接结束，而不是排在它后面](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#retries)。

记录也会被检查。在读取和写入之间，记录要经过[同意过滤](https://tajo.io/zh-cn/resources/help/getting-started/understanding-data-sync/)。一个在没有可证明同意的情况下要写入营销受众的联系人会被拒绝，而不是靠猜。用[帮助页面的话说](https://tajo.io/zh-cn/resources/help/getting-started/understanding-data-sync/)，失败模式始终是“过于谨慎”，而不是“过度发送”。

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

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

排队中的 Tajo 运行失败后，会有[五次尝试](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#retries)。尝试之间的等待依次是 60、120、240 和 480 秒，总共约十五分钟。有些失败[永远不会重试](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#retries)，因为再试一次也解决不了。与一次已在进行的运行撞上的运行不会重试，已发布版本或连接已不再有效的运行也不会重试。

连续失败和偶发故障是两回事。如果自同步上次修改以来，最近五次已结束的运行全部失败，Tajo 会[暂停这个同步](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#pause)，并在它的页面上显示最后一次错误。一次成功就会让计数清零。[没有任何东西会自动重启已暂停的同步](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#pause)；要由一个人修复原因，再重新发布。那篇 worker 挂掉的文章讲了催生这条规则的那次事故。

## 5. 把静默当作一项发现

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

做到的部分：报错的读取会让运行失败。被拒绝的令牌或没有响应的服务器，不会向目标系统发送任何东西，会让[游标留在原处](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#cursor)，并计入[连续五次运行失败后的暂停](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#pause)。另外，[每小时的第 13 分钟](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#hourly-check)，Tajo 会检查每个有活跃同步的工作区。如果过去 24 小时内没有一次成功运行，包括根本没有记录到任何运行的工作区，它就会告警自己的团队。这就是[每小时检查](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#hourly-check)。

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

反对意见是这样的：“按 15 分钟一次的计划，十次空运行就是两个半小时。为什么不在第一次就告警？”联系人同步确实[默认每 15 分钟运行一次](https://tajo.io/zh-cn/resources/help/getting-started/understanding-data-sync/)。而一家店铺一刻钟内没有新客户，再平常不过。在第一次空运行时就告警，每晚都会响，而一个总在响的告警没人会看。这条线用速度换取了可信度。它仍然是对静默的一种猜测，而不是作者的那条规则。

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

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

对同步来说，偏好设置文件对应的是已发布的规则。发布一个 Tajo 同步，会[把它绑定到一个摘要（digest）](https://tajo.io/zh-cn/resources/help/getting-started/understanding-data-sync/)，摘要对应的正是预览过的那条规则。编辑它会[让它回到草稿状态](https://tajo.io/zh-cn/resources/help/getting-started/understanding-data-sync/)，再次运行前要重新经过预览。每次运行在改动任何东西之前，都会检查自己运行的正是那个已发布版本，使用的也正是发布时的连接。没通过这项检查的运行[不会重试](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#retries)。方向也是固定的：同步规则[只朝一个方向写入](https://tajo.io/zh-cn/resources/help/getting-started/understanding-data-sync/)，绝不回写到 Shopify。

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

## 已经建好的，和还没建好的

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

- [一个游标](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#cursor)，只在一个每条记录都已送达的批次之后才移动；还有一个计划订单游标，人工启动的运行无法把它倒回去。
- [每条记录一个投递键](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#ledger)，对照保留七天的已完成写入账本进行检查。
- [每个同步一个租约](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#lease)，在写入前和移动游标前都会检查。
- [每次运行五次尝试](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#retries)，先等 60 秒，再依次等 120、240 和 480 秒；遇到冲突或发布无效时不重试。
- [连续五次运行失败后暂停](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#pause)，并显示在同步的页面上。
- 过去 24 小时内没有任何运行成功时，[每小时发出告警](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#hourly-check)。
- 对写入营销受众的联系人在运行时进行同意过滤，并在每次运行时检查它是否为已发布版本。

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

- 读取成功但返回零条记录，不会被报告为无法读取。十次运行的警告覆盖了其中一部分。它不覆盖 Shopify 订单，也不覆盖返回记录过少的来源。
- [24 小时告警发给 Tajo](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#hourly-check)，而不是发给你，十次运行的警告也一样。暂停倒是会显示在同步的页面上。
- [每小时检查看的是工作区](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#limits)，而不是每个同步。一个健康的同步会掩盖它旁边那个静默的同步。
- 没有按次计算的花费上限。
- 没有任何东西会重启已暂停的同步。要由一个人来做。
- [五次失败后的暂停和 24 小时检查](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#limits)是为整个 Tajo 部署统一设置的，而不是按同步设置。

当这些情况出现在你自己的同步上时，[恢复卡住或失败的同步](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/)会告诉你看到的是什么、该怎么做。

作者的六条规则，是为一个人每天早上阅读的简报写的。同步根本没有早上的读者，所以它更需要这些规则。第一到第四条和第六条，今天已经是[我们运行器里的代码](https://tajo.io/zh-cn/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/)。第五条只写了一半：一个读不到自己来源的同步，应该把这件事说出来。

## 常见问题

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

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

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

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

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

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

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

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

## 相关文章

### [Worker 挂了，同步没有](https://tajo.io/zh-cn/blog/worker-died-sync-didnt/)

2026年11月5日 · 7 分钟阅读

6 个章节

### [Brevo 集成：选择能够验证的连接方式](https://tajo.io/zh-cn/blog/brevo-connector-guide/)

2026年8月19日 · 4 分钟阅读

6 个章节

### [如何使用脚本（Python、Node.js、cURL）将 CSV 或 Excel 联系人导入 Brevo](https://tajo.io/zh-cn/blog/import-csv-contacts-to-brevo-with-a-script/)

2026年4月30日 · 4 分钟阅读

CSV → Brevo
