100万,一亿,10亿表数据,如何实现高效迁移?如何做平滑的数据迁移?

面试题

3 个回答

  • 普瑞姆
    重新审视自己,什么使你快乐,什么就是眼下最珍贵。
    数据迁移是指将数据从一个数据源迁移到另一个数据源。为实现平滑的数据迁移,需要满足 **业务无感知** 的要求,即迁移过程中不影响业务功能。这要求我们对存量数据、增量数据、迁移流程、核对和灰度切流等关键环节做好设计。 ## **迁移前的准备** ### **1. 明确迁移目的** - **分库分表**:优化数据存储结构。 - **替换数据库**:更换数据库类型(如 MySQL 替换为 PostgreSQL)。 - **技术架构变更**:如微服务化引起的数据存储调整。 - **数据归档**:清理历史数据,减轻主库压力。 ### **2. 数据评估** - **数据量级**:几十万、几百万、还是亿级?数据量影响迁移方案的复杂度。 - **存量与增量**: - 存量数据:原有库中已有的数据。 - 增量数据:迁移开始后产生的新数据(包括 `INSERT`、`UPDATE`、`DELETE`)。 - **实时性要求**:是否需要在迁移期间实时同步数据。 ### **3. 是否需要平滑迁移** - 如果可以停机迁移(如非高可用场景),可以直接迁移。 - 若必须业务无感,则需要平滑迁移方案。 ## **迁移流程设计** ### **1. 存量数据迁移** #### **特点** - 存量数据迁移是一次性的,涉及数据完整性、性能优化、断点续传等问题。 #### **步骤** 1. **迁移方式**: - **工具迁移**:如使用 DataX、Kettle 等工具,减少开发工作量。 - **自定义迁移**:自己写脚本或任务,针对性更强。 2. **断点续传**: - 给旧表新增一个标识字段(如 `migrated`),标记记录是否迁移成功。 - 每次迁移只处理 `migrated = false` 的记录,避免重复迁移。 3. **避免覆盖增量数据**: - 在迁移前检查新表中是否已存在记录,已存在则跳过迁移。 4. **性能优化**: - 分批次迁移:每次迁移一定范围内的数据(如按 ID 或时间段分批)。 - 并行任务:使用多线程或分布式任务调度框架(如 Spring Batch、XXL-JOB)。 ### **2. 增量数据同步** #### **特点** - 迁移开始后产生的增量数据需要实时同步到新库,确保数据一致性。 - 关键在于如何实现 **双写** 和 **数据核对**。 #### **双写方案** 1. **工具同步**: - 使用 **Canal** 或 **Flink CDC** 监听 Binlog 日志,自动将增量写入新库。 - 优点:无需编码,支持异构数据库。 - 缺点:延迟和失败风险,需配置重试机制。 2. **代码实现**: - 在代码中实现双写逻辑: ```java writeOldDB(data); writeNewDB(data); ``` - 优点:控制力强,可定制化逻辑。 - 缺点:开发复杂度高。 3. **异步双写**: - 使用消息队列(如 Kafka 或 RabbitMQ)将写入任务异步发送到新库,削峰填谷。 #### **增量数据核对** - **旁路验证**: - 读取旧库数据时,异步读取新库数据进行比对,发现不一致时报警。 - **更新和删除逻辑**: - 判断数据是否已迁移: - 若是增量数据,则更新新库。 - 若是存量数据,则更新旧库即可。 ### **3. 数据核对** 数据核对是确保迁移成功的关键,分为以下几类: 1. **存量数据核对**:逐条比对新旧库中的所有记录。 2. **增量数据核对**:比对双写或同步过程中是否有遗漏。 3. **核对工具**: - 使用 SQL 脚本、Diff 工具,或自写对比任务。 - 在旁路验证中实时比对。 ### **4. 灰度切流** #### **目的** 逐步将业务请求切换到新库,降低风险。一旦发现问题,可以快速回滚到旧库。 #### **步骤** 1. **切流读新**: - 优先将读请求切换到新库,确保新库的数据完整性和稳定性。 - 使用灰度策略逐步切流: - 按用户 ID 尾号划分用户(如 10%、30%、50%)。 - 从小比例逐步增加,直到所有请求都读新库。 - 灰度期间,旁路验证切换到比对旧库数据。 2. **切流写新**: - 等读新完全稳定后,再将写操作切到新库。 - 切流写新是不可回滚的步骤,需谨慎验证。 ### **5. 回滚机制** - **双写阶段回滚**: - 写新失败时回滚到旧库(双写第一阶段)。 - 写旧失败时回滚到新库(双写第二阶段)。 - **切流阶段回滚**: - 切流读新:读操作切回旧库。 - 切流写新:切流前确保新库数据完整性,一旦切流写新完成无法回滚。 ## **工具选择** - **存量数据迁移**: - **DataX**:支持多种异构数据源的批量同步。 - **Kettle**:开源 ETL 工具,灵活且易于操作。 - **增量数据同步**: - **Canal**:基于 Binlog 日志解析,实现增量同步。 - **Flink CDC**:实时捕获数据变更,适合实时数据管道。 - **自定义代码**: - 使用 Java、Python 等语言,结合线程池、批量操作、分布式调度等。 ## **完整流程图** ```mermaid graph TD A[读旧写旧] --> B[增量双写] B --> C[存量数据迁移] C --> D[存量数据核对] D --> E[切流读新] E --> F[切流写新] F --> G[迁移完成] ``` ## **总结** 平滑数据迁移的核心在于 **数据完整性、实时性和灰度切流**。关键点: 1. **存量数据迁移**:分批迁移、断点续传,确保不覆盖增量数据。 2. **增量数据同步**:通过工具或代码实现双写,旁路验证保证一致性。 3. **数据核对**:使用工具或脚本比对数据,确保新旧库一致。 4. **灰度切流**:逐步切流读新、写新,降低迁移风险。 5. **回滚机制**:支持在双写阶段回滚,切流前彻底验证数据。 通过完整的设计和工具支持,结合严密的监控和核对,可以实现真正的平滑迁移。
    发布于 2024-11-07 12:17 •IP属地 甘肃
    举报
    评论
    收藏

  • ketty
    不必太张扬,是花自然香。
    多线程,通过hash算法,找对应的数据,分页查询,批量插入
    发布于 2022-12-23 16:19 •IP属地 云南
    举报
    评论
    收藏

  • 小王子-B765
    时间不在乎你拥有多少,而在于你怎样使用。
    1. 首先要区分是增量数据还是存量数据。 2. 如果只需要迁移存量数据,那么找数仓的同事,让他们用dts等工具,直接监听binlog进行同步。 3. 如果是增量数据的同步,那么就复杂很多,因为在你同步增量数据的时候,又会有新的增量数据到来,并且,如果有更新操作,由于旧数据还没有同步到新库,所以更新操作会失败。 4. 最佳实践一般就是,通过cannel监听旧库的binlog,然后插入到新库,如果更新操作失败,则将失败的数据放到rocketmq的延时队列中,等待10分钟再更新,如此可以确保对插入先于更新执行。等到新旧库的数据一致且稳定运行一段时间后,就将读取与更新操作转移到新库,然后下线旧库,清理数据。 5. binlog都是已经提交的数据,所以不必担心监听到了的数据又回滚,造成新旧库数据不一致的问题。
    编辑于 2024-07-29 18:09 •IP属地 陕西
    举报
    评论
    收藏