面试官问'你做过数据迁移吗'——迁移项目是最好的面试素材
先说结论
迁移项目面试时要讲三件事:为什么要迁移(动机)、怎么迁移不出问题(方案)、迁移后效果怎么样(结果)。动机要和业务痛点挂钩,方案要讲灰度策略和回滚预案,结果要有性能和成本的数字对比。
迁移的核心难点不是'搬数据',而是'保证不出错'。面试官最看重你怎么保证数据一致性、怎么做灰度验证、怎么应对SQL兼容性问题。这些才是真正体现工程能力的地方。
即使你没做过整个迁移,参与过其中一个环节也可以讲。比如你负责了SQL改写、或者负责了数据对账、或者负责了性能调优。面试时说清楚你具体负责的部分就行。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
数据迁移是大数据工程师最容易出彩的项目经验。为什么?因为迁移项目天然就有'挑战+方案+结果'的完整故事弧——有技术难点(SQL兼容性、数据一致性)、有工程难度(不停服切换、灰度方案)、有量化结果(性能提升、成本降低)。我做过EMR到Databricks的全链路迁移,这个项目基本上成了我面试的'王牌项目'。今天把迁移项目的讲法和关键技术点都分享出来。
迁移的完整流程:七个阶段
| 阶段 | 关键任务 | 耗时(我的经验) | 风险点 |
|---|---|---|---|
| ① 评估调研 | 对比候选平台、评估迁移成本和收益 | 2周 | 选错平台,后面全白费 |
| ② 方案设计 | 设计灰度方案、制定SQL改写规则、设计对账方案 | 1周 | 方案设计不周全导致反复返工 |
| ③ 环境搭建 | 搭建新平台、配置网络和权限、部署监控 | 1周 | 环境差异导致后面的问题 |
| ④ SQL改写 | 处理SQL方言差异、函数替换、语法适配 | 2周 | 遗漏某些特殊SQL导致数据错误 |
| ⑤ 灰度验证 | 新老两套并行跑,对比结果一致性 | 2-3周 | 对账不充分,遗漏数据差异 |
| ⑥ 正式切换 | 流量从老平台切到新平台 | 1天 | 切换后发现问题需要紧急回滚 |
| ⑦ 收尾清理 | 下线老平台、清理资源、输出文档 | 1周 | 过早下线老平台导致无法回滚 |
整个迁移我花了大约8周。其中最关键的是④SQL改写和⑤灰度验证,这两个阶段占了总时间的60%。
SQL方言差异:迁移中最繁琐的部分
从EMR(标准Spark SQL)迁移到Databricks,虽然都是Spark生态,但还是有不少SQL差异。我统计过,100+个Spark作业中有20%需要修改SQL。主要的差异包括:
-- 常见的SQL方言差异和改写
-- ① 日期函数差异
-- EMR写法
SELECT date_format(dt, 'yyyyMMdd') FROM orders;
-- Databricks更推荐用date_format配合标准格式
SELECT date_format(dt, 'yyyy-MM-dd') FROM orders;
-- ② 类型转换差异
-- EMR允许隐式转换
SELECT * FROM orders WHERE order_id = '123'; -- order_id是INT
-- Databricks严格模式下会报错,需要显式转换
SELECT * FROM orders WHERE order_id = CAST('123' AS INT);
-- ③ NULL处理差异
-- 某些函数对NULL的处理逻辑不同
-- EMR: CONCAT('a', NULL) = 'a'
-- Databricks: CONCAT('a', NULL) = NULL (严格模式)
-- 修复:显式处理NULL
SELECT CONCAT('a', COALESCE(col1, '')) FROM table1;
我当时整理了一份SQL改写对照表,按差异类型分类(日期函数、类型转换、NULL处理、窗口函数),给团队成员参考。这份文档后来成了团队的标准改写手册,新人加入也能快速上手。
灰度方案:双写双读怎么做
灰度方案是迁移中最体现工程能力的环节。我设计的灰度策略是'双写双读'——新老两套同时跑相同的ETL逻辑,然后对比输出结果。
// 双写双读灰度方案
// 第1阶段:双写(2周)
// 老平台(EMR)正常执行ETL,产出报表数据
// 新平台(Databricks)跑相同的ETL,产出到独立的验证库
// 下游报表仍然从老平台取数——新平台只跑不用
// 第2阶段:对账验证(每天自动跑)
// 自动对比新老两套的核心指标:
// - 每张表的记录数
// - 核心字段的SUM/COUNT DISTINCT
// - 关键报表的最终数字
// 差异超过0.01%就告警
// 第3阶段:切流(1天)
// 连续2周对账通过后,把下游报表切到新平台
// 老平台保留1周作为回滚保障
// 第4阶段:下线老平台(1周后)
// 确认一切正常后,停掉老平台的ETL作业
// 保留老平台数据30天,以备万一
数据对账:怎么确保不丢数据
对账是灰度验证的核心。我写了一套自动化对账脚本,每天凌晨ETL完成后自动执行:
-- 对账脚本示例:对比新老平台的核心指标
-- 检查1:记录数对比
SELECT
'dwd_device_activation' AS table_name,
(SELECT COUNT(*) FROM emr_db.dwd_device_activation
WHERE dt = '${bizdate}') AS old_count,
(SELECT COUNT(*) FROM databricks_db.dwd_device_activation
WHERE dt = '${bizdate}') AS new_count,
ABS(old_count - new_count) AS diff;
-- 检查2:核心字段SUM对比
SELECT
(SELECT SUM(amount) FROM emr_db.dws_order_daily
WHERE dt = '${bizdate}') AS old_sum,
(SELECT SUM(amount) FROM databricks_db.dws_order_daily
WHERE dt = '${bizdate}') AS new_sum;
-- 检查3:去重数对比
SELECT
(SELECT COUNT(DISTINCT user_id) FROM emr_db.dws_user_daily
WHERE dt = '${bizdate}') AS old_uv,
(SELECT COUNT(DISTINCT user_id) FROM databricks_db.dws_user_daily
WHERE dt = '${bizdate}') AS new_uv;
对账脚本覆盖了所有核心表的三个维度:记录数、求和、去重数。连续14天全部通过后才允许切流。实际跑下来,前5天发现了3个SQL改写遗漏导致的数据差异,修复后后面9天全部通过。
迁移中的分批策略
100+个Spark作业不能一次全迁移。我按作业的依赖关系分了三批:
| 批次 | 作业类型 | 数量 | 策略 |
|---|---|---|---|
| 第1批 | 独立作业(无下游依赖或依赖简单) | 约40个 | 先迁简单的,验证流程可行性 |
| 第2批 | 核心链路(设备激活、订单、用户) | 约35个 | 最关键,对账最严格,双跑时间最长 |
| 第3批 | 边缘作业(临时报表、历史分析) | 约30个 | 最后迁,出问题影响最小 |
分批的核心原则是:风险从低到高。先迁影响小的,积累经验和信心;核心链路放中间,验证最充分;边缘作业放最后。每批迁移后都要做完整的对账验证,确认无误后再迁下一批。
面试高频追问
追问一:迁移过程中遇到最棘手的问题是什么?
我遇到的最棘手的问题是一个隐蔽的数据精度差异。有一个计算广告ROI的SQL,涉及除法运算。在EMR上用的是DOUBLE类型的除法,在Databricks上同样的SQL用的是DECIMAL类型的除法(严格模式下的默认行为)。两者的精度不同,导致ROI数字在小数点后第4位有差异。对账脚本设的阈值是0.01%,这个差异刚好在阈值边缘,时有时无。后来我调整了SQL,显式指定了CAST(... AS DOUBLE)来统一精度,问题就解决了。
追问二:如果迁移后发现有数据丢失怎么办?
这是考你的应急预案。我的回滚方案分三级:第一级,如果是单个作业出问题,把这个作业的数据源切回老平台,重跑一次就行。第二级,如果是整个链路出问题,启动老平台的全量ETL,从ODS重新跑一遍。第三级,如果新平台完全不可用,把下游报表的数据源全部切回老平台。因为老平台在切流后保留了一周,所以这三级回滚都是可行的。实际上我们只用过第一级——有一个作业因为时区函数差异导致某天的数据偏差,回滚到老平台重跑后修复了SQL再切回来。
追问三:迁移的ROI怎么衡量?怎么说服老板投入资源做迁移?
这考的是你的商业思维。我当时给老板算了一笔账:EMR每月的运维成本(包含集群费用+运维人力折算)是X万,迁移到Databricks后每月费用是0.8X万。加上性能提升40%后可以用更小的集群,实际每月节省35%。迁移投入大约2个月的人力成本,4个月就能回本。另外还有'软收益'——ETL稳定性提升(故障从月均2次降到0次)、开发效率提升(Delta Lake的MERGE INTO减少了大量重复代码)。把硬成本和软收益都算清楚,老板自然会支持。
实战踩坑
迁移过程中我犯过一个低级但严重的错误。在第2批核心作业迁移时,有一个作业的SQL里用了EMR特有的UDF(自定义函数),但Databricks上没有注册这个UDF。作业跑的时候直接报错了。
问题不在于报错——报错很好排查。问题在于这个报错是在凌晨3点自动跑的,告警通知发到了钉钉群但没有人看。第二天早上业务方发现报表没出数,7:30就开始追问了。
// 踩坑:UDF缺失 + 告警无人响应
// 根因:SQL中用了自定义UDF ip_to_country()
// 这个UDF在EMR上注册了,但忘记在Databricks上注册
// 为什么没提前发现:
// 我在SQL改写阶段只关注了'语法差异',
// 没有系统性地扫描所有SQL中的UDF依赖
// 修复:
// 1. 立即在Databricks上注册了这个UDF
// 2. 写了一个脚本扫描所有SQL,列出所有UDF引用
// 3. 逐个确认UDF在新平台上是否可用
// 告警改进:
// 核心链路的告警升级为电话通知,不只是钉钉消息
// 设置了值班制度,凌晨的告警必须有人响应
教训:迁移前要做'全量依赖扫描'——不只是SQL语法,还包括UDF、外部表引用、权限配置等。另外,迁移期间的监控和告警要比日常更严格,核心链路的告警必须有人实时响应。
总结
迁移项目是面试的优质素材,因为它天然包含'挑战+方案+结果'。讲迁移重点讲三件事:灰度方案(双写双读+自动对账)、SQL改写(方言差异处理)、分批策略(风险从低到高)。数字上准备好迁移前后的性能对比和成本对比。最关键的是讲清楚你怎么保证'不丢数据'——对账脚本的设计和执行是面试官最关心的技术细节。
下一篇聊项目经验的最后一个高频题:面试官问'你踩过最大的坑是什么'——怎么把踩坑讲成加分项?
你做过数据迁移吗?过程中遇到过什么意外?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长