1. 初识大数据平台:从一堆散装工具到一站式工作台
刚接触数据平台那会儿,我的日常是这样的:凌晨两点被报警电话叫醒,因为某个报表任务跑挂了;早上九点开会,业务方问“昨天的GMV怎么和后台对不上”;下午写SQL写到一半,发现上游表结构又变了。那时候团队里流传一句话——“数据开发不是在修数据,就是在去修数据的路上”。
后来有机会深度体验了一套企业级大数据平台,才真正理解“一站式”三个字的分量。它把数据仓库、调度系统、数据质量、离线计算、实时计算这些原本各自为政的能力,收拢到一个统一的界面里。你不用再在五六个系统之间来回切换,不用手动维护crontab,不用写脚本去校验数据对不对。对于中小团队来说,这种平台能直接把数据链路的搭建成本砍掉一大半;对于个人开发者,它也是理解现代数据栈运作方式的最佳样本。
这篇文章我会从实际使用的角度,把这套平台的几个核心模块拆开讲清楚:它到底解决了什么问题、内部大概是怎么运转的、上手时要注意哪些坑。不管你是刚入行的数据开发,还是想给团队选型的技术负责人,应该都能从中拿到一些可以直接参考的东西。
2. 数据仓库:不只是存数据的地方
2.1 分层设计背后的现实考量
很多人第一次接触数据仓库,会觉得不就是建几张表嘛。但真正用起来才发现,分层设计才是决定后期维护成本的关键。这套平台默认推荐的是经典的四层结构:ODS(贴源层)、DWD(明细层)、DWS(汇总层)、ADS(应用层)。
为什么要分这么细?我举个实际例子。之前有个项目,业务方要查“每个省份昨天的新增用户数”。如果直接从原始日志表查,需要解析JSON、过滤无效记录、关联用户维度表,一条SQL跑下来十几分钟。但如果在DWD层已经把日志清洗成标准明细,DWS层按天按省预聚合,ADS层直接出结果,查询就是秒级的事。
注意:分层不是越多越好。我见过有的团队分了七层,结果数据血缘复杂到没人能理清。四层对于大多数场景已经够用,关键是每层的职责要清晰。
平台在建模时提供了可视化配置,你可以直接拖拽字段、设置分区键。这里有个细节值得说:分区字段的选择直接影响查询性能。比如按天分区的表,如果查询条件里没有日期范围,就会全表扫描。我一般会强制要求所有DWD以上的表都必须带时间分区,并且在平台里设置“查询必须带分区过滤”的规则,从源头避免误操作。
2.2 维度建模的实操要点
维度建模听起来很理论,但落到操作上其实就是几件事:确定业务过程、选择粒度、识别维度、确定事实。平台里内置了维度表和事实表的模板,新建表的时候可以直接选。
我踩过的一个坑是缓慢变化维的处理。比如用户等级会变,如果直接覆盖,历史订单关联到的就是当前等级,分析会失真。平台支持拉链表,但配置起来需要指定生效时间、失效时间、是否当前记录这几个字段。我的经验是:只对真正需要追溯历史的维度做拉链,否则存储和ETL复杂度都会飙升。
另一个实用功能是数据地图。它能自动解析SQL里的表依赖关系,生成血缘图。有一次上游表要下线,我通过血缘图快速定位到下游有二十多个任务在依赖它,提前做了迁移,避免了一次大面积故障。这个功能建议每个团队都强制开启。
3. 调度系统:让任务按时按序跑起来
3.1 DAG编排的核心逻辑
调度系统的本质是有向无环图的执行引擎。每个任务是一个节点,依赖关系是边。平台里你可以通过拖拽或者配置依赖的方式,把任务串起来。
这里的关键是依赖的粒度。我见过有人把整个数仓的所有任务串成一条长链,结果一个任务延迟,后面全堵住。合理的做法是按业务域拆分,比如订单域、用户域、流量域各自成链,域之间只在关键节点做跨链依赖。
平台支持几种触发方式:定时触发、依赖触发、事件触发。定时触发适合每天固定时间跑的报表;依赖触发适合上游表就绪后才执行的任务;事件触发则用于实时性要求高的场景,比如收到消息队列的消息就启动。
提示:任务的重试策略一定要配。我一般设置失败重试3次,间隔5分钟。但要注意,如果任务本身不是幂等的,重试会导致数据重复。所以写任务时尽量保证“重跑不影响结果”,比如用
INSERT OVERWRITE而不是INSERT INTO。
3.2 补数与回溯的实战技巧
数据开发最怕的就是“昨天的数据算错了,需要重跑”。平台提供了补数功能,可以指定时间范围批量重跑任务。但这里有几个坑:
第一,补数时的并发控制。如果一次性补30天,所有任务同时启动,可能会把集群资源打满。我一般会设置并发度,比如同时只跑3天的量。
第二,下游依赖的处理。补跑上游表后,下游表不会自动更新,需要手动触发或者配置级联补数。平台里有“补数影响分析”功能,能列出所有受影响的下游任务,这个一定要看,否则容易出现数据不一致。
第三,补数的时间窗口。有些任务依赖外部数据源,比如第三方接口,补数时可能接口已经不支持历史数据了。这种情况只能手动处理,或者提前把外部数据落地到ODS层。
我整理了一个补数检查清单,每次操作前过一遍:
| 检查项 | 说明 |
|---|---|
| 补数范围 | 确认起止日期,避免多补或漏补 |
| 并发设置 | 根据集群负载调整,一般不超过5 |
| 下游影响 | 查看血缘图,确认需要级联补数的任务 |
| 幂等性 | 确认任务重跑不会产生重复数据 |
| 资源预留 | 提前和集群管理员沟通,避免影响正常任务 |
4. 数据质量:从“事后救火”到“事前拦截”
4.1 质量规则的配置方法
数据质量模块是我觉得最被低估的功能。很多团队等到业务方投诉了才去查数据,但这时候损失已经造成了。平台支持在任务执行前后自动跑质量检查,不通过就阻断下游。
常见的质量规则有几类:
- 非空检查:关键字段不能有NULL,比如订单ID、用户ID
- 唯一性检查:主键不能重复
- 值域检查:比如订单金额不能为负数
- 波动率检查:今天的数据量和昨天比,波动超过阈值就告警
- 自定义SQL:写一段SQL,返回不为空就说明有问题
我一般会在ODS层做基础检查(非空、格式),在DWD层做业务检查(值域、唯一性),在ADS层做波动检查。这样层层过滤,问题能尽早发现。
注意:质量规则的阈值不要设得太死。比如波动率,如果业务本身有周期性,周末和工作日的量本来就不一样,一刀切设10%会导致大量误报。我的做法是按周同比,或者用移动平均来动态计算阈值。
4.2 告警与处理流程
质量检查不通过后,平台会触发告警。告警渠道可以配邮件、短信、企业通讯工具。但告警太多人会麻木,所以要做分级:
- P0:核心报表数据异常,立即电话通知
- P1:重要表数据异常,通讯工具告警,30分钟内响应
- P2:一般表数据异常,邮件通知,当天处理
处理流程也很关键。我建议每个告警都要有处理记录:谁处理的、什么原因、怎么解决的。平台里有工单功能,可以关联到具体的质量事件。积累一段时间后,你会发现很多问题是重复出现的,这时候就可以针对性优化。
5. 离线计算与实时计算:两条腿走路
5.1 离线计算的优化经验
离线计算主要跑批处理任务,平台底层用的是分布式计算引擎。对于数据开发来说,最常打交道的就是SQL。同样一个逻辑,不同的写法性能可能差几十倍。
我总结了几条SQL优化经验:
第一,尽早过滤。能在子查询里过滤的,不要留到外层。比如SELECT * FROM (SELECT * FROM t WHERE dt='2024-01-01') WHERE status=1,不如直接SELECT * FROM t WHERE dt='2024-01-01' AND status=1。
第二,小表驱动大表。JOIN的时候,把数据量小的表放在前面。如果小表足够小,还可以用MapJoin,平台会自动优化,但你要确保小表真的小。
第三,避免数据倾斜。如果某个key的数据量特别大,会导致单个任务卡住。常见的处理方法是加盐,把key打散。比如用户ID是热点,可以拼接随机数,先局部聚合再全局聚合。
第四,合理设置并行度。并行度太低跑得慢,太高则调度开销大。一般根据数据量来定,比如1GB数据配10个并行度左右。平台有自动推荐功能,但最好自己压测一下。
5.2 实时计算的场景与选型
实时计算主要处理流式数据,比如实时监控、实时风控、实时推荐。平台支持SQL化的流计算,不用写Java代码,对数据开发很友好。
但实时计算不是万能的。我见过有的团队为了“实时”而实时,把本来可以T+1的报表改成实时,结果复杂度翻倍,收益却很小。我的判断标准是:如果延迟一小时对业务没有实质影响,就不要做实时。
真正需要实时的场景通常有几个特征:数据价值随时间快速衰减(比如风控)、需要即时交互(比如用户行为触发推荐)、或者业务方明确要求秒级可见。
实时任务的开发有几个注意点:
- 状态管理:流计算是有状态的,比如计算累计UV,需要保存状态。状态太大会导致性能下降,要定期清理或设置TTL。
- 乱序处理:数据到达顺序可能和产生顺序不一致,需要用事件时间加水印来处理。
- Exactly-Once语义:确保每条数据只处理一次,这需要源端和目标端都支持。平台提供了配置选项,但要根据具体数据源来确认。
6. 常见问题与排查技巧实录
6.1 任务失败排查速查表
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 任务一直等待 | 上游未完成 | 查看依赖图,确认上游状态 |
| 任务运行超时 | 数据量突增或SQL低效 | 查看执行计划,检查数据量变化 |
| 内存溢出 | 并行度过高或数据倾斜 | 调整并行度,检查key分布 |
| 数据重复 | 任务重跑且非幂等 | 检查写入方式,改用OVERWRITE |
| 数据缺失 | 过滤条件过严或上游延迟 | 对比上下游数据量,检查过滤逻辑 |
| 质量检查失败 | 数据异常或规则过严 | 查看具体失败规则,抽样检查数据 |
6.2 几个容易忽略的细节
时区问题。平台默认可能是UTC,但业务数据往往是北京时间。如果没注意,会导致分区日期错位。我一般会在任务开头显式设置时区,比如SET timezone='Asia/Shanghai'。
空值处理。SQL里NULL和空字符串是两回事。WHERE field != 'abc'会过滤掉NULL的行,因为NULL和任何值比较都是NULL。要用WHERE field != 'abc' OR field IS NULL。
资源队列。大任务和小任务要分开队列,避免小任务被大任务堵住。平台支持队列配置,可以按业务域或者优先级划分。
版本管理。任务的SQL变更一定要有版本记录,出问题可以快速回滚。平台自带版本管理,但很多人不用,改完直接发布,出了问题只能凭记忆恢复。
7. 一些个人体会
用这套平台一年多,最大的感受是:工具能解决效率问题,但解决不了设计问题。平台提供了很好的基础设施,但数仓怎么分层、任务怎么拆分、质量规则怎么定,这些还是依赖人的判断。
我见过把平台用得很好的团队,也见过用得很糟的。区别往往不在技术能力,而在规范意识。比如命名规范,表名要能看出业务域、分层、更新频率;比如注释,每个字段都要写清楚含义;比如文档,每个任务都要说明目的和负责人。这些看起来是小事,但决定了平台能不能长期健康运转。
另外,不要追求一步到位。刚开始可以只用一个模块,比如先把调度用起来,把散落的脚本管起来。等团队习惯了,再逐步引入数据质量和实时计算。平台本身是渐进式的,没必要一次性把所有功能都堆上去。
最后分享一个实用技巧:平台里有个“任务模板”功能,可以把常用的SQL模式保存下来,比如拉链表更新、增量合并、维度关联。新任务直接套模板,既快又不容易出错。我把自己常用的十几个模板整理成了一个库,团队新人来了直接参考,上手速度能快很多。