1. 项目背景与需求分析
去年我在某电商平台实习期间,负责优化他们的推荐系统时发现一个有趣现象:手机品类的用户点击转化率比其他品类低了近30%。经过深入分析,发现问题出在现有的协同过滤算法上——它只能基于历史行为做简单推荐,完全忽略了手机这类高单价商品的特殊购买逻辑。
手机购买决策通常具有以下特点:
- 决策周期长(平均7-15天)
- 对比维度多(性能、价格、品牌等)
- 用户会反复查看同类商品
- 评价内容影响重大
传统推荐系统面对这种场景时,就像用渔网捞金鱼——看似覆盖全面实则漏洞百出。这促使我设计了这个基于Hadoop的京东手机推荐系统,核心要解决三个问题:
- 如何捕捉用户的跨会话行为特征
- 如何量化非结构化评价数据
- 如何实现实时+离线混合推荐
2. 系统架构设计
2.1 技术选型对比
在方案设计阶段,我对比了三种技术路线:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 纯Spark | 实时性好 | 机器学习库有限 | 需要流处理的场景 |
| Hadoop+Mahout | 成熟稳定 | 实时性差 | 批处理推荐 |
| Hadoop+Spark MLlib | 兼顾批流 | 运维复杂 | 混合推荐系统 |
最终选择第三种方案,核心考虑是:
- 京东手机数据日均增长2TB+,HDFS的分布式存储更可靠
- Spark SQL可以高效处理用户行为日志
- MLlib提供的ALS算法特别适合隐性反馈数据
2.2 分层架构实现
系统采用经典Lambda架构,分为五层:
code复制[数据源层]
├─ JD商品API
├─ 用户行为日志
└─ 评论爬虫
[存储层]
├─ HDFS原始数据
├─ HBase实时数据
└─ Hive数仓
[计算层]
├─ MapReduce离线处理
├─ Spark Streaming实时计算
└─ Spark MLlib模型训练
[服务层]
├─ RESTful API
├─ 推荐引擎
└─ 缓存集群
[展示层]
├─ Web前端
├─ 移动端
└─ 管理后台
特别说明几个关键设计点:
- 使用Flume+Kafka做日志采集,确保高峰时段不丢数据
- Hive表按日期+商品类目分区,查询效率提升6倍
- Redis缓存热门手机榜单,减轻数据库压力
3. 核心算法实现
3.1 数据预处理流程
原始数据需要经过严格清洗:
python复制# 示例:评论情感分析预处理
def clean_text(text):
# 去除特殊字符
text = re.sub(r'[^\w\s]', '', text)
# 中文分词
words = jieba.cut(text)
# 去除停用词
stop_words = load_stopwords()
return [w for w in words if w not in stop_words]
# 使用TF-IDF提取关键词
tfidf = TfidfVectorizer(max_features=500)
features = tfidf.fit_transform(cleaned_texts)
3.2 混合推荐算法
结合协同过滤与内容推荐的优势:
-
离线部分(每日更新)
- 使用ALS矩阵分解计算用户-商品隐含特征
scala复制val als = new ALS() .setRank(50) .setMaxIter(10) .setRegParam(0.01) .setImplicitPrefs(true) val model = als.fit(ratings) -
实时部分(用户触发时计算)
- 基于当前会话计算内容相似度
- 结合用户画像做加权排序
-
冷启动处理
- 新用户:采用热门手机+品牌偏好策略
- 新商品:使用Word2Vec计算描述文本相似度
4. 性能优化实践
4.1 分布式计算调优
在集群部署时踩过几个坑:
-
问题1:Reduce阶段卡住
- 原因:数据倾斜导致个别Reducer负载过高
- 解决:增加随机前缀打散热点数据
-
问题2:Spark任务OOM
- 原因:默认executor内存配置不足
- 优化:
bash复制
spark-submit --executor-memory 8G --driver-memory 4G --num-executors 20
4.2 缓存策略设计
采用三级缓存架构:
- 本地缓存(Guava):存储用户最近浏览记录
- Redis集群:缓存热门推荐结果
- HBase:存储用户长期画像
关键配置参数:
xml复制<!-- Redis连接池配置 -->
<redis>
<maxTotal>200</maxTotal>
<maxIdle>50</maxIdle>
<minIdle>10</minIdle>
<testOnBorrow>true</testOnBorrow>
</redis>
5. 效果评估与改进
5.1 A/B测试指标
上线后对比原系统关键指标提升:
| 指标 | 旧系统 | 新系统 | 提升 |
|---|---|---|---|
| CTR | 1.2% | 2.7% | 125% |
| 转化率 | 0.8% | 1.5% | 87.5% |
| 平均停留时长 | 68s | 142s | 108% |
5.2 典型问题排查
问题现象:凌晨时段推荐质量下降
排查过程:
- 检查监控发现此时正在跑MapReduce离线任务
- 查看资源管理器发现磁盘I/O饱和
- 定位到Hive查询没有限制分区范围
解决方案:
sql复制-- 优化前
SELECT * FROM user_behavior WHERE dt='20230101';
-- 优化后
SELECT * FROM user_behavior
WHERE dt='20230101'
AND category='mobile';
6. 项目部署指南
6.1 环境准备
硬件最低配置:
- 5台服务器(1NameNode+4DataNode)
- 每台32核CPU/64GB内存/10TB硬盘
- 万兆网络互联
软件版本要求:
- Hadoop 3.2.4
- Spark 3.1.3
- HBase 2.4.9
- JDK 1.8+
6.2 关键配置项
hdfs-site.xml重要参数:
xml复制<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<name>dfs.blocksize</name>
<value>256m</value>
</property>
7. 开发经验总结
-
数据质量优先:初期曾因脏数据导致推荐异常,后来增加了数据校验模块:
java复制public boolean validateUserLog(UserLog log) { return StringUtils.isNotBlank(log.getUserId()) && log.getViewTime() > 0 && VALID_ACTIONS.contains(log.getAction()); } -
算法可解释性:为运营人员开发了推荐理由生成功能:
- "根据您最近浏览的华为P50"
- "与您同年龄段的用户也喜欢"
-
灰度发布策略:先对5%用户开放新算法,观察指标稳定后再全量
这个项目让我深刻体会到,好的推荐系统不是算法越复杂越好,关键要理解业务场景。比如发现手机推荐中"价格区间"这个因子权重特别高,后来专门优化了价格敏感度模型。建议后续可以加入更多时序特征,比如考虑节假日促销的影响。