我们公司把旧的数据仓库迁移到了新的数据湖架构,整个过程花了三个月,踩了不少坑。

旧系统是传统的数据仓库,用了很多年,性能越来越差,扩展性也不够。新系统是基于数据湖的架构,支持更多的数据类型和更灵活的分析方式。

本文分享完整的迁移实战过程,包括迁移背景、方案设计、数据迁移、应用迁移、验证测试、灰度切换、回滚方案,以及踩过的坑和经验总结。

一、迁移背景

1. 旧系统的问题

旧系统是一个传统的数据仓库,用了五年了。主要问题:

  • 性能差:查询越来越慢,复杂查询要跑几个小时
  • 扩展性差:存储和计算耦合,扩容困难
  • 数据类型有限:只支持结构化数据,不支持半结构化和非结构化数据
  • 成本高:专用硬件,维护成本高
  • 灵活性差:新加字段或改表结构很麻烦
  • 数据孤岛:各个业务系统的数据没有打通

2. 新系统的目标

新的数据湖架构,目标是:

  • 支持结构化、半结构化、非结构化数据
  • 存储和计算分离,弹性扩展
  • 支持多种计算引擎(Spark、Presto、Flink)
  • 支持批处理和流处理
  • 降低成本,用对象存储代替专用存储
  • 数据统一管理,打破数据孤岛

3. 技术选型

新系统的技术栈:

  • 存储:对象存储(S3兼容)
  • 文件格式:Parquet + ORC
  • 计算引擎:Spark 3.0 + Presto
  • 元数据:Hive Metastore + AWS Glue
  • 调度:Airflow
  • 数据质量:Great Expectations
  • 数据目录:DataHub

二、迁移方案设计

1. 迁移原则

迁移的原则:

  • 业务不中断:迁移过程中,旧系统继续运行,不影响业务
  • 数据不丢失:迁移前后数据一致,不能丢数据
  • 可回滚:出问题能快速回滚到旧系统
  • 分批迁移:不要一次性全迁,分批次迁移
  • 充分测试:迁移后充分验证,确保正确

2. 迁移步骤

整体迁移分为几个阶段:

  1. 基础设施搭建:搭建新的数据湖环境
  2. 元数据迁移:迁移表结构、分区、权限等元数据
  3. 历史数据迁移:迁移历史数据
  4. 增量数据同步:实时同步增量数据
  5. 应用迁移:迁移ETL任务、报表、API等应用
  6. 验证测试:数据一致性验证、性能测试、功能测试
  7. 灰度切换:逐步切换流量到新系统
  8. 旧系统下线:确认稳定后,下线旧系统

3. 风险评估

迁移的主要风险:

  • 数据不一致:迁移前后数据不一致
  • 性能不达标:新系统性能不如旧系统
  • 应用不兼容:新系统不支持旧系统的某些功能
  • 业务中断:切换过程中影响业务
  • 回滚失败:出问题无法回滚

针对这些风险,制定了相应的应对措施。

三、基础设施搭建

1. 存储层

  • 搭建对象存储集群(S3兼容)
  • 配置合理的存储策略(标准存储、低频存储、归档存储)
  • 配置数据加密和访问控制
  • 配置数据冗余和备份

2. 计算层

  • 搭建Spark集群,配置合理的资源
  • 搭建Presto集群,用于即席查询
  • 搭建Hive Metastore,管理元数据
  • 搭建Airflow,用于任务调度

3. 网络和安全

  • 配置VPC和安全组,确保网络安全
  • 配置数据传输加密
  • 配置访问控制和审计日志
  • 配置监控和告警

4. 测试环境

  • 搭建独立的测试环境
  • 用生产数据的子集做测试
  • 验证新系统的功能和性能

四、元数据迁移

1. 表结构迁移

  • 导出旧系统的表结构(DDL)
  • 转换为新系统的表结构(数据类型映射、分区策略调整)
  • 在新系统中创建表
  • 验证表结构的一致性

注意: 新旧系统的数据类型可能有差异,需要做映射。比如,旧系统的DECIMAL类型,新系统可能需要调整精度。

2. 分区策略调整

旧系统的分区策略,可能不适合新系统。

  • 旧系统:按天分区,单表有上万个分区
  • 新系统:按天分区,但合并小文件,减少分区数量

分区策略的调整,需要考虑查询模式和数据量。

3. 权限迁移

  • 导出旧系统的用户和权限
  • 在新系统中创建对应的用户和角色
  • 配置表级、列级、行级权限
  • 验证权限的一致性

4. 元数据验证

元数据迁移后,做全面的验证:

  • 表数量一致
  • 字段数量和类型一致
  • 分区策略一致
  • 权限配置一致
  • 注释和描述一致

五、历史数据迁移

1. 全量迁移方案

历史数据的全量迁移,用的是Spark批量迁移:

  • 从旧系统读取数据
  • 转换为Parquet格式
  • 写入新系统的对象存储
  • 按分区组织数据

迁移的并行度,根据数据量和集群资源调整。大表用更多的并行度,小表用较少的并行度。

2. 数据校验

迁移后,做数据校验:

  • 行数一致
  • 字段值一致(抽样比对)
  • 分区数据一致
  • 汇总指标一致(如总数、总和、平均值)

用Great Expectations做自动化数据质量检查,确保数据质量。

3. 大表迁移策略

对于数据量特别大的表(TB级),用分批迁移:

  • 按时间范围分批迁移
  • 每批迁移后做校验
  • 全部迁移完成后,做整体校验

分批迁移可以减少单次迁移的风险,也方便回滚。

4. 小文件合并

迁移过程中,可能产生大量小文件。小文件会影响查询性能。

迁移完成后,用Spark的OPTIMIZE命令合并小文件:

  • 目标文件大小:128MB-256MB
  • 按分区合并
  • 合并后验证数据一致性

六、增量数据同步

1. 同步方案

历史数据迁移完成后,需要同步增量数据,保持新旧系统的数据一致。

增量同步的方案:

  • 基于binlog的实时同步(用Debezium或Canal)
  • 基于时间戳的批量同步(每小时同步一次)
  • 基于消息队列的实时同步(Kafka)

我们用的是混合方案:核心业务用binlog实时同步,非核心业务用批量同步。

2. 同步延迟监控

增量同步的延迟,要实时监控:

  • 同步延迟 < 1分钟:正常
  • 同步延迟 1-5分钟:告警
  • 同步延迟 > 5分钟:紧急处理

监控同步延迟,确保新旧系统的数据差异在可接受范围内。

3. 数据一致性校验

增量同步过程中,定期做数据一致性校验:

  • 每天凌晨,比对新旧系统的数据
  • 比对行数、汇总指标、抽样数据
  • 发现不一致,及时修复

七、应用迁移

1. ETL任务迁移

旧系统有大量的ETL任务,需要迁移到新系统。

  • 梳理所有ETL任务,分类(核心/非核心,批/流)
  • 逐个迁移,从非核心任务开始
  • 迁移后验证输出结果的一致性
  • 优化新系统的ETL任务(利用新系统的特性)

ETL任务的迁移,是整个迁移过程中工作量最大的部分。

2. 报表迁移

旧系统有很多报表,需要迁移到新系统。

  • 梳理所有报表,按使用频率排序
  • 逐个迁移,先迁移高频使用的报表
  • 验证报表数据的一致性
  • 优化报表的查询性能

3. API迁移

对外提供的数据API,需要迁移到新系统。

  • 梳理所有API,评估影响范围
  • 新系统提供兼容的API接口
  • 逐步切换API的后端数据源
  • 确保API的性能和稳定性

4. 用户培训

新系统的使用方式和旧系统不同,需要对用户进行培训。

  • 编写新系统的使用文档
  • 组织培训课程
  • 提供在线支持
  • 收集用户反馈,持续优化

八、验证测试

1. 数据一致性验证

这是最重要的验证。

  • 全量数据比对:行数、字段值、分区数据
  • 汇总指标比对:总数、总和、平均值、最大值、最小值
  • 抽样比对:随机抽取数据,逐字段比对
  • 业务指标比对:核心业务指标的一致性

数据一致性验证,要持续一段时间(至少一周),确保增量同步也一致。

2. 性能测试

新系统的性能,要达到或超过旧系统。

  • 查询性能测试:对比常用查询的响应时间
  • 并发性能测试:模拟多用户并发查询
  • 写入性能测试:对比数据写入的速度
  • ETL任务性能测试:对比ETL任务的运行时间

如果新系统性能不如旧系统,需要优化:

  • 优化数据布局(分区、分桶、排序)
  • 优化查询(谓词下推、列裁剪、Join优化)
  • 优化资源配置(executor数量、内存、CPU)
  • 优化文件格式和压缩

3. 功能测试

新系统的功能,要覆盖旧系统的所有功能。

  • 所有SQL语法的兼容性
  • 所有函数的兼容性
  • 所有ETL任务的功能
  • 所有报表和API的功能
  • 权限和安全功能

发现不兼容的地方,要么修改应用,要么在新系统中做兼容处理。

4. 稳定性测试

新系统要稳定运行,才能切换。

  • 长时间运行测试(72小时以上)
  • 故障恢复测试(节点故障、网络故障)
  • 压力测试(超出正常负载)
  • 监控和告警测试

九、灰度切换

1. 切换策略

验证通过后,开始灰度切换。

切换策略:

  • 先切换非核心业务(如内部报表、分析查询)
  • 再切换次要业务(如部分API、部分ETL)
  • 最后切换核心业务(如核心数据管道、核心API)

每个阶段,观察一段时间,确认稳定后,再进入下一个阶段。

2. 双跑阶段

切换过程中,新旧系统双跑一段时间。

  • 旧系统继续运行,作为备份
  • 新系统处理部分流量
  • 对比新旧系统的输出,确保一致
  • 发现问题,及时回滚

双跑的时间,根据业务的重要性确定。核心业务双跑时间长一些,非核心业务可以短一些。

3. 流量切换

流量切换的方式:

  • 按用户切换:先切换部分用户
  • 按业务切换:先切换部分业务
  • 按比例切换:先切换10%,再50%,最后100%

切换过程中,密切监控:

  • 错误率
  • 响应时间
  • 数据一致性
  • 系统资源使用

4. 回滚方案

切换过程中,如果出问题,要能快速回滚。

回滚方案:

  • 应用层回滚:把流量切回旧系统
  • 数据层回滚:新系统的数据同步回旧系统(如果有数据写入)
  • 元数据回滚:恢复旧系统的元数据

回滚要提前演练,确保切换时能快速执行。

十、旧系统下线

1. 下线条件

旧系统下线,要满足以下条件:

  • 所有业务都切换到新系统
  • 新系统稳定运行至少一个月
  • 没有未解决的重大问题
  • 数据一致性验证通过
  • 回滚方案已经不需要了(或者新系统已经稳定运行足够长时间)

2. 下线步骤

旧系统下线的步骤:

  • 停止旧系统的写入(确保所有写入都到新系统)
  • 最后一次数据同步(确保旧系统的数据都同步到新系统)
  • 停止旧系统的计算任务
  • 备份旧系统的数据和元数据(归档保存)
  • 停止旧系统的服务
  • 释放旧系统的资源

3. 归档

旧系统的数据,要归档保存:

  • 历史数据归档到低成本存储
  • 元数据归档(表结构、权限、配置等)
  • 文档归档(架构文档、运维文档等)
  • 归档保存至少3年(根据合规要求)

十一、踩过的坑

迁移过程中,踩了不少坑。

坑一:数据类型不兼容

旧系统的某些数据类型,新系统不支持,或者精度不同。

比如,旧系统的TIMESTAMP类型,精度到微秒;新系统的TIMESTAMP类型,默认精度到秒。迁移后,时间数据丢失了微秒部分。

解决:

  • 迁移前,仔细对比数据类型
  • 不兼容的类型,做转换或调整
  • 迁移后,验证数据的精度

教训: 数据类型的映射,要仔细,不能想当然。


坑二:分区策略不匹配

旧系统按天分区,新系统也按天分区。但旧系统的分区字段是字符串,新系统的分区字段是日期类型。

迁移后,分区查询的性能很差,因为类型不匹配,无法做分区裁剪。

解决:

  • 统一分区字段的类型
  • 迁移后,验证分区裁剪是否生效
  • 用EXPLAIN查看执行计划

教训: 分区策略和字段类型,直接影响查询性能,要重点验证。


坑三:小文件问题

迁移过程中,产生了大量小文件。新系统的查询性能很差,因为小文件太多,打开文件的开销很大。

解决:

  • 迁移时,合理设置并行度,避免产生小文件
  • 迁移后,用OPTIMIZE合并小文件
  • 配置自动合并小文件的机制
  • 监控小文件数量,及时处理

教训: 小文件是数据湖的常见问题,要从迁移开始就注意。


坑四:增量同步延迟

增量同步的延迟,有时候会突然变大。

原因是,业务高峰期,数据写入量大,同步跟不上。

解决:

  • 增加同步任务的资源
  • 优化同步程序的性能
  • 高峰期前,提前扩容
  • 监控同步延迟,及时告警

教训: 增量同步的性能,要留有余量,应对业务高峰。


坑五:应用不兼容

有些旧系统的SQL,用了新系统不支持的语法或函数。

迁移后,这些SQL报错,ETL任务失败。

解决:

  • 迁移前,扫描所有SQL,找出不兼容的部分
  • 不兼容的SQL,改写为新系统支持的语法
  • 对新系统不支持的函数,自定义UDF
  • 建立兼容性测试,提前发现问题

教训: 应用迁移前,要做兼容性扫描,不要等迁移了才发现问题。


坑六:性能不达标

新系统的某些查询,性能不如旧系统。

原因是,新系统的优化器和旧系统不同,执行计划不一样。

解决:

  • 分析慢查询,找出性能瓶颈
  • 优化数据布局(分区、分桶、排序)
  • 优化SQL(谓词下推、列裁剪、Join顺序)
  • 调整优化器参数
  • 必要时,用Hint强制执行计划

教训: 新系统不一定比旧系统快,要做充分的性能测试和优化。


坑七:回滚复杂

切换过程中,有一次出了问题,需要回滚。但回滚比预想的复杂,因为新系统已经有数据写入了,要把这些数据同步回旧系统。

解决:

  • 提前设计回滚方案,包括数据回滚
  • 回滚方案要提前演练
  • 切换时,尽量避免新系统有数据写入(或者有双向同步)
  • 回滚后,验证数据一致性

教训: 回滚方案要考虑周全,不能只停留在纸面上。

十二、经验总结

1. 充分准备

迁移前,要做充分的准备:

  • 梳理所有数据和应用
  • 评估风险,制定应对方案
  • 搭建测试环境,充分验证
  • 培训团队,熟悉新系统

准备越充分,迁移越顺利。

2. 分批迁移

不要一次性全量迁移,要分批:

  • 先迁移非核心业务
  • 再迁移核心业务
  • 每批迁移后,充分验证
  • 确认稳定后,再迁移下一批

分批迁移,可以降低风险,也方便回滚。

3. 数据一致性是关键

迁移过程中,数据一致性是最重要的。

  • 迁移前,记录数据基线
  • 迁移后,全面比对数据
  • 增量同步过程中,持续校验
  • 切换后,继续验证一段时间

数据不一致,是迁移最大的风险。

4. 性能优化要提前

不要等迁移完了才优化性能,要在迁移过程中就优化。

  • 合理设计分区和分桶
  • 选择合适的文件格式和压缩
  • 合并小文件
  • 优化SQL和资源配置

性能优化,是迁移过程中的持续工作。

5. 回滚方案要到位

迁移不可能100%成功,要有回滚方案。

  • 设计详细的回滚步骤
  • 回滚方案要提前演练
  • 切换时,密切监控,发现问题及时回滚
  • 回滚后,分析原因,解决问题后再切换

有回滚方案,心里才不慌。

6. 沟通很重要

迁移涉及很多团队,沟通很重要。

  • 提前通知业务方,告知迁移计划和影响
  • 迁移过程中,及时同步进度
  • 出问题时,及时沟通,协调资源
  • 迁移完成后,总结反馈

良好的沟通,能减少很多误解和冲突。

十三、写在最后

这次数据湖迁移,前后花了三个月时间。虽然过程中踩了不少坑,但最终顺利完成了。

迁移完成后,新系统的优势逐渐显现:

  • 查询性能提升了3-5倍
  • 存储成本降低了60%
  • 支持了更多的数据类型
  • 扩展性大大增强
  • 数据分析更灵活

数据湖迁移,是一个系统工程,涉及数据、应用、人员、流程等方方面面。要做好充分的准备,制定详细的计划,分批迁移,充分验证,才能顺利完成。

2022年了,越来越多的企业在建设数据湖,从传统数据仓库迁移到数据湖架构。这是一个趋势,但也是一个挑战。希望我们的经验,能帮正在做数据湖迁移的你,少走一些弯路。

最后,用一句话总结:"数据湖迁移,充分准备,分批迁移,数据一致,性能达标,回滚到位,沟通顺畅。做好这几点,迁移就能成功。"

愿你的数据湖迁移,一帆风顺。