第27章:ETL监控与运维:日志管理、告警机制、性能监控、故障恢复、版本管理
说实话,很多做ETL的朋友,前期开发时风生水起,一到上线运维就抓瞎。我见过太多案例——凌晨三点被电话叫醒,说数据没跑出来,结果连日志在哪都找不到。嗯,这章咱们就把运维这块硬骨头啃下来。
27.1 日志管理:你的第一道防线
日志这东西,平时没人看,出事了就是救命稻草。我个人习惯把日志分成三个层级:
- 运行日志:记录每一步的执行状态、开始时间、结束时间、处理行数
- 错误日志:记录异常堆栈、错误码、失败原因、重试次数
- 审计日志:记录谁在什么时间改了什么配置、做了什么操作
核心原则:日志要结构化,别写散文。每行日志都应该是机器可解析的JSON格式。
我在项目中遇到过最坑的事——日志文件把磁盘撑爆了。所以一定要配日志轮转策略:
# log4j配置示例
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.MaxFileSize=100MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.File=/data/logs/etl_job.log
避坑指南:我曾经因为日志级别设成DEBUG,结果一个批处理任务跑了6小时。生产环境请用INFO级别,排查问题时再临时调成DEBUG。
27.2 告警机制:别等用户发现你挂了
告警不是越多越好。你想想看,如果每天收到100条告警,最后你肯定全忽略了。我建议按严重程度分三级:
| 级别 | 触发条件 | 响应方式 |
|---|---|---|
| P0(致命) | 任务失败、数据延迟超过SLA | 电话+短信+邮件,5分钟内响应 |
| P1(严重) | 数据质量异常、资源使用率超80% | 短信+邮件,15分钟内响应 |
| P2(警告) | 重试次数超过阈值、慢查询 | 邮件,次日处理 |
说白了,告警要能区分「系统要挂了」和「系统还能撑一会儿」。我习惯在ETL任务里埋几个关键检查点:
- 源端数据量波动超过±20%时告警
- 目标表写入速度低于历史均值50%时告警
- 连续3次重试失败时升级为P0
注意:别把告警发到个人微信。万一那个人休假了呢?一定要发到团队群组,并设置值班轮转。
27.3 性能监控:找到瓶颈在哪
性能监控不是看CPU用了多少就完事了。ETL的瓶颈通常不在计算,而在I/O和网络。我常用的监控指标:
- 吞吐量:每秒处理多少行数据
- 延迟:从数据到达源端到写入目标端的时间
- 资源消耗:内存、CPU、磁盘I/O、网络带宽
- 连接池状态:活跃连接数、等待连接数
为什么会这样?因为很多ETL工具默认配置是给OLTP场景用的,你拿来跑批处理,连接池一下就满了。我曾经调过一个任务,把连接池从10改成50,性能直接翻倍。
这里我画了一张性能监控的核心流程图,你看一眼就明白了:
27.4 故障恢复:别让数据丢了
故障恢复的核心就一句话:幂等性。同一个任务跑两次,结果必须一样。我常用的恢复策略:
- 断点续传:记录每个分区的处理状态,失败后从断点继续
- 重试机制:指数退避重试,第一次等10秒,第二次等30秒,第三次等90秒
- 回滚策略:如果目标表支持事务,失败时整体回滚;如果不支持,用临时表做中间态
实战经验:我建议每个ETL任务都配一个「状态表」,记录任务ID、开始时间、结束时间、处理行数、状态码。这样恢复时直接查状态表,不用猜。
举个例子,我曾经处理过一个Kafka到HDFS的实时ETL任务。Kafka的offset是连续的,但HDFS写文件时可能写到一半就挂了。我的做法是:先写临时文件,写完后原子重命名。这样即使任务挂了,重启后也能从上次的offset继续消费。
-- 状态表示例
CREATE TABLE etl_job_status (
job_id STRING,
source_offset BIGINT,
target_path STRING,
status STRING, -- RUNNING, SUCCESS, FAILED
retry_count INT,
create_time TIMESTAMP,
update_time TIMESTAMP
);
27.5 版本管理:别让改代码变成灾难
版本管理不只是Git的事。ETL的版本管理要管三样东西:
- 代码版本:SQL脚本、Python脚本、配置文件
- 数据版本:源表结构变化、目标表结构变化、数据字典
- 调度版本:任务依赖关系、调度频率、参数配置
我见过最惨的案例——有人直接在生产环境改了SQL,没走版本控制。结果第二天数据对不上,回滚都不知道回滚到哪。从那以后,我强制要求所有变更必须走PR流程,并且要有自动化测试。
小技巧:每次部署前,自动生成一份「变更清单」,对比当前版本和上一个版本的差异。这样上线前就能发现是不是改了什么不该改的东西。
版本管理的另一个重点是回滚预案。每次上线前,我都要确认两件事:
- 回滚脚本准备好了吗?
- 回滚后数据一致性怎么保证?
说白了,上线不是终点,能安全回滚才是本事。
好了,这一章的内容就到这。日志、告警、监控、恢复、版本——这五个点做好了,你的ETL系统就能睡个安稳觉。记住,运维不是事后补救,而是事前预防。