Springboot 定时任务分布式下幂等性解决方案
一、概述:
在分布式环境下,定时任务的幂等性问题需要考虑多个节点之间的数据一致性和事务处理。
一种解决方法是使用分布式锁来保证同一时间只有一个节点能够执行该任务。具体实现可以使用Redis或Zookeeper等分布式协调工具提供的分布式锁功能。
另一种解决方法是使用消息队列来保证任务的幂等性。当一个节点执行任务时,先将任务发送到消息队列中,然后等待其他节点确认任务已经执行完毕后再进行后续操作。如果有节点出现故障或者网络异常导致任务未能成功执行,则可以重新发送任务并等待其他节点确认。
二、示例
如下图,有三台机器同时启动定时任务,将数据保存到Redis中,如何保证数据的幂等性?
解决方法–Redission分布式锁:
- 在启动定时任务时,获取分布式锁,保证只有一个线程进入
- 在获取锁之后,锁定10秒
- 然后执行业务
- 业务执行完成后,释放分布式锁
@Scheduled(cron = "*/10 * * * * ? ") public void uploadSeckillSkuLatest3Days() { // 重复上架无需处理 log.info("上架秒杀的商品..."); // 分布式锁(幂等性) RLock lock = redissonClient.getLock(SeckillConstant.UPLOAD_LOCK); try { lock.lock(10, TimeUnit.SECONDS); // 上架最近三天需要秒杀的商品 seckillService.uploadSeckillSkuLatest3Days(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } }
上架商品时,判断redis是否有该商品,没有才上架
Boolean hasKey = redisTemplate.hasKey(key); if (!hasKey) { }
全部代码
private void saveSessionInfos(List<SeckillSessionWithSkusTO> sessions) { if (!CollectionUtils.isEmpty(sessions)) { sessions.stream().forEach(session -> { // 1.遍历场次 long startTime = session.getStartTime().getTime();// 场次开始时间戳 long endTime = session.getEndTime().getTime();// 场次结束时间戳 String key = SeckillConstant.SESSION_CACHE_PREFIX + startTime + "_" + endTime;// 场次的key // 2.判断场次是否已上架(幂等性) Boolean hasKey = redisTemplate.hasKey(key); if (!hasKey) { // 未上架 // 3.封装场次信息 List<String> skuIds = session.getRelationSkus().stream() .map(item -> item.getPromotionSessionId() + "_" + item.getSkuId().toString()) .collect(Collectors.toList());// skuId集合 // 4.上架 redisTemplate.opsForList().leftPushAll(key, skuIds); } }); } }
到此这篇关于Springboot 定时任务分布式下幂等性如何解决的文章就介绍到这了,更多相关Springboot 幂等性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
SpringCloud客户端报错:- was unable to send&nb
这篇文章主要介绍了SpringCloud客户端报错:- was unable to send heartbeat!的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-05-05
最新评论