• 使用redis分布式锁来解决集群项目的定时任务冲突问题


    //    @Scheduled(cron="0 */1 * * * ?")//(每隔1分钟的整数倍)
        public void closeOrderTaskV2(){
            System.out.println("关闭订单定时任务启动");
            long lockTimeout = 5000;//锁存在的时间 这个时间根据具体业务处理时间来设置
            
            Long setnxResult = RedisShardedPoolUtil.setnx(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTimeout));
            if(setnxResult != null && setnxResult.intValue() == 1){//如果返回值是1,代表设置成功,获取锁。假设程序执行到这里,此时关掉服务器 那么这里有可能出现死锁的问题
                RedisShardedPoolUtil.expire(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,5);//有效期5秒,防止死锁(这里的锁有效期,与上面的lockTimeout值必须统一)
                System.out.println("-----------业务方法开始---------");
                System.out.println("执行业务方法");
                System.out.println("-----------业务方法结束---------");
                RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);//业务方法执行完之后 手动将锁撤销
            }else{
                System.out.println("未获得分布式锁,锁名是:"+Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
            }
            System.out.println("关闭订单定时任务结束");
        }
    
        @Scheduled(cron="0 */1 * * * ?")//(每隔1分钟的整数倍)
        public void closeOrderTaskV3(){
            System.out.println("关闭订单定时任务启动");
            long lockTimeout = 5000;//锁存在的时间 这个时间根据具体业务处理时间来设置
            Long setnxResult = RedisShardedPoolUtil.setnx(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTimeout));
            if(setnxResult != null && setnxResult.intValue() == 1){
                RedisShardedPoolUtil.expire(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,5);//有效期5秒,防止死锁(这里的锁有效期,与上面的lockTimeout值必须统一)
                System.out.println("-----------业务方法开始---------");
                System.out.println("执行业务方法");
                System.out.println("-----------业务方法结束---------");
                RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
            }else{
                //未获取到锁,那么继续判断,判断时间戳与当前时间对比,看是否可以重置并获取到锁
                String lockValueStr = RedisShardedPoolUtil.get(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
                if(lockValueStr ==null||lockValueStr != null && System.currentTimeMillis() > Long.parseLong(lockValueStr)){//这种到老锁存在但是已经超时的情况一般是上面遇到的死锁情况
                    //设置新锁 并获取老锁的值,getset是一个原子性的方法
                    String getSetResult = RedisShardedPoolUtil.getSet(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTimeout));
                    if(getSetResult == null || (getSetResult != null && StringUtils.equals(lockValueStr,getSetResult))){//老锁消失 或者老锁过期并且老锁未被其他进程操作的情况下 有权利获取锁
                        //真正获取到锁
                        RedisShardedPoolUtil.expire(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,5);//有效期5秒,防止死锁
                        System.out.println("-----------业务方法开始---------");
                        System.out.println("执行业务方法");
                        System.out.println("-----------业务方法结束---------");
                        RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
                    }else{
                        System.out.println("没有获取到分布式锁");
                    }
                }else{
                    System.out.println("没有获取到分布式锁");
                }
            }
            System.out.println("关闭订单定时任务结束");
        }
  • 相关阅读:
    Laravel 手动分页实现
    大话Web-Audio-Api
    关于audio标签播放跨域的问题
    jquery的命名空间
    正则表达式的应用
    七天学会ASP.NET MVC (六)——线程问题、异常处理、自定义URL 【转】
    七天学会ASP.NET MVC (五)——Layout页面使用和用户角色管理 【转】
    七天学会ASP.NET MVC (四)——用户授权认证问题 【转】
    七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理 【转】
    七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 【转】
  • 原文地址:https://www.cnblogs.com/tjqBlog/p/10035462.html
Copyright © 2020-2023  润新知