淘宝用户行为项目是我完成度最高的一条离线数仓练习。它的输入很朴素:一个很大的行为明细 CSV,字段只有 user_id,item_id,category_id,behavior_type,ts,必须先按天切开才进得了集群。目标不是做几个看板,而是把 CSV 文件稳定加工成可调度、可校验、可追溯、可展示的电商数据仓库。
主链路如下:
UserBehavior.csv
-> 按天切分
-> Hadoop Landing + manifest
-> ODS Batch TEXT
-> ODS Parquet Snappy
-> DWD 明细宽表
-> DWS 用户/商品/漏斗汇总
-> ADS KPI/画像/归因/排行/异常
-> MySQL taobao_ads
-> Flask + ECharts / Grafana01集群与调度
项目文档记录的实验环境由一组 Hadoop 节点和一个独立的数据服务节点组成:
| 节点 | 角色 |
|---|---|
| Hadoop01 | NameNode、ResourceManager、Hive、Spark Master/Worker、Zookeeper、Kafka、Flume |
| Hadoop02 | DataNode、NodeManager、Spark Worker |
| Hadoop03 | DataNode、NodeManager、Spark Worker |
| main | MySQL、Airflow、BI 数据服务 |
Airflow DAG tb_data_pipeline 每天凌晨定时执行,任务顺序是:
validate_and_load
-> dwd_transform
-> dws_transform
-> ads_transform
-> sqoop_export早期也保留过 shell/crontab 形式,后面统一收敛到 Airflow,方便查看执行状态和失败重跑。
02Landing 与 ODS:先保证文件可信
本地大 CSV 先通过 split_by_day.py 按北京时间切成每日文件,再由 offline-etl.py 上传到 Hadoop Landing。上传时生成 manifest,记录文件大小、行数和 SHA256。
ODS 层分两步:
tb_ods_batch.user_behavior_di:TEXTFILE 暂存,接收原始分区。tb.ods_user_behavior_di:Parquet Snappy 标准化 ODS,补充source_file、etl_time和dt分区。
同一份数据从 TEXTFILE 转成 Parquet Snappy 之后,占用的存储空间明显下降,下游扫描时要读的字节也随之变少。这个结果说明列式存储和压缩不是“优化项”,而是后续 DWD/DWS 能稳定跑的基础。
03DWD:把行为日志加工成可分析明细
DWD 表 tb.dwd_user_behavior_di 保持明细行粒度不变,但把原始的几个字段扩展成一张可以直接分析的宽表。
新增字段包括:
- 行为中文名:
pv/cart/fav/buy映射为浏览、加购、收藏、购买。 - 时间维度:
event_time、event_hour、day_of_week、is_weekend。 - 会话字段:
session_id、session_seq、session_dur_sec,按固定的静默间隔切 session。 - 行为序列:
prev_behavior、next_behavior。 - 漏斗标记:
funnel_step,把浏览、加购、收藏、购买映射成递增的台阶。 - 质量字段:
quality_flag。 - 溯源字段:
source_file、etl_time。
DWD 的价值不是“多加字段”,而是把原始日志变成后续可复用的公共事实表。比如漏斗、归因、用户画像和异常监控都不需要重新解析时间戳或行为序列。
04DWS:按主题沉淀公共指标
DWS 层做轻度汇总,避免每张 ADS 报表重复扫 DWD。
| 表 | 粒度 | 说明 |
|---|---|---|
dws_user_daily | 用户 × 天 | pv/cart/fav/buy、会话数、活跃小时、购买商品/类目数 |
dws_item_daily | 商品 × 天 | 商品行为计数、购买用户数、cart/fav/pv 到 buy 转化率 |
dws_funnel_daily | 天 × 步骤 | 漏斗步骤用户数、相邻转化率、总体转化率 |
dws_etl_monitor | 步骤执行记录 | 行数、耗时、状态和错误信息 |
当前资源有限,所以没有做小时级 DWS、Cube 预聚合和复杂留存表。这个取舍是有意的:在数据量不小、内存很紧的小集群里,先保证每日批处理稳定和幂等,比堆企业级名词更重要。
05ADS、BI 与数据治理
ADS 层面向应用和展示:
| 表 | 用途 |
|---|---|
ads_kpi_dashboard | DAU、转化率、复购率、Top 类目等管理看板指标 |
ads_user_feature_wide | 短窗与长窗行为特征、偏好类目、活跃时段、RFM 分层 |
ads_attribution_path | 会话级行为路径与转化归因 |
ads_item_top | 每日热销商品榜 |
ads_anomaly_daily | 移动均值、z-score、环比变化和告警 |
Hive ADS 通过 Sqoop 导出到 MySQL taobao_ads,Flask + ECharts 提供接口和前端页面。接口覆盖 KPI、趋势、漏斗、用户分层、小时分布、Top 商品、行为路径和异常监控。
治理侧补了几块:
- 数据地图:
meta_catalog、meta_columns、meta_lineage,支持表搜索、表详情和血缘查询。 - 全链路可视化:把采集、ODS、DWD、DWS、ADS、MySQL、Flask 按链路阶段拆开。
- 质量规则:支持
row_count、null_rate、custom_sql检查,记录规则和执行结果。
06当前验证边界
这条链路主要验证离线日批的分层、调度、导出与展示闭环,不把它包装成实时数仓或生产级高并发系统。性能压测、小时级汇总、告警通知和长期稳定性仍是后续要补的实验,而不是当前项目已经完成的承诺。
07工程复盘
这个项目的核心收获是:离线数仓不是写几段 SQL,而是让每个环节都能被验证。
我认为最能体现工程能力的点是这几条:
- Landing manifest 用 SHA256 和行数校验避免坏文件进入 ODS。
- ODS 从 TEXTFILE 转成 Parquet Snappy,存储与扫描成本一起降下来。
- DWD 保持明细粒度不变,同时补齐会话、漏斗、行为序列和质量字段。
- Airflow 串起加载、DWD、DWS、ADS、导出,形成可调度闭环。
后续如果升级,我会优先做小时级 DWS、告警通知、数据地图自动化血缘和更完整的留存/复购指标,而不是简单增加页面数量。