1. 项目概述:基于Spark的商品房推荐系统
去年接手了一个房地产平台的智能化改造项目,客户需要从零构建一套能处理千万级房源数据的推荐系统。经过技术选型,最终采用Spark+Django架构实现了这套商品房推荐系统,日均处理2000万条用户行为数据,推荐准确率提升37%。这个系统核心解决了传统房产平台"千人一面"的推荐痛点,通过协同过滤算法为不同用户精准匹配房源。
系统分为三个核心模块:Spark分布式计算层处理海量用户行为数据并生成推荐结果;Django框架构建的Web应用层实现业务逻辑和前端展示;基于ECharts的数据可视化模块直观呈现楼盘分析数据。特别在Spark层,我们针对房产数据特点优化了传统的协同过滤算法,使其能够有效处理房源这类"冷启动"问题突出的物品类型。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 整体架构设计
系统采用典型Lambda架构,同时满足实时和离线处理需求:
code复制[数据源] -> [Spark批处理层]
-> [推荐模型存储]
-> [Django服务层]
-> [用户终端]
↘ [Spark流处理层] ->
批处理层每天凌晨全量更新用户画像和房源特征,流处理层实时处理用户最新行为。这种设计在保证推荐质量的同时,使系统响应速度控制在300ms以内。
2.2 技术选型考量
选择Spark作为计算引擎主要基于三点考虑:
- 内存计算特性适合频繁迭代的推荐算法
- MLlib内置的协同过滤算法可快速验证效果
- 原生Python API(pyspark)与Django整合成本低
Django框架的选择则因其:
- 自带Admin后台方便房源管理
- ORM简化数据库操作
- 模板系统快速构建数据可视化页面
3. 核心算法实现
3.1 协同过滤算法优化
基础算法采用ALS(交替最小二乘法),但针对房产数据做了三项关键改进:
python复制# 在Spark中初始化ALS模型
als = ALS(
rank=50, # 隐语义因子数
maxIter=15,
regParam=0.01,
coldStartStrategy="drop", # 冷启动处理
userCol="user_id",
itemCol="property_id",
ratingCol="rating_score"
)
改进点1:评分矩阵重构
传统5分制评分改为复合评分:
code复制评分 = 0.6*显式评分 + 0.3*浏览时长系数 + 0.1*分享次数
改进点2:地域衰减因子
引入反距离权重(IDW)算法,使推荐结果随距离衰减:
python复制def distance_weight(loc1, loc2):
d = geopy.distance.distance(loc1, loc2).km
return 1/(1+d) # 平滑衰减
改进点3:热度惩罚项
防止热门楼盘过度推荐:
python复制item_popularity = behavior_df.groupBy("property_id").count()
als_prediction = prediction.join(item_popularity, "property_id") \
.withColumn("final_score",
col("prediction")*(1-log(col("count")/max_count)))
3.2 冷启动解决方案
对于新上架楼盘,采用混合推荐策略:
- 基于内容相似度推荐(户型、价格段、地段)
- 基于区域热度推荐(该区域近期关注度)
- 人工运营位补足
通过AB测试,混合策略使新楼盘CTR提升22%。
4. 大数据处理实践
4.1 数据管道设计
使用Airflow调度每日数据处理任务:
python复制with DAG('property_recommend', schedule_interval='0 3 * * *'):
ingest = SparkSubmitOperator(
task_id='data_ingest',
application='ingest.py'
)
train = SparkSubmitOperator(
task_id='model_training',
application='train.py',
application_args=['--date', '{{ ds }}']
)
ingest >> train
4.2 性能优化技巧
- 分区策略:按城市+日期二级分区,使扫描数据量减少80%
- 广播变量:将20MB以下的小表广播到各节点
- 存储格式:Parquet列式存储+Snappy压缩
- 内存配置:Executor内存中50%留给Storage区域
关键配置示例:
bash复制spark-submit --executor-memory 8G \ --driver-memory 4G \ --conf spark.sql.shuffle.partitions=200 \ --conf spark.default.parallelism=100
5. Django系统实现
5.1 推荐API设计
python复制# views.py
class RecommendationView(APIView):
def get(self, request):
user_id = request.user.id
# 从Redis获取预计算的推荐结果
recs = cache.get(f'recs:{user_id}')
if not recs:
# 实时计算后备方案
recs = fallback_recommend(user_id)
return Response(recs[:20])
5.2 数据可视化方案
前端使用ECharts实现三类分析视图:
- 用户画像雷达图:展示价格敏感度、户型偏好等维度
- 楼盘热力图:基于地图API展示区域热度
- 对比柱状图:不同楼盘的关注度对比
javascript复制// 热力图配置示例
option = {
tooltip: {},
visualMap: {
min: 0,
max: 100,
calculable: true
},
series: [{
type: 'heatmap',
coordinateSystem: 'bmap',
data: heatData
}]
}
6. 部署与监控
6.1 集群部署方案
采用Kubernetes部署架构:
- Spark on K8s:3个Master节点+10个Worker节点
- Django集群:5个Pod负载均衡
- Redis集群:3主3从架构
- Prometheus+Granfana监控体系
6.2 关键监控指标
-
推荐质量指标:
- 点击通过率(CTR)
- 转化率(CVR)
- 推荐多样性
-
系统性能指标:
- P99响应时间
- 每日处理数据量
- 模型训练耗时
7. 踩坑与经验
-
数据倾斜问题:某热门楼盘导致计算长尾
- 解决方案:采样+分桶处理
- 检测方法:Spark UI观察Task耗时分布
-
特征穿越问题:误用未来数据
- 解决方案:严格按时间切分训练/测试集
- 检测方法:人工审查特征生成逻辑
-
Django ORM性能陷阱:N+1查询问题
- 解决方案:使用select_related/prefetch_related
- 检测方法:Django Debug Toolbar
这个项目给我的深刻体会是:推荐系统效果30%靠算法,70%靠数据质量。我们花了大量时间清洗开发商提供的楼盘数据,统一了全国200多个城市的行政区划编码体系,这个基础工作最终使推荐准确率提升了15个百分点。另一个收获是,在房产这类低频消费领域,单纯的行为数据远远不够,必须引入丰富的上下文特征(如学区政策、交通规划等)。
