• 【笔记8-Redis分布式锁】从0开始 独立完成企业级Java电商网站开发(服务端)


    Redis分布式锁

    Redis分布式锁命令

    • setnx当且仅当 key 不存在。若给定的 key 已经存在,则 setnx不做任何动作。setnx 是『set if not exists』(如果不存在,则 set)的简写,setnx 具有原子性。

    • getset先 get 旧值,后set 新值,并返回 key 的旧值(old value),具有原子性。当 key 存在但不是字符串类型时,返回一个错误;当key 不存在的时候,返回nil ,在Java里就是 null。

    • expire 设置 key 的有效期

    • del 删除 key

    Redis分布式锁流程图

    file

    Redis分布式锁优化版流程图

    file

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

    @Component
    
    @Slf4j
    
    public class CloseOrderTask {
    
    private static final Loggerlog = LoggerFactory.getLogger(CloseOrderTask.class);
    
        @Autowired
    
        private IOrderServiceiOrderService;
    
        @PreDestroy  // 关闭Tomcat之前执行删除锁,避免死锁
    
        public void delLock(){
    
    RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
    
        }
    
    // @Scheduled(cron = "0 */1 * * * ?")//每一分钟(每个一分钟的整数倍)
    
        public void closeOrderTaskV1(){
    
    int hour=Integer.parseInt(PropertiesUtil.getProperty("close.order.task.time.hour","2"));
    
            log.info("关闭订单定时任务启动");
    
            iOrderService.closeorder(hour);
    
            log.info("关闭订单定时任务结束");
    
        }
    
    //  @Scheduled(cron = "0 */1 * * * ?")//每一分钟(每个一分钟的整数倍)
    
        public void closeOrderTaskV2(){
    
    log.info("关闭订单定时任务启动");
    
            // 锁超时时间
    
            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("关闭订单定时任务结束");
    
        }
    
    @Scheduled(cron ="0 */1 * * * ?")//每一分钟(每个一分钟的整数倍)
    
        public void closeOrderTaskV3(){
    
            log.info("关闭订单定时任务启动");
    
            //锁超时时间
    
            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{
    
               //未获取到锁,继续判断,判断时间戳,看是否可以重置并获取到锁
    
                String lockValueStr=RedisShardedPoolUtil.get(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
    
                if(lockValueStr!=null&&System.currentTimeMillis()>Long.parseLong(lockValueStr)){
    
    String getSetResult=RedisShardedPoolUtil.getSet(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,String.valueOf(System.currentTimeMillis()+lockTimeout));
    
                    //再次用当前时间戳getset
    
                   //返回给定的key的旧值,-》旧值判断,是否可以获取锁
    
                   //当key没有旧值时,即key不存在时,返回nil->获取锁
    
                   //这里我们set了一个新的value值,获取旧的值
    
                    if(getSetResult==null||(getSetResult!=null&& StringUtils.equals(lockValueStr,getSetResult))){
    
                        //真正获取到锁
    
                        closeOrder(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
    
                    }else{
    
                        log.info("没有获取到分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
    
                    }
    
         }else{
    
                   log.info("没有获取到分布式锁:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
    
                }
    
    }
    
         log.info("关闭订单定时任务结束");
    
        }
    
    private void closeOrder(String lockName){
    
         RedisShardedPoolUtil.expire(lockName,50);//有效期5秒,防止死锁
    
            log.info("获取{} ,ThreadName:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,Thread.currentThread().getName());
    
            int hour=Integer.parseInt(PropertiesUtil.getProperty("close.order.task.time.hour","2"));
    
          //  iOrderService.closeorder(hour);
    
            RedisShardedPoolUtil.del(Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK);
    
            log.info("释放{} ,ThreadName:{}",Const.REDIS_LOCK.CLOSE_ORDER_TASK_LOCK,Thread.currentThread().getName());
    
            log.info("============================");
    
        }
    
    }
    

    Tomcat集群快速入门

    Nginx负载均衡配置、常用策略、场景及特点

    • 轮询(默认)

    file

    • 权重

    file

    • ip hash

    file

    • url hash(第三方)

    file

    • fail(第三方)

    file

    Nginx+Tomcat搭建集群

    https://blog.csdn.net/Leon_Jinhai_Sun/article/details/97640796

    Tomcat集群快速入门

    https://blog.csdn.net/Leon_Jinhai_Sun/article/details/97624274

    https://blog.csdn.net/Leon_Jinhai_Sun/article/details/97631761

    参考:

    https://www.jianshu.com/p/ca88c1f86069

    https://blog.csdn.net/qq_20057315/article/details/81624821

  • 相关阅读:
    vue3:jsbarcode生成条形码
    xml文件中<![CDATA[]]>和转义字符的使用
    VUE:计算属性
    BUG:JSONObject转实体类时空字符串变成19700101
    类与对象、封装、构造方法(成员变量与局部变量的区别)
    第四课rgb
    c++获取文件字符串
    cximage第一讲demo.cpp
    OPENGL第二课(正弦函数,点,线 圆,五角星)
    cv::flip
  • 原文地址:https://www.cnblogs.com/chen-chen-chen/p/12295290.html
Copyright © 2020-2023  润新知