上一篇
爱奇艺大数据开发笔试题
- 行业动态
- 2025-05-05
- 2697
基于用户行为与内容特征,通过数据清洗、特征工程构建推荐模型,采用ALS或Spark MLlib进行协同过滤训练,结合
实时用户行为分析系统设计
系统架构设计
组件 | 功能描述 |
---|---|
数据源 | Kafka集群:接收用户行为日志(含用户ID、时间戳、行为类型) |
流处理层 | Flink/Spark Streaming:实时消费Kafka数据,窗口计算UV、购买转化率 |
状态管理 | Flink Keyed State:维护用户活跃状态和购买标记 |
结果存储 | MySQL:存储每分钟计算结果(活跃用户数、转化率) |
监控层 | Prometheus+Grafana:监控系统延迟、吞吐量、错误率 |
核心处理逻辑(Flink示例)
// 定义水位线允许的事件延迟 env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime) val watermarkStrategy = WatermarkStrategy[UserBehavior] .withTimestampAssigner((event, timestamp) => event.timestamp) .withIdleness(Duration.ofMinutes(1)) // 主流处理逻辑 kafkaSource.assignTimestampsAndWatermarks(watermarkStrategy) .keyBy(_.userId) .window(TumblingEventTimeWindows.of(Time.minutes(1))) .process(new WindowFunction { def process(key, window, input, out): Unit = { val activeUsers = input.map(_.userId).distinct(_.userId).size val purchaseCount = input.filter(_.action == "purchase").size out.collect((window.getEnd, (activeUsers, purchaseCount))) } }) .addSink(mysqlSink)
关键优化点
优化方向 | 实施方案 |
---|---|
状态后端 | 使用RocksDB管理状态,设置stateBackend = new RocksDBStateBackend() |
检查点 | 启用Checkpoint(每分钟一次),配置checkpointStorage = new FsStateBackend("hdfs://...") |
并发控制 | 根据Kafka分区数设置parallelism = kafkaPartitions 2 |
反压处理 | 开启backpressure.enabled=true ,调整max.parallelism 参数 |
离线数据仓库建模(星型模型)
维度表设计
维度表 | 字段示例 | 存储周期 |
---|---|---|
用户维度 | user_id, gender, age, city, create_time | 永久存储 |
商品维度 | item_id, category, price, brand | 永久存储 |
时间维度 | date, hour, week, month, quarter | 最近2年数据 |
事实表设计
CREATE TABLE fact_order_detail ( order_id BIGINT, user_id BIGINT, item_id BIGINT, amount DECIMAL(10,2), order_time TIMESTAMP, -外键关联维度 PRIMARY KEY (order_id) ) PARTITIONED BY (dt STRING) STORED AS ORC;
ETL流程设计
graph TD A[原始订单数据] --> B[数据清洗] B --> C[关联用户维度表] C --> D[关联商品维度表] D --> E[按日期分区] E --> F[存储至Hive]
常见问题与解答
Q1: Flink状态后端选择RocksDB还是内存?何时需要切换?
A1:
- 内存状态后端:适合小状态场景(如简单计数器),重启后状态丢失。
- RocksDB状态后端:适合大状态场景(如复杂用户画像),支持状态持久化和恢复。
- 切换时机:当状态数据量超过数百MB或需要故障恢复时,必须使用RocksDB。
Q2: Hive分区表设计时如何选择分区字段?
A2:
- 高频查询字段:优先选择WHERE条件中高频出现的字段(如
date
)。 - 基数控制:避免高基数字段(如
user_id
),建议使用组合分区(如year=2023/month=10/day=15
)。 - 业务意义:按自然时间周期或业务周期划分(如电商大促期间