ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Spring Boot + 协同过滤:跳蚤市场商品推荐系统实战

Spring Boot + 协同过滤:跳蚤市场商品推荐系统实战 springboot基于协同过滤算法的跳蚤市场商品推荐系统去年年底帮一个学弟做的毕业设计题目就是这个“基于协同过滤的跳蚤市场商品推荐系统”。他从一开始就没想清楚自己到底要做什么跟我说“导师让做一个带推荐功能的商城”结果需求文档写得跟淘宝似的。我听完就乐了你又没有淘宝级别的数据量搞什么高大上的推荐系统呢。你一个校园二手市场用户撑死几百人商品几千件你用什么深度学习、用什么大模型那都是杀鸡用牛刀。协同过滤这种经典算法正好是这个场景下的最优解。花了两周时间从需求梳理、表结构设计到算法落地、接口联调最后给他整出来一套完完整整能跑的项目。这中间踩了不少坑也总结了一些经验今天就把整个项目从头到尾拆解一遍从技术选型到算法实现从数据库设计到部署上线都写在这里。无论你是要做毕设、课程设计还是单纯想了解推荐系统在真实业务里怎么落地这篇都值得你耐心看完。1. 项目整体设计与思路拆解1.1 核心需求解析先搞清楚这项目到底是干什么的。跳蚤市场说白了就是二手交易平台学生把自己闲置的教材、数码产品、自行车、吉他挂上去卖其他人看到合适的就买走。核心功能就是商品发布、浏览、下单、订单管理、个人中心这些这些常规功能网上一抓一大把没什么技术含量。真正有技术含量的是“推荐”两个字。系统要能根据用户的历史行为比如浏览过什么、收藏过什么、买过什么主动把当前用户可能感兴趣的商品推送给他。这就是协同过滤算法的应用场景。那为什么不直接做商品分类筛选而是要做推荐呢原因很简单跳蚤市场跟淘宝京东不一样这里没有海量商家和铺天盖地的广告商品全靠搜索和分类很难被看到。比如某个用户是一名大二学生他刚学完高数想卖教材另一个大四学生正好在找这本教材。如果靠传统搜索两个人必须先知道对方上传了什么关键词才能匹配。但推荐系统的作用是当大四学生登录首页时系统会主动把他可能需要的教材推给他用户甚至不用搜索就能看到。推荐在这里的价值就是提升交易匹配效率和用户粘性。1.2 技术选型背后的考量这套系统我选了Spring Boot 2.7 MyBatis Plus MySQL 8.0 Redis Vue 3作为主技术栈推荐算法部分用Python实现。看到Python可能有人会问既然都用了Java为什么算法不也用Java写因为我只取算法计算出来的推荐结果通过JSON接口返回给Java后端算法本身和主系统解耦。比如相似度矩阵计算、用户商品交互数据处理这些用Python的pandas处理比Java方便得多开发效率完全不是一个量级。Spring Boot就不多说了现在做Java后端项目的标配自动配置省掉一大堆繁琐的XML配置。MyBatis Plus是我个人比较喜欢的一个ORM框架它比原生MyBatis好在单表操作不需要写SQL代码生成器一键生成实体类和Mapper太香了。MySQL选8.0是因为对JSON数据类型的支持更好后面我们会用到。Redis这个很关键它承担两个任务一是分布式session存储解决集群部署时的会话共享问题二是缓存热点数据和推荐结果避免每次刷新页面都重复计算推荐列表。前端用Vue 3加Element Plus这套组合适合后台管理系统场景对比Vue 2的选项式APIVue 3的组合式API代码更简洁逻辑复用也方便。UI框架用Element Plus能快速搭出清爽的管理后台这活干了这么多年就说句实话做这种带后台管理的项目Element Plus比Ant Design Vue上手更快。1.3 算法选型为什么是协同过滤协同过滤算法是推荐系统里最经典的算法之一核心思想就一句话人以群分物以类聚。它的实现主要分两种思路。基于用户的协同过滤User-Based CF是先找到和你兴趣相似的用户看看你相似用户都买过什么把这些商品推荐给你。基于物品的协同过滤Item-Based CF则是先算出物品之间的相似度然后根据你之前买过或浏览过的东西给你推荐相似的物品。这两个方案选哪个我在这里选了基于物品的协同过滤。为什么看一个具体的运营场景你就明白了某用户在跳蚤市场浏览过一本《数据结构》教材基于物品协同过滤就能算出这本《数据结构》教材和《算法导论》教材的相似度很高因为经常被同一批用户一起浏览和购买于是推荐算法就会给这个用户推《算法导论》的二手书。而基于用户的协同过滤算法更适合那种用户量远大于商品量、用户兴趣标签明显的平台。但跳蚤市场这个场景校园里用户就千把人商品却能不断新增商品之间的相似关系比用户之间的相似关系稳定得多。所以我最终选择了Item-Based CF作为主力算法。不过这还不够协同过滤有两个绕不开的痛点一个是冷启动问题新商品没有任何用户行为数据协同过滤就算不出它跟其他商品的相似度一个是数据稀疏问题跳蚤市场的用户行为本来就少矩阵稀疏得跟渔网似的。后面实操部分我们会讲怎么用数据预处理和兜底策略来处理这两个坑。2. 数据库设计与核心模块实现2.1 表结构设计的关键细节数据库是一个业务系统的地基这里的表结构设计花了不少心思。核心表包括用户表、商品表、订单表、收藏表、浏览记录表、评分表、推荐结果表。说几个关键设计的细节。第一个是用户表。用户除了常规的id、用户名、密码、昵称、头像、手机号、角色之外我特意加了一个字段叫user_type用来区分买家和卖家身份。有人可能会说跳蚤市场里每个人不都既是买家又是卖家吗你说得对但实际运营中有一部分用户就是只买东西不卖东西为了后续运营分析的便利还是把角色区分开了。对于既卖又买的用户这个字段就标记为both。第二个是商品表。关键字段有商品标题、描述、价格、原价、成色、分类、图片、状态。其中成色这个字段是跳蚤市场特有的业务字段是卖家对商品新旧程度的自评一般分成全新、几乎全新、轻微使用痕迹、明显使用痕迹、有瑕疵这五档这个字段在后续推荐权重计算里会有大用场。状态字段是上架中、已下架、已售出三个值查询时永远只查上架中的商品。第三个是订单表。除了常规的订单号、买家id、卖家id、商品id、价格、下单时间、支付时间之外我把订单状态细化成了待付款、待发货、已发货、已完成、已取消、退款中、已退款七个状态。都是做电商的为什么订单状态这么细你应该深有体会不细化后面统计经营数据的时候哭都来不及。然后是收藏表和浏览记录表。这两张表是推荐算法最重要的数据来源收藏表记录了用户对哪些商品感兴趣浏览记录表记录了用户看过哪些商品、看了多久。这里有个实用的设计经验浏览记录表不要只存商品id和浏览时间我加了一个duration字段记录用户在该商品详情页停留的秒数这个数据在后续算用户兴趣权重时非常好用停留时间长的商品说明用户确实感兴趣。评分表的设计也是推荐系统的重头戏。表面上用户可以在购买完成后给商品打分1到5分这是显式反馈数据。但跳蚤市场这类平台用户主动评分的行为其实很少所以我在设计评分表时把收藏行为、浏览行为、购买行为都归总到一张偏好记录表里作为隐式评分的数据来源这样协同过滤算法的输入数据才够用。最后是推荐结果表。这张表存协同过滤算法算出来的推荐结果包含用户id、商品id、推荐分值、推荐时间、推荐来源推荐来源区分了是基于协同过滤算出来的还是用了兜底策略算出来的。为什么要存这张表一是为了方便运营人员排查一个用户为什么看到这些推荐商品二是方便测试对比算法效果再者是避免一次首页请求就触发一次全量推荐计算直接把已经算好的结果查出来返回就行。2.2 Spring Boot后端架构与业务层实现后端项目用了经典的三层架构Controller层负责接收请求和参数校验Service层实现业务逻辑Mapper层处理数据库交互。为了避免代码量太庞大导致后期难维护项目做了一点点领域拆分的动作把用户、商品、订单、推荐这四个板块分成独立的模块。用户模块相对传统主要就是注册、登录、个人信息修改。注册逻辑里加了一道基础的校验比如用户名是否已存在、密码强度是否合规。密码存储用了BCrypt加密这是Spring Security框架提供的加密组件比MD5这种已经被撞库撞烂的算法要安全得多对毕设项目来说这个安全级别是够的。商品模块除了最基础的增删改查核心逻辑在于发布商品的流程里做了图片上传和价格合理性校验。图片上传这块我用了本地存储方案而不是对象存储服务因为项目还处在学习演示阶段没必要上云。改一下配置文件里的路径就行上传的图片通过WebMvcConfigurer配置的虚拟路径映射暴露给前端。商品查询列表做成分页接口支持按分类筛选、按价格区间筛选、按关键字模糊搜索。这里我用了MyBatis Plus的Page分页插件配合LambdaQueryWrapper构造动态查询条件单个接口能应对多种组合查询场景。这块也没人用ES做搜索数据量在这儿摆着呢杀鸡不用牛刀。订单模块是业务逻辑最复杂的一块。核心难点在于订单状态的流转管理我用了状态机模式来约束订单状态的合法流转比如已发货状态不能直接跳到已取消必须是已发货才能确认收货变成已完成。这块的代码核心是提前把每种状态允许跳转的状态集合定义好每次更新状态前做合法性校验这样一来脏数据的问题就能从源头上杜绝掉。推荐模块是我重点设计的。推荐接口从Redis缓存里查推荐结果查不到就走数据库里的推荐结果表数据库里也没有就触发实时推荐计算。这个多级缓存的设计思路很实用避免了每次请求都打数据库或者重复计算推荐结果。2.3 前端界面与交互流程前端部分用的是Vue 3加Element Plus做的核心页面有首页、商品详情页、购物车页、订单管理页、个人中心页、发布商品页、后台管理页。首页分两部分顶部是推荐位中间是全部商品列表。推荐位是首页最重要的一块这部分直接调用后端的推荐接口推荐结果展示成一行商品卡片每张卡片展示商品封面图、标题、价格、成色标签。这里我花了点心思被推荐的商品要打一个“猜你喜欢”的角标因为据我观察有推荐标签的商品点击率明显高于普通商品这算是利用推荐算法加运营策略提升整体点击率的一个小技巧。商品详情页展示了商品的完整信息包括图片、描述、成色、卖家信息同时也展示了相关推荐商品相关推荐的数据来源还是协同过滤算出的相似商品。这个功能是基于物品的协同过滤的直接体现用户正在看某个商品系统给他推相似商品促使他继续浏览。订单流程是这样的用户在商品详情页点击“立即购买”会创建一笔待付款订单支付成功进入待发货状态卖家发货后进入已发货状态买家确认收货后订单完成。另外做了售后服务功能买家可以发起退款申请卖家同意后订单状态变成已退款。整个交互流程该有的环节一个都没少。后台管理页面主要是管理员视角包括用户管理、商品管理、订单管理、数据统计管理员可以下架违规商品可以冻结违规用户。这个后台的权限控制用了最基础的拦截器方案管理员接口统一走/admin路径拦截器里校验当前登录用户是不是管理员角色。3. 协同过滤推荐算法的详细设计与落地3.1 数据预处理从原始行为到评分矩阵数据预处理是协同过滤算法工程质量的决定性因素比选择算法本身还重要。所有推荐算法的输入都是用户对物品的评分矩阵但跳蚤市场的原始数据里根本没有现成的评分数据全靠我们自己做数据加工。我们把用户对商品的反馈分为几个等级。收藏行为权重是3分加购物车是4分购买行为是5分浏览行为按停留时间折算成0.5到2分。为什么不直接用统一分数呢这背后的逻辑是一个用户买了某个商品说明他对这个商品有强兴趣这个信号比单纯的浏览强得多。如果不同强度的行为统一记1分那算法算出来的相似度区分度就很差。具体的偏好值计算逻辑我写成了Python的pandas代码片段这里是核心部分import pandas as pd import numpy as np def build_user_item_matrix(): # 读取收藏记录 df_fav pd.read_sql(SELECT user_id, product_id, create_time FROM fav_record, engine) df_fav[action_weight] 3.0 # 读取加购物车记录 df_cart pd.read_sql(SELECT user_id, product_id, create_time FROM cart_record, engine) df_cart[action_weight] 4.0 # 读取购买记录 df_order pd.read_sql(SELECT buyer_id as user_id, product_id, create_time FROM orders WHERE status已完成, engine) df_order[action_weight] 5.0 # 读取浏览记录按停留时间折算 df_view pd.read_sql(SELECT user_id, product_id, duration FROM view_record, engine) df_view[action_weight] df_view[duration].apply( lambda x: 0.5 if x 10 else (1.0 if x 30 else 2.0) ) # 合并所有行为并聚合 df_all pd.concat([df_fav[[user_id,product_id,action_weight]], df_cart[[user_id,product_id,action_weight]], df_order[[user_id,product_id,action_weight]], df_view[[user_id,product_id,action_weight]]], ignore_indexTrue) df_score df_all.groupby([user_id,product_id])[action_weight].sum().reset_index() df_score[action_weight] df_score[action_weight].clip(upper10) # 透视成用户-商品矩阵 matrix df_score.pivot_table(indexuser_id, columnsproduct_id, valuesaction_weight) matrix matrix.fillna(0) return matrix看着代码不难实际踩过的坑是在写入推荐结果表的时候如果用户行为特别多全量写入的耗时就会比较长容易把接口拖垮。所以我把离线计算和接口请求做了解耦离线计算出的推荐结果由后台任务写入推荐结果表接口只做查询动作。这个等下面部署部分详细说。3.2 Item-Based协同过滤的相似度计算基于物品的协同过滤核心分两步第一步算物品之间的相似度矩阵第二步根据用户历史行为把相似度高的物品推荐给用户。物品相似度的计算方式有很多种最常见的有余弦相似度、皮尔逊相关系数、Jaccard相似度。我这里用的是余弦相似度因为这个指标计算简单效果稳定对数据稀疏场景的容忍度也相对更高。余弦相似度的公式看着抽象但其实通俗解释一下就是两个向量夹角的余弦值夹角越小说明两个向量越相似。放在场景里理解就是计算两件商品被同一群用户产生过行为的一致程度。比如商品A被用户甲、乙、丙浏览或购买过商品B也被用户甲、乙、丙浏览或购买过那么这两件商品的向量就很接近相似度就高。在Python里计算也很简单直接调用scikit-learn库的pairwise_distances函数就能得到物品之间的相似度矩阵。from sklearn.metrics.pairwise import cosine_similarity # 矩阵转置变成商品-用户的矩阵行列原来是用户-商品 item_matrix matrix.T # 计算商品之间的余弦相似度 item_similarity cosine_similarity(item_matrix) # 转成DataFrame便于处理 item_sim_df pd.DataFrame(item_similarity, indexitem_matrix.index, columnsitem_matrix.index)算完相似度矩阵后关键一步是做相似商品的筛选。一刀切地把所有相似商品都算作候选是不行的一定要设置相似度阈值做过滤我用的阈值是0.5低于0.5的相似度不参与推荐。同时每个商品的相似商品最多保留Top 20。这里控制一下计算量和推荐精度不然相似度矩阵全量算下来容易内存爆炸。3.3 生成推荐列表的核心逻辑有了物品相似度矩阵接下来就是为用户生成Top N的推荐列表了。核心逻辑是找出用户最近有过正反馈行为的商品然后去相似度矩阵里找出这些商品的相似商品按相似度加权求和排个序取前N个。我在实现的时候专门加了一个时间衰减函数。理由是跳蚤市场这类平台用户在一个月前浏览过的商品和昨天刚浏览过的商品在当前时刻的兴趣权重不应该是一样的。时间衰减函数距离今天越近的行为权重越高越久远的行为权重越低用指数衰减来模拟这个规律效果明显好于不衰减的方案。核心代码是这一段import math from datetime import datetime def generate_recommendations(user_id, user_item_matrix, item_sim_df, top_n10, decay_factor0.98): # 用户历史行为 if user_id not in user_item_matrix.index: return [] user_row user_item_matrix.loc[user_id] # 找出用户有行为的商品 interacted_items user_row[user_row 0].index.tolist() if not interacted_items: return [] # 计算每个候选商品的推荐得分 scores {} for item in interacted_items: # 获取当前商品相似度最高的几个商品 sim_scores item_sim_df[item].drop(labelsinteracted_items, errorsignore) sim_scores sim_scores[sim_scores 0.5].sort_values(ascendingFalse)[:20] # 用户对当前商品的兴趣强度 user_interest user_row[item] for sim_item, sim_value in sim_scores.items(): if sim_item not in user_row or user_row[sim_item] 0: scores[sim_item] scores.get(sim_item, 0) user_interest * sim_value # 按得分排序取TopN ranked sorted(scores.items(), keylambda x: x[1], reverseTrue)[:top_n] return ranked还记得前面对浏览记录做了时长折算吗在这里就用上了浏览时间长的商品user_interest值高一些直接影响推荐得分这样用户只看了一眼的商品就不会成为推荐的主参考而认认真真看了五分钟的商品则会成为主参考。这个细节不算很难但就是这些细节决定了算法的推荐质量是普通水平还是相对优良。运营的A同学做了测试同一个用户用带时间衰减和不带时间衰减两版算法跑出来的结果第一屏的推荐商品准确率差了大概15%。很直观的效果差异。3.4 冷启动问题的兜底方案协同过滤算法最恶心的坑就是冷启动。系统刚上线商品和用户行为数据都很少矩阵稀疏到几乎每行每列都是0这时候算法就算跑出来结果也基本等于瞎推荐。冷启动分为用户冷启动和物品冷启动。新注册的用户没有任何行为数据推荐算法拿什么算相似度新上架的商品没有任何人看过买过相似度矩阵里它跟谁都不相似。我的兜底方案分了三层来做。第一次兜底对于完全没有行为数据的新用户直接推荐平台的热门商品。热门商品怎么定义就是最近7天浏览次数最多、收藏次数最多的商品按权重排序取前20个。这个策略简单粗暴但极其有效新用户进来看到大家都在看的商品至少不会觉得推荐完全不相关。第二次兜底对于有少量行为的用户如果行为数据不足以支撑协同过滤就用基于内容的推荐方式。具体实现是将商品分成若干个分类比如“教材教辅”、“数码产品”、“生活用品”、“运动户外”等然后对用户浏览过的商品类别做统计找出用户最感兴趣的Top3品类在这些品类下按价格、热度综合排序推荐一些好商品。这套基于内容的方案原理不复杂但实现后对冷启动用户的推荐效果立竿见影。第三次兜底新上架的商品在新品期内也就是上架后72小时内在推荐结果里做一个加权操作。具体做法是给新商品一个初始曝光权重这样它们在用户生成个性化推荐列表时有机会被带上。虽然新商品没有协同过滤的相似度数据但我们可以在Item-Based协同过滤的基础上额外附加一批新商品推荐设置20%的推荐位留给这类商品。这样就同时照顾了用户体验和新品曝光。这三层兜底方案加起来的实现成本不高但对整个系统的推荐可用性提升是决定性的。没有兜底方案的推荐系统在早期阶段基本是废的。4. 热门问题与性能优化实录4.1 推荐结果不准确怎么办在调这个系统时被问得最多的问题就是推荐结果不准推出来的商品用户根本不想看。这类问题基本可以按下面的思路逐层排查。第一步先检查数据量。如果用户行为记录不到50条那协同过滤效果不好是正常的没有足够的历史数据任何推荐算法都白搭。解决办法是用前面说的兜底策略优先走热门推荐或基于内容推荐。第二步检查评分矩阵的稀疏度。要算一个数据指标矩阵中非零元素占总元素的比例如果低于1%那协同过滤的效果就会打折。跳蚤市场数据天生稀疏解决办法是对行为数据进行加权比如购买过的商品权重调高到5分浏览只有1分提高强信号数据的占比。第三步检查相似度阈值。我默认设置0.5但这个值不是固定的。如果发现推荐的相似商品太少可以适当降低到0.3如果推荐的相似商品明显没多大相关性就调高到0.6。这个参数需要在不同数据集上反复试验。第四步看推荐结果表的兜底来源占比。我们每一条推荐记录都带一个来源字段如果发现大量推荐走的都是热门推荐而不是协同过滤说明协同过滤的有效覆盖率不足需要针对性排查是数据稀疏还是相似度矩阵计算错误。4.2 Redis缓存与接口响应优化推荐接口和首页接口是性能考量的重中之重。首页接口要聚合推荐商品、热门商品、最新商品等多个数据源如果没有缓存数据库压力会非常大。我用Redis做了一个两级缓存的方案。第一级缓存存推荐商品的Id列表Key设计成recommend:user:{userId}有效时间设成了30分钟。为什么是30分钟而不是更长因为推荐结果如果太久不更新用户每次打开看到的东西都一模一样时间长了就会产生审美疲劳30分钟算是一个兼顾实时性和缓存命中率的折中值。第二级缓存存了商品本身的详细信息Key设计成product:info:{productId}有效时间设成2小时。第一级缓存存储推荐id列表第二级缓存存储商品详细信息。三级缓存把商品详情从数据库里挪到Redis里商品详情的查询压力大幅下降实测下来首页的接口响应时间从150毫秒降到了50毫秒以下流畅度大幅提升。还有一点要注意的细节修改商品信息、下架商品时必须同步删除对应的商品缓存不然用户看到的还是旧的商品信息这就是经典的一致性维护问题。我实现方式是在商品更新的Service方法里统一调用Redis删除操作宁多删勿漏删。4.3 并发扣减库存与订单一致性跳蚤市场和常规电商有一个本质区别每件商品只有一个库存量。这意味着如果两个用户同时下单购买同一个商品只能有一个人成功另一个人必须收到“手慢了商品已被购买”的提示。如果只是减库存不加控制用常规的先查库存再更新库存的方式高并发场景下就会产生超卖问题。两个请求同时查到库存是1都判断可以买都执行了下单最后库存变成-1这就是超卖。解决办法是用数据库行锁配合乐观锁。在扣减库存时执行一条带条件更新的SQL语句只有当前库存大于0时才允许扣减同时受影响的行数为1才代表更新成功没成功就说明已经被别人抢了。UPDATE product SET stock stock - 1 WHERE id #{productId} AND stock 0MyBatis加不加Transactional这个细节也要留意。扣减库存、创建订单这两个操作必须加事务任何一个失败都要回滚保证数据一致性。这段代码是整个订单流程里最容易出bug的地方一定要把单元测试写好模拟并发场景反复压测。4.4 定时任务与离线计算调优推荐结果的计算不需要实时跑更合理的做法是定时任务离线计算。我用了Spring Boot内置的Scheduled注解实现定时任务固定在每天凌晨3点全量计算一次这个时间点服务器负载最低。每天凌晨计算的是全量推荐结果写入推荐结果表。另外内部做了一套增量计算逻辑每30分钟计算一次只算最近30分钟内有新行为数据的那些用户更新他们的推荐结果保证推荐列表的时效性。两套计算逻辑配合起来全量保证数据基础增量保证实时反馈服务器压力也不会太大。离线计算的核心数据结构是物品相似度矩阵全量计算时我会把它序列化保存到本地文件。增量计算时加载这个相似度矩阵只更新行为发生变化的用户避免每次都要全量重新加载所有数据。这个优化直接把定时任务的平均执行时间从十几分钟压到了几分钟。5. 部署上线与运营落地5.1 项目部署与安全合规部署方案选了一台2核4G的云服务器Linux系统。后端项目打成JAR包通过systemd配置成守护进程开机自启加崩溃自动重启。前端用Nginx托管静态文件后端接口用反向代理映射到域名路径下Nginx是前端构建产物最经典的托管方案后端接口也走Nginx代理顺便解决跨域问题。Java启动参数里-Xms和-Xmx设为512m配合上G1垃圾回收器。2核4G的服务器配置跑这套系统完全可以驾驭实测并发在50左右时CPU占用率大约40%响应延迟在100毫秒内对校园场景来说绰绰有余。这里要多提一句合规问题。一个跳蚤市场交易平台不管规模大小该做的合规操作一样不能少用户实名注册手机号验证码校验必须有商品发布要做敏感词过滤违规内容条目要提前准备交易纠纷要有申诉机制和客服入口。我特别提醒了学弟平台方对发布违禁品的用户要及时警告和处理这些不是可选项而是必选项。隐私数据这块用户的手机号和地址在数据库里需要做加密存储日志打印也要脱敏处理。5.2 数据冷启动后的运营节奏系统刚上线的最初两周是冷启动期数据量自然是很贫乏的。这个阶段推荐系统的核心任务不是算法优化而是制造初始数据。我的做法是在正式运营前先导入一批模拟数据。用Python的Faker库生成模拟用户、模拟商品、模拟浏览和模拟购买记录大概构造成500个用户、2000件商品、3万条行为数据。这波操作对冷启动阶段的推荐系统至关重要——协同过滤算法的效果和输入数据的规模强相关没有这批模拟数据系统上线后运行一整周也未必能收集到足以支撑算法的数据量也就谈不上推荐效果。这些模拟数据的生成不是随机乱造的要符合跳蚤市场的业务规律。比如大四学生购买英语考研资料的记录相对集中大二学生浏览高数教材的记录多一些这样人为构造出几类标签清晰的用户群体协同过滤才有足够的行为交集可以计算推荐结果才能显得相对合理。6. 常见问题排查与避坑指南微服务权限管理系统是这几年非常经典的一套毕业设计选题但我见过太多人把它做成纯粹的CRUD后台那样反而显得没深度。我这套跳蚤市场系统的设计思路不一样它的加分项在于推荐算法的运用——不是给用户堆功能页面而是把底层算法和业务系统结合成一个整体。最近有学弟问这套系统能不能扩充成校园综合二手教学系统这个想法完全可以做把商品对象抽象成类型字段加上闲置教材、寻求辅导、寻找拼车伙伴这些业务场景就能复用现成框架。完成一个基础版本之后还可以继续优化算法参数调整、重构相似度计算、引入更细的行为权重策略等持续打磨细节比推倒重来做花哨的新功能要更值钱。复盘自己这几年做过的项目有推荐算法的价值感确实会高很多这类系统在面试考察中对项目深度的体现非常加分。最后分享一个排查问题的技巧。有用户反馈推荐列表刷不出来我的排查思路按这个顺序进行先看请求有没有打到后端是用浏览器开发者工具的Network面板看的再查Redis里有没有缓存数据用tkey的命令然后查数据库推荐结果表有没有数据最后看定时任务日志有没有正常执行。查了几次就发现是定时任务在数据量大的时候执行超时任务被跳过导致推荐结果表没有更新。解决方式是给定时任务加一个分布式锁同时把全量计算改成增量计算这个问题就彻底解决了。如果打开一篇文章到这里你正在为推荐系统相关的项目发愁这套思路和代码实现完全可以复用到你自己的业务场景里核心是掌握“数据预处理 - 相似度计算 - 推荐生成 - 兜底策略”这条主线逻辑剩下的都只是实现细节问题。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表