当前位置: 首页 > news >正文

推荐系统_runRetainRecommend_如何防止重复插入retain推荐数据表

你已经触及“推荐任务幂等性与重复推荐控制”的核心。

我们一步步看下 为什么会重复、怎么防、最佳实践是什么 👇


🧩 一、问题出现的原因

你的定时任务 runRetainRecommend()(每天执行) 会:

  1. 遍历所有活跃用户;

  2. 计算 retain 推荐结果;

  3. 批量插入到 recommend_log_location

如果任务中断(例如服务重启、数据库锁、网络异常),
下次再执行时就可能:

  • 重新计算了同一天的推荐;

  • 重复插入相同 (uuid, region_id, loc_uid, strategy_type) 组合。


⚙️ 二、典型“重复推荐”风险场景

场景结果
任务中断后重启同一个用户重复推荐相同场地
定时任务多实例并行多次执行相同逻辑
异常重试 / 手动补跑同样数据插入多次

✅ 三、最佳实践方案(推荐策略)

可以从三个层面控制:逻辑层 + 数据层 + 执行层


方案 1:逻辑层幂等控制(最推荐)

在插入 recommend_log_location 之前,
先判断当日是否已经存在相同推荐,若有则跳过或更新。

public void insertRetainRecommendations(Long userId, Long regionId, List<UserLocationBehaviorStatsDTO> rankedStats) {LocalDate today = LocalDate.now();for (UserLocationBehaviorStatsDTO stat : rankedStats) {boolean exists = recommendLogLocationMapper.existsRecommendForToday(userId, regionId, stat.getId(), "retain", today);if (!exists) {RecommendLogLocation rec = new RecommendLogLocation();rec.setUuid(userId);rec.setRegionId(regionId);rec.setLocUid(stat.getId());rec.setStrategyType("retain");rec.setRecommendScore(stat.getScore());rec.setRecommendedTs(LocalDateTime.now());rec.setIsInteracted(false);recommendLogLocationMapper.insert(rec);}}
}

对应 SQL(MyBatis):

<select id="existsRecommendForToday" resultType="boolean">SELECT COUNT(*) > 0FROM recommend_log_locationWHERE uuid = #{userId}AND region_id = #{regionId}AND loc_uid = #{locUid}AND strategy_type = #{strategyType}AND DATE(recommended_ts) = #{today}
</select>

📍特点

  • 简单易懂;

  • 幂等;

  • 可在失败重跑后自动去重。


方案 2:数据库层唯一索引防重

给表加一个唯一索引

ALTER TABLE recommend_log_location
ADD UNIQUE KEY uniq_user_loc_day (uuid, region_id, loc_uid, strategy_type, DATE(recommended_ts));

然后使用:

try {recommendLogLocationMapper.insert(rec);
} catch (DuplicateKeyException e) {// 已存在则忽略
}

📍特点

  • 强一致性;

  • 防止并发插入;

  • 不怕多实例并行。

📉缺点

  • MySQL 不支持函数索引中的 DATE(),需要在表中额外添加一列 recommend_date(日期字段):

    ALTER TABLE recommend_log_location ADD COLUMN recommend_date DATE GENERATED ALWAYS AS (DATE(recommended_ts)) STORED;
    ALTER TABLE recommend_log_location ADD UNIQUE KEY uniq_user_loc_day (uuid, region_id, loc_uid, strategy_type, recommend_date);
    

方案 3:执行层锁 / 状态标识控制

在任务开始时:

  • 记录任务执行状态(如 Redis key 或数据库任务表);

  • 如果同日期已有“成功执行”记录,则跳过;

  • 如果中断,可重新执行未完成的部分。

例:

if (redisTemplate.hasKey("retain_task:" + LocalDate.now())) {return; // 已执行
}
redisTemplate.opsForValue().set("retain_task:" + LocalDate.now(), "running", 2, TimeUnit.HOURS);

📍特点

  • 防止同一时刻多实例并行;

  • 可用于分布式环境(微服务架构)。


🧠 四、推荐组合策略(最佳实践)

层级推荐做法
逻辑层查询是否已有推荐记录,幂等插入
数据层添加 recommend_date + 唯一约束
执行层Redis / DB 锁防并发执行
重跑机制可安全重试,已有数据自动跳过

🧩 五、可选优化

  • 记录任务表 recommend_task_log,存放任务日期、执行时间、状态(成功/失败),便于重跑;

  • 若使用批量插入,可通过 INSERT IGNOREON DUPLICATE KEY UPDATE 避免重复。


💬 总结一句话:

“推荐任务”必须具备幂等性,最佳实践是 ——
逻辑层先查是否存在 + 数据层唯一约束 + 执行层分布式锁。

http://www.dtcms.com/a/579407.html

相关文章:

  • 托管网站服务器怎么弄自己的微信公众号
  • 国外代码开源网站站长之家网页模板下载
  • 建设电影网站点击播放是乱页的新城疫怎么治疗
  • 邯郸有设计网站的吗什么网站ghost做的好
  • 东莞专业做网站建设服务软件科技开发公司
  • 产品销售网站模板网站排名软件包年
  • 网站栏目怎么濮阳自适应网站建设
  • 娱乐网站建设公司排名网站做搜索关键字好吗
  • 地图可视化实践录:leaflet学习之右键菜单
  • 网站关键词优化教程上海高端网站建设服
  • 视频弹幕网站怎么做建设牌官方网站
  • arduino烧录esp32问题
  • 生产环境 cpu 飙高,如何排查
  • 网站建设技术是干嘛的网站建立步骤
  • 智能建站模版国内专业建站平台
  • app会替代网站吗建设营销型网站的原因
  • 深圳建站哪家专业建网站自己做服务器
  • 建购物网站需要多少钱建设银行网站怎么短信转账
  • 西安长安区网站优化地址网站布局英文
  • Linux实用操作
  • 网站域名免费注册深圳宝安房价
  • 如何搜索网站微信公众号平台登陆
  • 销售外包团队搜索关键词排名优化技术
  • 常见网站推广方式莱芜吧重汽怎么样
  • 网站维护怎么学视频制作软件手机版
  • 怎么看到网站开发时间永嘉高端网站建设效果
  • 怎么建一个网站卖东西咸宁有做网站的吗
  • 抚州做网站wordpress菜单页面未找到
  • 注册域名的网站有哪些有没有网站
  • 上海做网站的小公司有哪些网站接入支付宝需要网站备案吗