10亿数据,如何做迁移?

news/2025/2/21 20:02:49/文章来源:https://www.cnblogs.com/12lisu/p/18730055

前言

某次金融系统迁移项目中,原计划8小时完成的用户数据同步迟迟未能完成。

24小时后监控警报显示:由于全表扫描SELECT * FROM users导致源库CPU几乎熔毁,业务系统被迫停机8小时。

这让我深刻领悟到——10亿条数据不能用蛮力搬运,得用巧劲儿递接

今天这篇文章,跟大家一起聊聊10亿条数据,如何做迁移,希望对你会有所帮助。

一、分而治之

若把数据迁移比作吃蛋糕,没人能一口吞下整个十层蛋糕;

必须切成小块细嚼慢咽。

避坑案例:线程池滥用引发的血案

某团队用100个线程并发插入新库,结果目标库死锁频发。

最后发现是主键冲突导致——批处理必须兼顾顺序和扰动

分页迁移模板代码

long maxId = 0;  
int batchSize = 1000;  
while (true) {  List<User> users = jdbcTemplate.query(  "SELECT * FROM users WHERE id > ? ORDER BY id LIMIT ?",  new BeanPropertyRowMapper<>(User.class),  maxId, batchSize  );  if (users.isEmpty()) {break;  }// 批量插入新库(注意关闭自动提交)  jdbcTemplate.batchUpdate(  "INSERT INTO new_users VALUES (?,?,?)",  users.stream().map(u -> new Object[]{u.id, u.name, u.email}).collect(Collectors.toList())  );  maxId = users.get(users.size()-1).getId();  
}

避坑指南

  • 每批取递增ID而不是OFFSET,避免越往后扫描越慢
  • 批处理大小根据目标库写入能力动态调整(500-5000条/批)

最近准备面试的小伙伴,可以看一下这个宝藏网站:www.susan.net.cn,里面:面试八股文、面试真题、工作内推什么都有。

二、双写

经典方案是停机迁移,但对10亿数据来说停机成本难以承受,双写方案才是王道。

双写的三种段位:

  1. 青铜级:先停写旧库→导数据→开新库 →风险:停机时间不可控
  2. 黄金级:同步双写+全量迁移→差异对比→切流 →优点:数据零丢失
  3. 王者级:逆向同步兜底(新库→旧库回写),应对切流后异常场景

当然双写分为:

  • 同步双写
  • 异步双写

同步双写实时性更好,但性能较差。

异步双写实时性差,但性能更好。

我们这里考虑使用异步双写。

异步双写架构如图所示:

代码实现核心逻辑

  1. 开启双写开关
@Transactional  
public void createUser(User user) {  // 旧库主写  oldUserRepo.save(user);  // 异步写新库(允许延迟)  executor.submit(() -> {  try {  newUserRepo.save(user);  } catch (Exception e) {  log.error("新库写入失败:{}", user.getId());  retryQueue.add(user);  }  });  
}
  1. 差异定时校验
// 每天凌晨校验差异数据  
@Scheduled(cron = "0 0 3 * * ?")  
public void checkDiff() {  long maxOldId = oldUserRepo.findMaxId();  long maxNewId = newUserRepo.findMaxId();  if (maxOldId != maxNewId) {  log.warn("数据主键最大不一致,旧库{} vs 新库{}", maxOldId, maxNewId);  repairService.fixData();  }  
}

三、用好工具

不同场景需匹配不同的工具链,好比搬家时家具用货车,细软用包裹。

工具选型对照表

工具名称 适用场景 10亿数据速度参考
mysqldump 小型表全量导出 不建议(可能天级)
MySQL Shell InnoDB并行导出 约2-4小时
DataX 多源异构迁移 依赖资源配置
Spark 跨集群大数据量ETL 30分钟-2小时

Spark迁移核心代码片段

val jdbcDF = spark.read  .format("jdbc")  .option("url", "jdbc:mysql://source:3306/db")  .option("dbtable", "users")  .option("partitionColumn", "id")  .option("numPartitions", 100) // 按主键切分100个区  .load()  jdbcDF.write  .format("jdbc")  .option("url", "jdbc:mysql://target:3306/db")  .option("dbtable", "new_users")  .mode(SaveMode.Append)  .save()

避坑经验

  • 分区数量应接近Spark执行器核数,太多反而降低效率
  • 分区字段必须是索引列,防止全表扫

四、影子测试

迁移后的数据一致性验证,好比宇航员出舱前的模拟训练。

影子库验证流程

  1. 生产流量同时写入新&旧双库(影子库)
  2. 对比新旧库数据一致性(抽样与全量结合)
  3. 验证新库查询性能指标(TP99/TP95延迟)

自动化对比脚本示例

def check_row_count(old_conn, new_conn):  old_cnt = old_conn.execute("SELECT COUNT(*) FROM users").scalar()  new_cnt = new_conn.execute("SELECT COUNT(*) FROM new_users").scalar()  assert old_cnt == new_cnt, f"行数不一致: old={old_cnt}, new={new_cnt}"  def check_data_sample(old_conn, new_conn):  sample_ids = old_conn.execute("SELECT id FROM users TABLESAMPLE BERNOULLI(0.1)").fetchall()  for id in sample_ids:  old_row = old_conn.execute(f"SELECT * FROM users WHERE id = {id}").fetchone()  new_row = new_conn.execute(f"SELECT * FROM new_users WHERE id = {id}").fetchone()  assert old_row == new_row, f"数据不一致, id={id}"

五、回滚

即便做好万全准备,也要设想失败场景的回滚方案——迁移如跳伞,备份伞必须备好。

回滚预案关键点

  1. 备份快照:迁移前全量快照(物理备份+ Binlog点位)
  2. 流量回切:准备路由配置秒级切换旧库
  3. 数据标记:新库数据打标,便于清理脏数据

快速回滚脚本

# 恢复旧库数据  
mysql -h旧库 < backup.sql  # 应用Binlog增量  
mysqlbinlog --start-position=154 ./binlog.000001 | mysql -h旧库  # 切换DNS解析  
aws route53 change-resource-record-sets --cli-input-json file://switch_to_old.json

总结

处理10亿数据的核心心法:

  1. 分而治之:拆解问题比解决问题更重要
  2. 逐步递进:通过灰度验证逐步放大流量
  3. 守牢底线:回滚方案必须真实演练过

记住——没有百分百成功的迁移,只有百分百准备的Plan B!

搬运数据如同高空走钢丝,你的安全保障(备份、监控、熔断)就是那根救命绳。🪂

最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。

求一键三连:点赞、转发、在看。

关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/887764.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025.2.21的模拟赛题“糖果”题解

2025.2.21的模拟赛题“糖果”题解为避免混淆,题目中的 \(X\) 在下文中为大写。 称前 \(k-1\) 次操作成为1号操作,第 \(k\) 次(不含)以后的操作称作2号操作 设 \(f_{x,i,j}\) 表示在 \(x\) 的子树中,1号操作做了 \(i\) 次,2号操作做了 \(j\) 次 限制就是\(X\) 到跟的路径不…

【飞书】Zabbix 7.2 告警与飞书机器人深度联动的全流程

midnight, the sound of a phone buzzing wakes you up abruptly. "又是告警!"你猛地从床上坐起,眼睛酸涩地盯着手机屏幕。作为一名运维工程师,这样的场景几乎成了家常便饭。无论是深夜还是清晨,系统故障总能找到你的联系方式,仿佛在提醒你:科技24小时不眠不休…

Windows平台上Idea、Tomcat、浏览器页面显示乱码问题解决

核心:乱码问题是由于字符编码不一致导致的,所以解决乱码问题的核心概念是统一字符编码。首先我们查看各个平台的字符编码: Windows cmd中输入chcp 命令查看(Windows系统默认字符编码时GBK)936 代表 GBK 65001 代表 UTF-8 注意:通过chcp命令如 chcp 65001 来更改字符编码只…

关于 xrlong 是神的论证

xrlong orz搜索内容搜索结果__________________________________________________________________________________________本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18729881

idea插件+cursor使用技巧

cursorignore配置# Compiled files *.class *.jar *.war# Build directories target/ build/# IDE files .idea/ *.iml .vscode/ .project .classpath .settings/# Logs *.log logs/# Temporary files *.tmp *.bak *.swp# Maven specific .mvn/ mvnw mvnw.cmd# Spring Boot spe…

设计测试用例方法 -经验方法(三种)

1、基于经验的测试技术之错误推测法 错误推测法也叫错误猜测法,就是根据经验猜想,已有的缺陷,测试经验和失败数据等可能有什么问题并依此设计测试用例2、基于经验的测试技术之异常分析法 系统异常分析法就是针对系统有可能存在的异常操作、软硬件缺陷引起的故障进行分析,依…

DeepSeek 即将发布 5 个开源项目;Cartesia Voice Changer:声音转换、克隆和实时语音翻译丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 技术 」、「有亮点的 产品 」、「有思考的 文章 」、「有态度的 观点 」、「有看点的 活动 」,但内容仅代表编辑…

Spring复习-注解开发

@Component 基本Bean注解,主要是使用注解的方式替代原有xml的 标签及其标签属性的配置使用@Component 注解替代标签使用:再类上使用 @Component(value = "userDao") //若没有配置value,默认使用类名作为beanName public class UserDaoImpl implements UserDao { }…

测试用例编写技巧

一、用例模板 模板1:模板2:模板3:二、用例的来源 (1)公司就有模板 (2)自己设计模板 (3)用例管理工具种导出模板 三、写用例的核心要素 用例编号、用例标题、前置条件、用例步骤,预期结果、优先级(必填) 系统名称、模块名称、用例创建时间、用例类型、实际结果、执行…

利用deepseek,体验ai写代码

vscode利用cline接入火山引擎deepseek,免费体验ai写代码。注册火山引擎,开通deepseek服务进行火山引擎官网https://www.volcengine.com/,进行注册。进入控制台,访问火山方舟在左侧下拉菜单选择开通管理,开通模型,由于我已经开通过R1模型,以DeepSeek-R1-Distill-Qwen-32B…

测试用例编写

模板1:模板2:模板3:二、用例的来源(1)公司就有模板(2)自己设计模板(3)用例管理工具种导出模板三、写用例的核心要素用例编号、用例标题、前置条件、用例步骤,预期结果、优先级(必填)系统名称、模块名称、用例创建时间、用例类型、实际结果、执行时间(非必填项)四…

TEN 现已接入智谱 GLM-Realtime丨社区来稿

就在上周,三星 Galaxy S25 系列全球首发。基于最新 Galaxy AI 的三星 Galaxy S25 系列手机是三星在全球范围内首次推出具有视频通话功能的原生 AI 智能硬件产品。三星 Galaxy S25 系列背后的智谱最新实时音视频通话 GLM-Realtime 模型,今天已经以插件形式接入 TEN。现在你可以…