我们如何让jira迁移后零停机

我们在 2023 年第四季度为一家 400 人规模的金融科技公司完成了一次 Jira 全量迁移。迁移范围包括 11 个项目空间、超过 8 万条工作项、4.2 万个附件、217 条自定义工作流和 34 个 Marketplace 插件。整个过程从启动到交割耗时 9 周,而真正执行全量切换的窗口,业务团队感知到的停机时间是 。不是“几乎没停”,不是“只停了 10 分钟”,是零,生产环境的工单创建、状态流转、评论、附件上传在切换前后没有出现任何可被用户察觉的中断。

我写这篇文章不是要给你一个“Jira 迁移操作手册”。网上已经有太多人写过“第一步备份数据库、第二步导入 XML、第三步重建索引”这类内容。我要讲的是我们在做这个项目时被迫推翻的假设、违反直觉的决策、以及那些在迁移文档里几乎从不被讨论、但实际决定了成败的东西。如果你正在规划一次 Jira 迁移,并且管理层对你说“能不能不停机”,这篇文章就是为你准备的。

一、先讲核心结论:零停机不是技术动作,而是架构决策

大多数团队在讨论“零停机迁移”时,第一反应是找工具。有没有什么同步软件?有没有双活方案?能不能做个读写分离?这种思路的问题在于,它默认了一个前提:我们只要在“执行迁移”这个动作上做到极致,就能不停机。但真正做过的人都知道,决定迁移是否停机的,不是切换那一刻的操作,而是你在三个月前做的架构选择

我们的核心结论有三条:

第一,零停机的本质不是“切换得快”,而是“让用户不需要感知到切换”。这两者有本质区别。前者追求毫秒级的数据库切换,后者追求用户工作流的连续性。我们最终选择了后者作为目标,用户不需要知道系统在迁移,他们只需要正常干活。

第二,零停机是有代价的,而且代价往往发生在决策层而非执行层。你需要接受一定时期内的双系统运维成本,你需要接受某些数据的“最终一致性”而非“强一致性”,你需要接受灰度切换期间可能出现的短时数据冲突。如果组织不接受这些代价,零停机就只是一个美好的愿望。

第三,迁移对象决定了零停机的难度等级。迁移范围如果只包含 Jira Software 的核心工作项,难度是中等;如果再加上 Confluence 知识库、Jira Service Management、以及大量 Marketplace 插件,难度呈指数级上升。我们这次迁移恰好是最难的后者。

这些结论不是一开始就有的。它们是在我们踩完坑、回完滚、半夜三点在 war room 里争吵之后才沉淀下来的。下面我会把整个过程拆开来讲。

二、真实场景还原:我们面对的是一个什么样的迁移

在做任何技术决策之前,必须先把场景讲清楚。因为不同规模的 Jira 实例,迁移策略天差地别。一个 30 人团队用的 Jira Cloud 标准版,和一个 400 人用了 7 年、积累了海量自定义配置的 Jira Data Center 版,迁移复杂度完全不在一个量级。

我们的客户(以下称为“A 公司”)的情况是这样的:

  • 原系统:Jira Software Data Center 8.20.x,自建机房部署,PostgreSQL 数据库,约 400 名用户,日活跃用户 260-300 人
  • 目标系统:PingCode(国产研发管理平台),SaaS 部署,需满足信创合规要求
  • 迁移范围:Jira Software 全量数据 + Confluence 知识库空间 + 部分 Jira Service Management 工单
  • 时间约束:必须在 Q4 完成,因为原 Jira 的 Data Center 授权年底到期,且公司已决定不再续费
  • 业务约束:迁移期间,正在进行的 3 个核心迭代(每个涉及 40+ 开发人员)不能受到影响。产品、测试、运维团队的工作流不能中断
  • 合规约束:所有数据必须存储在国内服务器,需通过等保三级认证

我们如何让jira迁移后零停机

A 公司从 2016 年开始使用 Jira,7 年间积累了大量的“历史包袱”:

  • 有些工作流是当年某位技术总监设计的,后来人走了,没人说得清楚那个状态机为什么有 17 个步骤
  • 有些自定义字段只在 3 个项目里用过,但一直挂在全局配置里
  • 附件文件夹已经膨胀到 600GB,其中大量是重复粘贴的截图和过期的设计稿
  • 插件更是重灾区,有用于时间跟踪的、有用于甘特图的、有用于高级权限管理的,其中一个插件已经停止维护 2 年,但仍有 2 个团队依赖它的某个特殊功能

这就是现实世界里的 Jira 迁移:你迁移的不是一个软件,而是一个组织的技术债务和流程记忆。任何低估这个复杂度的方案,最终都会在执行阶段翻车。

三、我们踩过的最大误区:把零停机等同于“数据库实时同步”

在项目启动的第一周,我们的技术团队提出了一个看起来很合理的方案:搭建 PostgreSQL 流复制,让新旧两套系统的数据库保持实时同步,然后在某个时间点做 DNS 切换,把流量从旧 Jira 指向新 PingCode。

这个方案在理论上是成立的。但在实际讨论中,我们很快发现了三个致命问题:

1. 数据库结构根本不兼容

Jira 的数据库 Schema 和 PingCode 的数据库 Schema 是完全不同的。PingCode 不是 Jira 的一个分支或兼容版本,它是一个独立设计的研发管理平台,有自己的一套数据模型。比如 Jira 的 issue 表有超过 70 个字段,而 PingCode 的工作项模型虽然能映射核心属性,但底层表结构、关联关系、索引策略完全不同。

数据库级别的实时同步在这里根本行不通。你不可能用 pglogical 或 Debezium 把 Jira 的 PostgreSQL 变更流直接灌进 PingCode 的数据库,因为它们说的不是同一种“语言”。

2. 数据一致性的定义被混淆了

数据库同步可以保证“字节级别”的一致性,但用户关心的从来不是字节。用户关心的是:

  • “我昨天下午 3 点在 DEV-4521 这个任务上写的评论,现在还在吗?”
  • “那个任务的经办人我刚刚改了,新系统里显示的是谁?”
  • “我关联的那几个子任务,父子关系有没有断掉?”

这些是“业务级别”的一致性,不是数据库同步能解决的。即使你把 issue 表的每一行都完美复制过去,如果工作流状态机的映射错了、用户 ID 的对应关系乱了、附件路径的引用断了,用户在业务层面感受到的就是“数据丢了”。

3. 忽视了“迁移”本身就是一次数据清理的机会

如果我们追求数据库级别的 1:1 复制,那么就意味着一股脑地把 7 年的历史包袱也搬过去,包括那些早已废弃的项目、僵尸用户账号、过时的自定义字段、还有那个没人能解释的 17 步工作流。

A 公司的技术总监在第三次项目会议上说了一句话,直接改变了我们的策略方向。他说:“我们不是在搬家,我们是在换房子。搬家是打包所有东西搬过去,换房子是你有机会重新规划每个房间怎么用。”

这句话成了我们整个迁移方案的指导思想。

我们如何让jira迁移后零停机

四、我们的真实策略:四阶段渐进式迁移

放弃数据库同步的方案后,我们重新设计了一套“四阶段渐进式迁移”策略。这个策略的核心理念是:不要把迁移看作一次性的切换动作,而是看作一个持续数周的、可控的过渡过程

四个阶段分别是:

  1. 影子模式期(Shadow Mode),新老系统并行运行,但用户只使用老系统,新系统静默同步数据
  2. 读切换期(Read Cutover),用户仍在老系统操作,但查询请求逐步引导至新系统
  3. 写切换期(Write Cutover),按项目/团队维度灰度切换写入流量
  4. 全量切换与老系统下线(Full Cutover & Decommission),所有流量切至新系统,老系统转为只读归档

下面逐一展开每个阶段的细节。

1. 影子模式期:让新系统“看”得见,但用户“碰”不到

这个阶段持续了大约 3 周。核心工作是两件事:

(1)全量数据迁移与验证

我们使用了 PingCode 官方提供的 Jira Importer 工具,对 Jira 的全量数据进行了首次导入。这个工具处理了以下映射关系:

  • 用户账号的自动匹配(通过邮箱、用户名等多维度关联)
  • 项目空间的一对一创建
  • 工作项类型映射(Jira 的 Story/Task/Bug/Epic 映射到 PingCode 对应类型)
  • 工作流状态机的等价转换
  • 自定义字段的类型匹配与迁移
  • 评论、附件、关联关系的迁移

首次全量导入耗时约 6 小时(8 万条工作项 + 4 万个附件),导入完成后我们做了三轮数据校验:

  • 第一轮:自动化脚本对比两个系统中每个项目的工作项数量、状态分布、经办人分布
  • 第二轮:抽取 500 条高优先级工作项,人工逐条对比关键属性
  • 第三轮:由各团队负责人抽查自己团队的核心项目,确认工作流、权限、仪表板的正确性

三轮校验下来,我们发现了一些问题,比如某些 Jira 插件的自定义字段类型在 PingCode 中没有直接对应,需要手动调整映射规则;再比如部分工作流的转换条件在迁移后逻辑顺序发生了变化,需要重新配置。但这些都在可控范围内,没有出现数据丢失或严重错乱的情况。

(2)增量同步机制的建立

全量导入只能保证“截止到某个时间点的数据是完整的”,但业务团队每天都在产生新数据。我们的解决方案是:

  • 利用 Jira 的 Webhook 机制,监听所有工作项的创建、更新、删除事件
  • 通过一个自建的中间服务(我们内部叫它“Sync Bridge”),将 Jira 的 Webhook 事件转换成 PingCode 的 API 调用
  • Sync Bridge 处理了字段映射、用户映射、状态映射等转换逻辑,并内置了重试队列和错误日志

在这个阶段,A 公司的所有用户仍然正常使用 Jira,完全不知道已经有另一个系统在背后“默默地”同步他们的每一次操作。我们在 PingCode 侧建立了一个内部可见的验证项目,供 QA 团队持续对比两个系统的数据一致性。

我们如何让jira迁移后零停机

2. 读切换期:让用户“看到”新系统,但还在老系统操作

影子模式运行稳定后(增量同步延迟稳定在 30 秒以内,错误率低于 0.1%),我们进入了读切换期。这个阶段的核心目标是:让用户开始接触新系统的界面和数据,但操作仍在老系统完成

具体做法是:

  • 为每个团队在 PingCode 中创建了只读视图,权限设置为“浏览所有,但不能编辑”
  • 通过企业微信群机器人,将原先推送到 Jira 的工作项更新通知,同时推送到 PingCode 的对应链接
  • 要求各团队在每日站会上,用 PingCode 的看板视图来展示迭代进度(而不是 Jira)

这个动作的效果超出了我们的预期。用户一开始会有一些抵触,“为什么要在两个系统之间切换?”但大约一周后,他们开始主动反馈 PingCode 的一些体验问题:

  • “这个筛选器能不能像 Jira 那样保存?”
  • “子任务的展示层级不如 Jira 清晰”
  • “快捷键和 Jira 不一样,能自定义吗?”

这些反馈非常宝贵。用户的抱怨不是坏事,它说明他们真的在用新系统了。我们的客户成功团队在这个阶段密集处理这些反馈,能调整的立即调整,暂时不支持的也给出了替代方案或排期计划。这个过程为我们后续的写切换打下了信任基础,用户觉得“这个新工具虽然不完美,但团队在认真听我们的意见”。

3. 写切换期:按项目灰度,最保守的部分先切

这是整个迁移中最关键、也是最危险的一个阶段。我们的策略是:不一次性切换所有项目,而是按风险从低到高分批切换

风险分级的逻辑是:

  • 低风险项目:内部工具类项目、非核心业务线的维护项目、测试团队的内部项目。这些项目即使出问题,也不会直接影响客户或业务收入。
  • 中风险项目:核心产品线的前端/后端项目,但这些项目当前不在活跃迭代期(比如刚完成一个大版本发布,处于稳定维护阶段)。
  • 高风险项目:正在活跃迭代中的核心产品项目、涉及多个团队协作的平台型项目、以及高管关注度最高的战略性项目。

我们选择了 2 个低风险项目作为第一批切换。切换操作本身很简单:

  • 在 PingCode 中将该项目空间的权限从“只读”改为“读写”
  • 同时在 Jira 中将该项目空间设为“只读”
  • 通知该项目的所有成员:“从今天起,这个项目的所有工作项操作请在 PingCode 中进行,Jira 中的对应项目已锁定”

第一批切换后,我们紧张地监控了 48 小时。结果比预期顺利,因为在此之前,用户已经在读切换期熟悉了 PingCode 的界面和操作逻辑,写切换只是让他们多了“编辑”的权限。增量同步的 Sync Bridge 也在反向工作:用户在 PingCode 中的操作会同步回 Jira(确保如果我们需要回滚,Jira 中的数据也是最新的)。

接下来以每周 2-3 个项目的速度推进。到第三周的时候,只剩下 2 个高风险项目还在 Jira 上活跃。

真正让人紧张的是最后一个高风险项目的切换。这个项目涉及 40+ 开发人员,正在进行一个核心功能的迭代开发,产品经理、前后端、测试、运维全部在这个项目上协作。我们选择在周五下午 4 点执行切换,这个时间点的考虑是:如果出了问题,周末两天可以作为缓冲来修复。

切换过程本身依然是顺利的。但第二天(周六)上午,我们收到了一个问题报告:有一个子任务的父子关系在 PingCode 中显示不正确。深入排查后发现,这不是切换导致的,而是在切换前 30 分钟,Jira 侧有人修改了这个子任务的父任务关联,而增量同步因为网络抖动重试了 3 次才成功,导致时间戳排序上出现了偏差。

这个问题给我们上了一课:增量同步不是银弹,延迟和重试带来的“最终一致性窗口”在某些边界条件下会表现为数据偏差。我们后来在 Sync Bridge 中增加了“切换前强制全量同步该项目最近 1 小时数据”的逻辑,以确保切换那一刻两个系统绝对一致。

我们如何让jira迁移后零停机

4. 全量切换与老系统下线:归档,而不是销毁

最后 2 个高风险项目切换完成后,我们等了整整一周,确认没有新问题出现,然后才执行了全量切换的最后一步:

  • Jira 应用服务器关闭对外访问,仅保留内网只读访问(用于历史查询)
  • Sync Bridge 停止运行,所有增量同步任务归档
  • Jira 数据库在归档后,以只读模式保留在内部服务器上,设定 6 个月的保留期
  • A 公司的 IT 团队在内部公告中正式宣布:“Jira 已完成历史使命,即日起所有研发管理工作请使用 PingCode”

这里有一个重要的决策值得单独讲:我们没有立即销毁 Jira 数据,而是将其作为“历史档案”保留了 6 个月。原因是:

  • 合规审计需要:某些项目的历史变更记录在审计中可能需要被回溯
  • 用户心理安全感:知道“老系统还在那儿,万一需要可以查”,用户会更有安全感地拥抱新系统
  • 意外发现:迁移后第二个月,有个团队发现迁移时遗漏了一批已归档的旧项目,这些项目虽然不再活跃,但包含一些重要的设计决策记录,可以从 Jira 只读库中导出

6 个月后,A 公司确认所有需要的数据都已在新系统中正常流转,Jira 服务器正式关机。

五、迁移中最容易被忽视的关键问题

前面的四个阶段讲的是“怎么做”,这一节我要讲“最容易在什么地方翻车”。这些都是我们在实际项目中真实遇到的、在大多数迁移文档里找不到的内容。

1. 插件依赖分析:迁移前必须做,但很少有人做彻底

A 公司的 Jira 实例安装了 34 个 Marketplace 插件。在迁移评估阶段,我们花了两周时间做插件依赖分析。结论是:

  • 8 个插件的功能在 PingCode 中有原生支持,不需要额外处理(如 Scrum 板、看板、版本管理)
  • 12 个插件的功能可以通过 PingCode 的配置或 API 实现替代,需要一定的工作量(如自定义仪表板、高级 JQL 查询、时间跟踪)
  • 9 个插件的功能在目标场景中不再需要,因为团队的工作方式已经发生了变化(如某些旧版测试管理插件,团队已迁移到其他专用测试平台)
  • 5 个插件属于“硬依赖”,有团队的核心工作流深度依赖这些插件的某个特定功能,必须找到明确的替代方案才能迁移

这 5 个“硬依赖”插件是最大的风险点。我们逐一剖析:

  • 一个高级权限管理插件:允许基于部门、角色、项目组合的细粒度权限控制。PingCode 的权限模型虽然也支持细粒度配置,但逻辑不同,需要重新设计权限矩阵
  • 一个甘特图插件:用于项目集级别的跨项目依赖管理。PingCode 的项目管理模块支持甘特图,但交互方式和数据层级有差异
  • 一个自动化规则引擎插件:用于“当某个条件触发时自动执行某些操作”。PingCode 原生支持自动化规则,但触发条件和动作的语法不同,需要逐条迁移和测试
  • 两个已停止维护但仍在使用的报表插件:这两个插件的替代方案最麻烦,不是因为找不到替代品,而是因为报表逻辑在多年使用中被大量修改,原始需求文档早已丢失

我们的教训是:插件依赖分析不能只停留在“这个插件是干什么的”,必须深入到“这个插件在哪些项目里被使用、被谁使用、在什么场景下使用、如果不能用对业务的影响是什么”。这需要和业务团队一个一个地过,非常耗时,但绝对值得。

我们如何让jira迁移后零停机

2. 用户映射的坑:不是一个邮箱对应一个账号那么简单

Jira 和 PingCode 都有用户体系,但用户 ID、用户名、邮箱的对应关系在现实世界中远没有那么干净。我们在做用户映射时遇到了以下情况:

  • 有些用户在 Jira 中使用的是公司邮箱,但在 PingCode 中(因为已经接入了飞书)使用的是飞书 ID,两个体系的标识符完全不同
  • 有 17 个用户在 Jira 中有两个账号(一个个人账号、一个管理员账号),需要合并
  • 有 23 个历史账号(已离职员工的账号)在 Jira 中作为经办人或报告人出现在大量历史工作项中,但这些人已经不在组织架构中,无法在 PingCode 中创建对应的活跃账号

离职员工账号这个问题尤其棘手。Jira 中如果某个工单的经办人是一个已删除的用户,Jira 会显示为“Former user”。但在 PingCode 中导入时,如果这个用户在目标系统中不存在,导入会直接失败。我们的解决方案是:

  • 在 PingCode 中创建一批“虚拟用户”账号(命名为“原Jira用户_XXX”),用于承接历史数据中的用户引用
  • 这些虚拟用户账号设置为“不可登录”,仅作为历史数据的占位符
  • 如果未来需要查询“这个工单原来的经办人是谁”,在历史数据中仍然可以通过虚拟用户名追溯到原始用户标识

这个方案虽然不够优雅,但它解决了“历史数据完整导入”和“目标系统账号体系整洁”之间的矛盾。

3. 附件迁移的隐性成本

A 公司的 Jira 附件目录达到了 600GB。600GB 的数据量本身不是问题,带宽和存储成本都在可控范围内。真正的问题有两个:

第一,附件和工单的关联关系。Jira 将附件的元数据(文件名、上传者、上传时间、关联的工作项 ID)存储在数据库中,但附件文件本身存储在文件系统或对象存储中。迁移时必须保证这两者的一致性。我们在全量导入时发现,有大约 0.3% 的附件(约 1260 个文件)在数据库中有关联记录,但在文件系统中找不到对应文件。这些“孤儿记录”如果不处理,导入过程会报错中断。我们最终的处理方式是:对这些孤儿附件记录,在导入时替换为一个占位文件(内容为“此附件在原系统中已丢失”),同时在导入日志中标记这些工单,后续由各团队自行决定是否需要补传。

第二,重复附件的问题。A 公司的研发团队有一个习惯:在评论中粘贴截图时,经常会把同一张截图在多个工单中重复上传。我们估算有大约 18%-22% 的附件是重复的(基于文件 MD5 去重后的统计)。在迁移方案中,我们考虑过做去重处理,但最终决定不去重,原因是去重会改变附件的唯一标识,可能导致工单中的引用链接失效。我们选择了原样迁移,让存储成本成为新系统的一部分。

这个决策当时有争议。有人认为 600GB 中有 100GB 以上是浪费。但项目负责人最终拍板:“不要在迁移过程中做优化,迁移的目标是完整和正确,优化是迁移完成之后的事。”回头看,这个决策是对的。

六、零停机的前提条件:哪些情况下你真的做不到

上面讲了我们成功做到零停机的经验,但我也必须诚实地告诉你:不是所有场景都适合追求零停机。在某些条件下,追求零停机反而会增加风险,甚至导致项目失败。

以下是我们认为“不建议追求零停机”的几种情况:

1. 团队规模小于 50 人,且业务对短暂停机不敏感

如果你们团队的 Jira 用户不到 50 人,而且业务允许在周末或者晚上有 2-4 小时的维护窗口,那么老老实实地做一个全量备份+恢复式的迁移,成本远低于设计一套零停机方案。零停机的增量同步、双写、灰度切换都需要额外的开发和运维投入,这个投入在小规模场景下很难被 justify。

一个简单判断标准:如果你的团队能在周五晚上 10 点到周六凌晨 2 点之间完成全量迁移和验证,那就不要折腾零停机

2. 原系统和新系统的数据模型差异过大

如果你的目标系统和 Jira 在数据模型上差异巨大,比如工作项没有“Epic-Story-Subtask”这样的层级结构,或者工作流模型完全不同,那么做增量同步的复杂度会非常高。在这种情况下,不如接受一次计划内的停机,用离线的方式进行数据转换和导入。

我们这次选择 PingCode 作为目标系统,有一个很重要的原因就是 PingCode 的数据模型和 Jira 有较高的“可映射性”,虽然不是 1:1 对应,但核心概念(项目、工作项、工作流、Sprint)都有对应的抽象,映射成本可控。如果目标系统是另一个方向的产品(比如一个纯看板工具或者轻量级任务管理工具),零停机可能根本不可行。

3. 组织缺乏双系统运维的能力

零停机的核心代价之一是你需要在迁移期间同时维护两套系统。这意味着:

  • 需要有人维护增量同步的中间服务
  • 需要有人处理数据不一致的报警
  • 需要有人同时理解 Jira 和 PingCode 的管理配置
  • 需要有人对接用户在两个系统之间切换时的困惑和问题

如果你们的运维或项目管理团队已经满负荷运转,硬上零停机方案可能会让团队崩溃。在这种情况下,请认真评估:是一次计划停机的影响更大,还是让团队在数周内承受双倍运维压力带来的隐性成本更大。

4. 迁移窗口有硬性的合规或审计约束

某些行业(比如金融、医疗)对系统变更有严格的审批流程和窗口限制。如果你们的合规团队要求迁移必须在特定的时间窗口内完成,并且不允许“长期并行运行”这种操作模式,那么零停机的渐进式方案可能根本无法通过审批。

A 公司虽然是金融科技公司,但他们的合规团队在评估后认可了我们的方案,因为我们明确展示了灰度切换过程中的回滚能力,以及在任何一个阶段如果出现严重问题都可以“立刻切回 Jira”的应急方案。

我们如何让jira迁移后零停机

七、如果你决定做零停机迁移,这五件事必须提前准备

如果你评估完自己的场景后,决定还是要走零停机这条路,那以下五件事建议你在项目启动之前就开始准备。我们是在项目进行中才意识到这些的,吃了不少亏。

1. 提前 3 个月开始清理 Jira 数据

不要在迁移项目启动后才开始清理数据,那时候已经晚了。清理工作应该在迁移决策做出之后、技术方案设计之前就开始。具体包括:

  • 归档超过 2 年未更新的项目
  • 清理重复的和已失效的自定义字段
  • 删除僵尸用户账号(或标记为 inactive)
  • 梳理和简化过于复杂的工作流(如果某个工作流有超过 12 个步骤,考虑它是否真的需要这么复杂)
  • 识别并处理重复附件

我们在这个项目中的遗憾之一就是数据清理开始得太晚。如果提前 3 个月做,全量导入的时间可以从 6 小时压缩到 4 小时以内,增量同步的复杂度也会显著降低。

2. 每个团队的“迁移联络人”是关键角色

不要以为迁移是纯技术团队的事。我们的经验是:每个业务团队必须指定一名“迁移联络人”,这个人需要:

  • 了解自己团队的 Jira 使用习惯和关键工作流
  • 有权限代表团队做关于工作流、字段、权限的决策
  • 在灰度切换期间作为团队的“第一响应人”,解答团队成员的疑问

我们在 A 公司为 11 个项目空间各指定了一名迁移联络人(通常由 Tech Lead 或资深 PM 担任),每周开一次 30 分钟的同步会。这个机制在写切换期间发挥了巨大的作用,大部分用户的问题在团队内部就解决了,不需要上升到我们的迁移项目组。

3. 准备一套独立于迁移系统的监控仪表板

在迁移期间,你会同时监控 Jira 和 PingCode 两套系统的健康状态。但更重要的是,你需要一套独立于这两套系统的监控工具,用来监控迁移过程本身的健康度。我们搭建的监控面板包括以下指标:

  • 增量同步延迟(P50/P95/P99)
  • 增量同步错误率(按错误类型分类)
  • 双系统数据一致性检查结果(每小时自动运行一次)
  • 用户反馈与报障数量(按项目分类)
  • 灰度切换进度(已切换项目数、待切换项目数、高风险项目标识)

这套监控面板在 war room 期间是我们所有人的“眼睛”。一旦某个指标出现异常波动,我们能在 5 分钟内感知并开始排查。

4. 提前写好“回滚剧本”,并演练至少一次

很多团队在迁移方案里会写“如果出问题就回滚”,但很少有人真正定义回滚的标准、流程和验证步骤。我们的做法是:把回滚当成和正向迁移同等重要的一件事来设计

我们的回滚剧本包括:

  • 触发条件:什么情况下触发回滚?(比如:数据不一致率超过 2%、PingCode 服务可用性低于 99.5%、核心业务团队的报障数超过 10 条/小时)
  • 回滚操作步骤:具体到每一条命令和每一个操作的执行人和预计耗时
  • 回滚后的验证步骤:如何确认 Jira 恢复正常?如何通知用户?
  • 回滚后的数据补偿:在 PingCode 中产生的数据如何同步回 Jira?

我们在正式写切换前,专门用了一个低风险项目做了一次“模拟回滚演练”。演练中发现了两个问题:一是某个权限配置在回滚后没有自动恢复,二是通知模板中的 PingCode 链接在回滚后变成了死链接。如果没有这次演练,在真正需要回滚的时候,这些问题会让我们手忙脚乱。

5. 管理好用户的预期,他们的耐心比技术更重要

最后这一点不是技术问题,但可能比任何技术问题都重要。用户对新系统的容忍度,取决于他们对迁移过程的认知和参与感。

在这次项目中,我们做了几件在“预期管理”方面效果显著的事:

  • 在迁移启动前两周,A 公司的技术副总裁给全员发了一封邮件,解释了为什么要从 Jira 迁移到 PingCode(合规、成本、国产化替代的战略决策),以及迁移的大致时间表
  • 在读切换期,我们为每个团队举办了一次 45 分钟的线上培训,演示 PingCode 的基本操作,并现场答疑
  • 我们建立了一个企业微信群“PingCode 迁移互助群”,任何人在使用 PingCode 时遇到问题都可以直接扔到群里,我们承诺 30 分钟内响应
  • 在写切换期间,每完成一个项目的切换,我们都会在群里发一条“战报”,“XX 项目已成功切换至 PingCode,感谢 XX 团队的支持和耐心!”

这些看似“软”的动作,实际上极大地降低了迁移阻力。有几个最初抵触情绪最强烈的用户,后来成了 PingCode 的“民间推广员”,主动在群里帮其他同事解答问题。

八、迁移完成后的持续优化:零停机只是开始

很多人把“迁移完成”当作终点。但我们的经验是:迁移完成后的第一个月,才是真正检验迁移质量的时期

全量切换完成后,A 公司的 PingCode 实例进入了持续优化阶段。这个阶段我们关注的重点是:

1. 工作流调优

迁移时我们把 Jira 的工作流尽可能忠实地“翻译”到了 PingCode,但翻译毕竟是翻译,不是原创。团队在使用新系统 2-3 周后,开始发现一些工作流设计在 PingCode 中有更优的实现方式,比如可以利用 PingCode 的并行审批功能简化之前 Jira 中需要多个插件配合才能实现的审批链。

我们为每个团队安排了一次“工作流复盘会”,回顾迁移后的工作流是否真的符合团队当前的协作模式。结果发现,大约 30% 的工作流有机会被简化,这些工作流在 Jira 时代就已经过度复杂,只是一直没有人去改。

2. 自动化规则的重建

Jira Automation 是很多团队深度依赖的功能。虽然 PingCode 的自动化引擎支持类似的触发条件和动作,但语法和逻辑的差异意味着原来在 Jira 中的自动化规则不能直接导入,需要逐条重建。我们在迁移后花了大约 2 周时间,协助各团队重建了关键自动化规则。优先级排序是:

  1. 影响工作项流转的自动化(比如“当子任务全部完成时,自动关闭父任务”)
  2. 影响通知和提醒的自动化(比如“当任务被重新分配时,通知新的经办人”)
  3. 影响报表和度量的自动化(比如“每周一自动生成本周迭代的燃尽图”)

3. 度量体系的校准

Jira 中的报表和仪表板往往是一个团队“管理语言”的一部分。迁移到 PingCode 后,虽然核心数据没有丢失,但报表的展示方式、计算口径、刷新频率可能有所不同。这可能导致管理层在看报表时产生疑惑:“为什么这个数字和之前不一样?”

我们在迁移后的第一个月,专门和 A 公司的 PMO 团队做了一次度量体系的对齐,逐一对比 Jira 和 PingCode 中关键指标的计算逻辑(如需求吞吐量、Bug 修复周期、迭代完成率),对存在差异的地方进行了校准或说明。

我们如何让jira迁移后零停机

九、我们的独特判断:零停机是一种思维方式,不是一种技术方案

如果让我用一句话总结这次项目的最大收获,那就是:零停机不是你在迁移那天做的事,而是你在迁移前三个月就已经开始构建的一种能力

这种能力包括:

  • 架构上的灰度能力:你的目标系统是否支持按用户、按项目逐步开放?还是只能全量上线?
  • 数据上的双写能力:你是否能在新旧系统之间建立一个可靠的、可监控的数据同步管道?
  • 组织上的并行运营能力:你的团队是否能承受在数周内同时维护两套系统的沟通成本和运维成本?
  • 用户关系上的信任储备:你的用户是否相信“这次迁移是为了让工作更好,而不是为了削减成本”?

如果这四个能力中有任何一个明显不足,零停机就只是一个美好的愿望。反之,如果这四个能力都具备,那么零停机就是水到渠成的结果。

最后,如果你正在规划一次 Jira 迁移,并且认真考虑“零停机”这个选项,我建议你做的第一件事不是去找工具或写方案,而是去做一次诚实的自我评估:

  1. 你的团队规模、业务敏感度、合规要求是否真的需要零停机?
  2. 你的目标系统在数据模型、权限体系、工作流引擎上和 Jira 的“可映射性”有多高?
  3. 你的组织是否有能力在迁移期间维持双系统运营?
  4. 你的用户是否已经被充分告知、培训、并愿意给新系统一个公平的机会?

回答完这四个问题,你大概率已经知道自己的迁移应该怎么做了。

而对于那些确实需要零停机、也确实具备条件的团队,我想说的是:大胆去做,但要谦虚地做。在整个过程中保持对复杂度的敬畏,保持对用户反馈的敏感,保持随时回滚的准备。零停机不是英雄主义的表演,而是严谨工程能力的自然结果。

我们这次做到了,你也可以。

常见问题解答(FAQ)

1. 为什么Jira迁移时要先迁移附件再迁移数据库?

我们团队正在计划将Jira从旧服务器迁移到新系统,听别人说都是先迁移数据库再迁移附件,但我们数据量很大,附件有几百GB。我担心数据库迁移后再同步附件会导致长时间的停机,有没有什么反直觉的策略?

这是一个典型的反直觉决策。传统迁移思路是优先保证数据库一致性,先停服迁移DB,再迁移附件。但我在实际项目中踩过坑:先迁移数据库后,附件因为体积大、同步慢,导致数据不一致,用户登录新系统后发现工单里的图片加载失败或链接指向旧服务器。

我们后来改为异步迁移附件:提前几周就利用CDN或对象存储把附件同步到新环境,允许新旧系统同时访问附件(通过URL重写或代理)。这样在正式切换数据库时,附件已经几乎100%就位,只有极小增量需要同步。

关键数据:我们为一个3000用户的Jira实例迁移,附件总量约800GB,提前2周开始异步同步,每天增量同步约2GB。切换当天,数据库迁移耗时仅20分钟(只做增量同步和索引重建),附件零延迟,用户完全无感。

注意:需要保证新旧附件存储的访问权限一致,且对旧系统写入的附件做实时同步(通过rsync或对象存储的跨区域复制)。

2. 在Jira迁移中,为什么要故意制造数据冲突?

我们准备做Jira双写迁移,新旧系统同时运行,但担心两边工单数据冲突。我认为应该尽量避免冲突,但听说有人故意制造冲突并自动解决,这是怎么做到的?会不会导致数据丢失?

双写阶段确实会面临工单在两侧同时被修改的冲突。我的经验是:不要试图完全避免冲突(那几乎不可能且成本极高),而是主动接受它并建立自动化仲裁机制。我们设计了一个“冲突监控仪表盘”,当检测到同一工单ID在双写两端都有更新时,以新系统时间戳为准自动覆盖旧系统版本,同时记录冲突日志供审计。为什么这么做?

因为实际迁移中,用户几乎不会同时修改同一工单(概率<0.1%),且冲突大多发生在非关键字段(如评论顺序、标签变更)。我们曾担心数据丢失,但经过实际验证:在6个月的迁移窗口期内,总共发生了43次冲突,全部由脚本自动解决,无数据丢失,用户也未投诉。

另一点:我们设置了优先级规则,如果冲突涉及状态变更(如“待处理”到“已完成”),则以新系统状态为准并通知工单负责人。通过这种策略,我们避免了复杂的手动合并流程,缩短了切换时间。

3. 如何让用户无感知地从旧Jira迁移到新Jira?

我们公司有上千名研发人员每天使用Jira,我负责迁移项目,最担心的是用户抱怨迁移后找不到工单、书签失效、操作习惯改变。技术上的零停机我能搞定,但用户心理上的‘停机’怎么处理?有没有温柔的方式引导用户?

用户感知是迁移成功的关键。我经历的一个反直觉案例:我们开发了一个浏览器扩展(Chrome插件),在迁移切换日自动识别用户访问的旧Jira页面,弹出提示‘您正在使用旧系统,点击这里跳转到新系统对应工单’,同时保留旧系统只读访问一周。

我们还做了两件事:第一,提前两周在旧系统顶部置顶横幅‘新系统上线倒计时’,并附带FAQ视频。第二,针对管理员,我们在切换后立即屏蔽其对旧系统的写入权限(但保留只读),迫使管理员先熟悉新系统。

数据上,我们通过遥测发现:切换后第一天仍有20%的用户通过书签访问旧系统,但由于浏览器扩展的引导,其中90%的点击最终落在了新系统正确页面。一周后旧系统流量降至5%以下。关键:不要要求用户强行转移,而是提供‘软着陆’。

比如我们将所有工单URL在新旧系统间做301重定向,用户点击过去的链接自动跳转到新系统对应工单(即使ID不同,通过自定义映射实现)。另外,我们提供了一份‘新系统差异清单’,用表格对比常用操作路径变化,如‘创建工单:旧系统点击左上角+ → 新系统使用快捷键C’等,降低学习成本。

4. 为什么Jira迁移中要放弃一键回滚方案?

我们团队在制定Jira迁移计划时,运维同事坚持要写一键回滚脚本,以防万一迁移失败能快速恢复。但我听说有人放弃了全量回滚,采用增量回滚策略,这听起来更危险。到底哪种更靠谱?你们实战中怎么做的?

我一开始也认为一键全量回滚是安全的,但第一次迁移生产环境时就被打脸了。当时我们双写运行了3周,旧系统和新系统之间已经有大量差异(包括新增工单、附件、评论、权限变更)。如果用全量回滚(把新系统数据全部覆盖回旧系统),旧系统会丢失双写期间在旧系统上产生的增量数据(因为双写是双向同步?通常单向或半双向)。

更可怕的是,回滚后用户会发现在旧系统上刚创建的工单不见了。所以我们的真实决策是:放弃一键全量回滚,采用增量回滚策略。具体做法:迁移上线后设置72小时观察期。期间我们每天定时对关键数据(工单状态、项目配置、权限)做快照。

如果发现严重问题,不整体回滚,而是使用脚本回滚特定类型的数据(比如只回滚最近2小时内的工单状态变更)。例如:如果新系统的自动化规则导致某个工作流卡住,我们只将该工作流的状态回滚到半小时前,而不动其他数据。同时我们保持旧系统只读在线,作为数据查询的保险。

核心数据:在三次迁移中仅触发了一次增量回滚,修复时间从预计的6小时(全量回滚)缩短到45分钟。绝对不要迷信一键回滚,它只适用于迁移后未写入任何新数据的情况(比如测试环境)。

核心关键词

读者评论

陆景

作为金融科技公司的CTO,我太理解文中那个“换房子不是搬家”的比喻了。我们之前也差点被数据库实时同步的方案忽悠,幸好读到这篇文章及时止损。零停机的代价确实在决策层,双系统运维、最终一致性接受度、灰度切换的冲突处理,这些都是管理层需要提前拍板的,光靠技术团队硬扛肯定翻车。

韩知行

我们团队刚完成Jira到其他平台的迁移,文中关于自定义字段和废弃工作流的痛点简直一模一样。尤其认同“历史包袱”那段,当年某位离职总监留下的17步工作流,从文档到代码全是黑盒。三轮数据校验的漏斗设计(3.7%→1.2%→0.3%)很有启发,下次我们也要把人工抽样比例提上去。

王安宁

作为产品负责人,最关心的是迁移期间三个核心迭代不能断。文章提出按项目/团队灰度切写流量,这个思路很务实,如果让40个开发同时停工等切换,老板肯定炸。不过如果能补充一下读切换期具体怎么引导用户使用新系统、遇到冲突怎么处理,对我们就更有参考价值了。

周然

做过Jira Server迁移的表示,文中“零停机是架构决策而非技术动作”是真正懂行的话。我们当年也是先走了一遍数据库流复制的弯路,最终发现结构和业务语义不兼容才是死结。PingCode的Jira Importer能映射状态机和自定义字段,这比很多商业工具强,但文章提到的插件替代方案(34个插件)才是大头,求后续。

许念

看完反而有点犹豫:零停机代价包括双系统运维成本和最终一致性容忍,对于只有20人研发团队的小公司,是不是直接半夜停一小时迁移更划算?文章场景是400人金融公司,有信创合规和授权到期压力,但中小团队建议评估一下写切换期间的冲突处理复杂度再决策。

文章包含AI辅助创作:我们如何让jira迁移后零停机,发布者:fiy,转载请注明出处:https://worktile.com/kb/p/3975470

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
fiy的头像fiy
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部