栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

基于redis分布式锁,解决定时任务重复执行问题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于redis分布式锁,解决定时任务重复执行问题

小编所在公司做的项目,大官人说要在项目中添加定时推送短信的功能,每周1推送一次,以便大官人可以不登录系统,知道还有什么紧急事情要处理。so接了任务,就得完成,所以我首先想到了使用定时任务+分布式锁来完成。定时任务定时发送短信,因为是集群部署,到时间点,每个服务器都要发送短信,怎么样只让一台服务器发送短信呢,所以要用到分布式锁,那台服务抢到锁,发送短信的任务就交给它。

背景交代清楚了,开始coding吧

第一步:写个定时任务

@Configuration //1.主要用于标记配置类,兼备Component的效果。
@EnableScheduling // 2.开启定时任务
public class SaticScheduleTask {
//3.添加定时任务
@Scheduled(cron = “0/5 * * * * ?”)
//或直接指定时间间隔,例如:5秒
//@Scheduled(fixedRate=5000)
private void configureTasks() {
System.err.println("执行静态定时任务时间: " + LocalDateTime.now());
}
}

第二步:写个分布式锁,小编使用set+lua脚本的方式,实现分布式锁。

@Slf4j
@RestController
@RequestMapping("/")
public class distributeLock {

@Autowired
private RedisTemplate redisTemplate;


@RequestMapping(value = "redisLock",method = RequestMethod.GET)
public String RedisLock(){
    // key是业务类型名称
    String key = "redisKey";
    // value是用来校验删除的是否是当前的线程的锁
    String value = UUID.randomUUID().toString();

    // 被回调函数,声明一个锁,作用是set一个值是否成功
    RedisCallback redisCallback = (connection)->{
 // nx,如果为false表示设置失败,为true表示该key未被设置过
 RedisStringCommands.SetOption setOption = RedisStringCommands.SetOption.ifAbsent();
 // 过期时间
 Expiration expiration = Expiration.seconds(30);
 byte[] keys = redisTemplate.getKeySerializer().serialize(key);
 byte[] values = redisTemplate.getValueSerializer().serialize(value);
 //set()来实现分布式锁
 Boolean result = connection.set(keys, values, expiration, setOption);
 return result;
    };

    // 执行set
    Boolean execute = (Boolean)redisTemplate.execute(redisCallback);
    if (execute){
 // 业务逻辑
 log.info("=====我获得了锁,进入了业务逻辑=====");
 try {
     Thread.sleep(1500);
 } catch (InterruptedException e) {
     e.printStackTrace();
 }finally {
     // 执行完毕业务之后,释放锁,使用lua脚本
     String lu = "if redis.call('get', KEYS[1]) == ARGV[1] n" +
      "    then n" +
      "t    return redis.call('del', KEYS[1]) n" +
      "t else n" +
      "t    return 0 n" +
      "end";
     // 执行lua脚本
     Redisscript redisscript = Redisscript.of(lu, Boolean.class);
     List keyss = Arrays.asList(key);
     Boolean bool = (Boolean)redisTemplate.execute(redisscript, keyss,value);

     log.info("释放锁的结果:"+bool);
 }
    }
    return null;
}

}

上面是个例子,仅供参考:

核心思想就是:多个服务器抢这把锁,谁抢到谁发送短信

原文链接:https://mp.weixin.qq.com/s/Esej0qMpZFSOPIwkdBg-lw

作者:一起写程序

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/237009.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号