服务之间的数据迁移:策略、风险与权衡

发布: (2026年1月19日 GMT+8 05:37)
10 min read
原文: Dev.to

Source: Dev.to

Source:

背景

最近我在一次任务中需要在两个服务之间迁移数万条审计记录!这是我第一次进行如此规模的数据迁移,我学到了很多东西,于是决定在本文中把所有经验记录下来。

基本上,数据迁移是指将一组存储在某个来源(比如数据库、电子表格或其他格式)中的信息,转换后能够被另一个服务正确消费,且符合目标端的模型和规则。

数据迁移

迁移动机

  • 需要将遗留数据迁移到新服务。
  • 不同系统开始共享职责,需要保持数据的一致交集。
  • 预先规划,能够为分析和执行争取更多时间。
  • 紧急需求,例如客户请求、某部门的需求或意外的运营需求。

迁移的决定可以来源于产品团队,也可以来源于工程团队。但工程团队有责任评估并最终确定迁移的技术可行性!这种可行性直接取决于我们对现有数据的研究。

例如,当需求来自产品时,工程通常会有更大的空间去调查复杂性、风险和成本。但这并不能仅凭一句“可以迁移,交给我吧”来解决。任何承诺之前,都必须非常重要地分析涉及数据的体量、结构和复杂度。

可行性分析

一个明显的例子:让一两个开发者停下来两次冲刺两轮 Sprint)去迁移15 条记录值得吗?在大多数情况下,不值得。工程成本可能远高于对产品的微小影响。

当然,可行性不仅仅是数字。产品的背景同样重要。以下问题有助于决策:

  • 正在迁移的是什么类型的数据?
  • 数据是简单的还是递归的?
  • 记录之间是否存在依赖关系?
  • 是否有中间状态、历史记录或业务规则与这些数据耦合?

所有这些都会直接影响最终的决定。

迁移阶段

当迁移被认为是可行的时,需要解决的问题集合通常分为三个主要阶段:

  1. 提取 – 数据将如何被提取?
  2. 转换 – 这些数据将如何适配为预期的格式?
  3. 加载 – 转换后的数据将如何发送到目标服务?

正是在这种背景下,我了解了 ETL,这是一种专门用于组织和结构化此类过程的方法(恭喜,你也学会了 ETL 是什么! :))

ETL

尽管如此,仍需强调:ETL 不是万能药。在许多情况下,创建专门的迁移应用可能是多余的复杂性。在任何实现之前,必须研究迁移的实际可行性,了解源数据的格式、转换工作量以及维护该解决方案的成本。

一般来说,当迁移需要多次执行或在未来重复使用时,ETL 更有意义。对于一次性迁移,使用更简单的方案可能更足够且更安全。

策略

小型迁移

当我处理小型迁移时,通常会选择简单的方案。尤其是,我非常喜欢使用 Jupyter Notebook,特别是当源数据位于电子表格或小型数据库时。在这些场景下,我并不觉得有必要为了执行一次性过程而构建完整的应用程序。

创建 notebook 相对简单:只需一个后缀为 .ipynb 的文件以及本地配置好的 kernel。根据具体情况,可以使用 Kotlin、Python、Deno 等多种选项。其最大的优势在于能够快速探索数据、测试转换并且轻松迭代。

Jupyter Notebook

复杂迁移

对于更复杂的迁移,我更倾向于 创建一个本地运行的终端应用——一个简单但受控的 CLI。这种方式能够:

  • 提供更高的可预见性和执行控制;
  • 便于处理大规模数据;
  • 支持版本管理和自动化(例如:CI/CD 脚本)。

典型的迁移 CLI 结构包括:

  1. 参数解析器 – 用于接收起始/结束日期、过滤条件、dry‑run 模式等参数。
  2. 抽取层 – 与数据库、API 或文件的连接器。
  3. 转换层 – 接收记录并返回目标格式的纯函数。
  4. 加载层 – 批量插入、写入文件或调用目标 API。
  5. 日志与指标 – 用于审计和监控迁移进度。

结论(第一)

  • 在开始之前评估迁移的可行性至关重要——考虑数据量、复杂性、依赖关系和工程成本。
  • ETL 是一个强大的工具,但只有在需要复用或定期执行时才应采用。
  • 对于一次性的小规模迁移,Jupyter Notebook 或临时脚本更为灵活。
  • 对于大规模或需要细粒度控制的迁移,CLI 或小型专用应用是更安全的选择。
[![Imagem da migração](https://media2.dev.to/dynamic/image/width=800,height=,fit=scale-down,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8w59uslh300rzxxop5e.png)](https://media2.dev.to/dynamic/image/width=800,height=,fit=scale-down,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8w59uslh300rzxxop5e.png)

在这里,一个根本性的关注点是拥有回滚策略。绝不能假设迁移第一次就能完美运行。尽可能在预发布环境中进行测试,再在生产环境执行,并且要与团队充分协调 rollout。

数据加载方式也很重要。在某些情况下,直接写入数据库可能足够。其他情况下,使用 API 或甚至将事件发布到队列更安全,尤其是处理大批量数据并希望以异步方式处理时。

归根结底,ETL 的形式不如最终目标重要。它可以是 notebook、CLI 或甚至一个简单脚本——只要能够安全、可预期地完成抽取、转换和加载需求。

实际挑战

缺失或不一致的数据

在真实迁移中,常常会遇到不完整、不一致或标记为已删除(例如:软删除)的数据。这些情况需要明确处理,可以忽略记录、填充默认值或标记未知数据。

数据丰富

并非所有必要信息都在同一个地方。通常需要“对接”其他数据库或服务/API以获取缺失的数据。最好从一开始就关注这一点,因为它会增加解决方案的复杂性。

技术权衡

  • 速度 vs 正确性 – 当迁移紧迫时,需要决定在不影响交付的前提下,能够接受数据不一致的程度。
  • Jupyter Notebook vs CLI – 对于小规模迁移,Notebook 能快速解决问题并提升效率!但它可能会迅速膨胀,导致可读性和可维护性下降。此时,采用 CLI 更为合适。
  • 全部迁移 vs 只迁移核心数据 – 并非所有数据都值得迁移。必须与产品团队对齐,明确哪些数据需要保留,哪些可以在知情的前提下舍弃。
  • 一次性处理全部 vs 分批处理 – 推荐将记录分成 batches(批次)处理,并在每个批次后验证结果。这种方式远优于一次性处理全部数据,后者一旦出现小的处理错误就可能需要全部重做。

结论(第二)

如果没有人注意到数据迁移在生产环境中进行,这可能是个好兆头。归根结底,一切归结为 上下文、平衡和权衡 — 并且要让团队保持一致,了解可以交付的内容。

Back to Blog

相关文章

阅读更多 »

别再像2015年那样写API

我们已经进入2025年,仍有许多代码库把 API 视为简单的“返回 JSON 的端点”。如果你的 API 设计仍停留在基本的 CRUD 路由上,你正……