Spring:结合实训项目,利用Spring Schedule与Redis分布式锁实现分布式任务调度,包含Redisson框架

Spring Schedule与Redis分布式锁构建分布式任务调度

一、项目中使用的Redis分布式锁命令
1.1 setnx

setnx具有原子性,SET if Not eXists,在set的同时就开始判断是否已经存在

1.2 getset

先get后set,获取旧的值,设置新的值

1.3 expire

为 key设置过期时间

1.4 del

删除已创建的key

1.5 流程图

在这里插入图片描述

二、实现代码
2.1 RedisShardedPoolUtil添加setnx方法
    //setnx方法
    public static Long setnx(String key,String value){
   
        ShardedJedis jedis = null;
        Long result = null;
        try {
   
            jedis = RedisShardedPool.getJedis();
            result = jedis.setnx(key,value);
        } catch (Exception e) {
   
            log.error("setnx key:{} value:{} error",key,value,e);
            RedisShardedPool.returnBrokenResource(jedis);
            return result;
        }
        RedisShardedPool.returnResource(jedis);
        return result;
    }
2.2 在Const常量类中添加锁名字
    public interface REDIS_LOCK{
   
        String CLOSE_ORDER_TASK_LOCK = "CLOSE_ORDER_TASK_LOCK";
    }
2.3 propertise添加过期时间
    #closeOrderTaskTime start
    close.order.task.time.hour=2
    #毫秒数
    lock.timeout=50000
    #closeOrderTaskTime end
2.4 修改CloseOrderTask关闭订单方法

这里需要解决锁过期的问题,当获取锁成功后,进入closeOrder方法,设置锁的有效期,然后去操作订单,如果订单提前操作完成,则利用del删除锁以便快速释放锁

**存在问题:**在Tomcat集群中,如果Tomcat1获取到锁,刚准备调用closeOrder的时候被关闭了,则整个Tomcat集群都进入死锁状态,这时候可以利用kill方法,获取@Destory注解让tomcat关闭前调用此RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK)删除锁

    @Scheduled(cron = "0 */1 * * * ?")
    public void  closeOrderTaskV2(){
   
        log.info("关闭订单定时任务启动");
        //分布式锁锁5秒,设置5秒是为了测试用,生产环境不设置那么短时间
        long lockTimeout = Long.parseLong(PropertiesUtil.getProperty("lock.timeout","5000"));
        //配合时间戳
        Long setnxResult = RedisShardedPoolUtil.setnx(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTimeout));
        if(setnxResult != null && setnxResult.intValue()==1){
   
            //返回值为1,则代表成功获取锁
            closeOrder(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
        }else{
   
            log.info("没有获得分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
        }
        log.info("关闭订单定时任务结束");
    }

    //封装锁,设置锁的有效期,否则之后都是获取到setnxResult的0返回值
    private void closeOrder(String lockName){
   
        //设置key为50秒,防止死锁,过期后,锁便会释放
        RedisShardedPoolUtil.expire(lockName,50
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值