dbaplus社群 11月10日 09:01
十亿级数据零停机迁移:系统设计与人性考量
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文作者分享了团队如何实现一项艰巨任务——将超过10亿条关键金融数据从旧数据库无缝迁移至新数据库,全程零停机。文章详细阐述了分阶段批量迁移冷数据、通过双写机制处理实时流量、利用影子读进行线上暗测,以及最终切换策略。作者强调了幂等性、重试队列、缓存预热、详尽的可观测性以及制定回滚计划的重要性。整个过程不仅是技术挑战,也充满了对系统设计原理和人性压力的深刻洞察,最终证明零停机迁移是设计而非运气的产物。

✅ **分块并行与幂等性批量迁移**:面对海量数据,直接导出易导致数据库崩溃。作者团队将数据按主键范围分块,禁用二级索引和约束,并行加载,并对每个数据块进行校验和比对,确保数据完整性。此方法强调了“分块+并行+幂等”是处理超大规模迁移的关键。

💡 **双写与重试队列实现低成本分布式事务**:为应对实时新增流量,应用层修改为双写,同时写入旧库和新库。新库写入失败的数据会进入Kafka重试队列,并通过唯一ID确保写入操作的幂等性。这种机制有效降低了数据同步的成本和风险,是处理部分失败的有效手段。

🧐 **影子读捕捉真实流量下的潜在问题**:在数据同步后,通过影子读(后台对新库执行查询并与旧库结果比对)来验证新库的可靠性。这种方法能发现测试环境难以暴露的时区差异、NULL值处理、排序规则不匹配等问题,为客户无感知地修复提供了宝贵时间。

🚀 **缓存预热与细致监控确保平稳切换**:切换数据库时,新库缓存为空是主要风险。团队通过运行合成查询预热缓存,并在流量最低谷时启用功能标志进行切换,同时保持双写开启。全程依赖Grafana仪表盘进行近乎偏执的监控,确保业务指标稳定,为成功切换奠定基础。

📊 **全面可观测性是迁移成功的生命线**:作者认为,迁移成功的关键在于可观测性。通过监控复制延迟、死锁、缓存命中率、影子读取不匹配计数以及业务关键绩效指标,团队能够及时发现并解决问题,将迁移视为一个监控问题而非单纯的数据问题。

原创 Himanshu Singour 2025-11-10 07:16 广东

有些项目,你一辈子都忘不了……

有些项目,你一辈子都忘不了。

对我来说,就是那个夜晚(其实连续了很多个夜晚),我们把超过10亿条记录从旧数据库迁移到新数据库……

全程没有一秒钟的停机。

我们迁移的是关键金融数据——支付、订单、账本。一旦出错,客户会亏钱,仪表板会崩溃,信任会在一夜之间蒸发。

我们通过研究数据库内部原理、艰难权衡以及每个决策背后的人性压力,以最痛苦的方式学会了系统设计。

我们为什么必须这么做

旧数据库一直兢兢业业地为我们服务着,但规模扩大改变了一切。

数据库记录数量突破10亿,不堪重负。业务不断增长,停机时间是不可接受的。我们别无选择:迁移。

但,这么大的数据量,怎么做到不停机迁移?

第一步:批量迁移旧数据

我们从“冷数据”入手,也就是那些不再更新的旧交易数据。

数据库内部发生了什么?

我们怎么做的:

这办法不花哨,但管用。

教训:超大迁移,别想着“一把梭”。要分块 + 并行 + 幂等。

第二步:双写,接住实时流量

复制旧数据很容易,真正的挑战在于如何应对不断增长的新流量。

试想一下:在我们复制旧数据的同时,每秒仍有数千笔新的付款信息涌入。如果我们不记录这些信息,新的数据库就会始终滞后。

我们怎么做的:

为什么可行:

在PostgreSQL/MySQL这类关系库,每次插入先写WAL(预写日志)。我们利用了这一原理,确保至少在一个地方写入成功,并不断重试,直到两个数据库的结果一致为止。

教训:双写 =低成本分布式事务。重试队列能救你于部分失败。

第三步:影子读(线上暗测)

现在旧库新库同步了。

但……我们能信新库吗?

我们的秘密武器:影子读。

我们的发现:

这些问题测试环境永远抓不到,只有真实流量才能暴露,影子读给了我们几周时间修这些坑,客户毫无感知。

教训:影子流量并非可有可无,它是赶在客户发现之前捕获查询规划器和编码不匹配的唯一方法。

第四步:切换(让人抓狂的那一夜)

系统切换日就像在备战。

风险:

我们的计划:

前10分钟……

我们盯着Grafana仪表盘,像在看病人的心电图。

没人庆祝,我们怕得要死。

24小时后,曲线依旧平静,我们才敢笑。

教训:切换不是按个开关就完事,要缓存预热 + 回滚方案 +  obsessive监控。

第五步:可观测性(我们的生命线)

如果问我什么救了我们,不是酷炫SQL,而是可观测性。

我们发现:

没有这些仪表盘,我们如同盲人摸象。

教训:迁移实际上是伪装成数据问题的监控问题。

我们面对的权衡

1、大爆炸 vs 分阶段

→ 我们选分阶段

2、ETL vs 双写

→ 我们选择了双写操作

3、迁移时是否建索引

→ 我们延迟了索引的创建

人性的一面

切换成功那一刻,我们没有欢呼,只是沉默地看绿色曲线。

然后有人开了个玩笑:

“要是明天炸了,谁来写复盘?”

我们笑了,笑得有点虚。

最终教训(如果你也要设计这种系统)

结束语

我们不仅仅是迁移了十亿条记录,我们认识到,数据迁移不是数据库问题,而是系统设计问题。

你不会一次性迁移十亿行数据。你会一次迁移一个安全批次,一次迁移一个 WAL 条目,一次迁移一个校验和。

这就是秘诀。

因为当你把迁移当作构建分布式系统来对待时,零停机时间就不是运气,而是设计的结果。

作者丨Himanshu Singour    编译丨Rio

来源丨网址:https://medium.com/@himanshusingour7/how-we-migrated-db-1-to-db-2-1-billion-records-without-downtime-c034ce85d889

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn

阅读原文

跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

数据库迁移 零停机 系统设计 高可用 数据工程 数据库 DBA 技术实践 Database Migration Zero Downtime System Design High Availability Data Engineering Database DBA Technical Practice
相关文章