zoukankan      html  css  js  c++  java
  • spring cloud 用redis做分布式锁(解决分布式多节点情况下,定时任务多次执行)

     我们知道现在微服务很流行,为此,许多中小型企业都将自己以前的框架加以改造,其中以SpringCloud为最多,但是SpringCloud如果要加定时任务的话,在单台服务器上很好支持,

    但是涉及到集群服务(多台服务的话)就要用到分布式锁了,最简单的方案是用Redis,好了废话不多说,直接上代码.

    1、分布式锁

    /**
     * 分布式锁
     * 
     *
     */
    @Component
    public class DistributedLockHandler {
    
       private static final Logger logger = LoggerFactory.getLogger(DistributedLockHandler.class);
    
       /**
        * 最大持有锁的时间(毫秒)
        */
       private final static long LOCK_EXPIRE = 30 * 1000L;
    
       /**
        * 尝试获取锁的时间间隔(毫秒)
        */
       private final static long LOCK_TRY_INTERVAL = 30L;
    
       /**
        * 获取锁最大等待时间( 毫秒 )
        */
       private final static long LOCK_TRY_TIMEOUT = 20 * 1000L;
    
       @Resource(name = "customRedisTemplate")
       private RedisTemplate<String, String> template;
    
       /**
        * 尝试获取 分布式锁
        * 
        * @param lockKey
        *            锁名
        * @return true 得到了锁 ,false 获取锁失败
        */
       public boolean tryLock(String lockKey) {
          return getLock(lockKey, LOCK_TRY_TIMEOUT, LOCK_TRY_INTERVAL, LOCK_TRY_INTERVAL);
       }
    
       /**
        * 尝试获取 分布式锁(不自动释放锁)
        * 
        * @param lockKey
        *            锁名
        * @return true 得到了锁 ,false 获取锁失败
        */
       public boolean tryLockNotAutoRelease(String lockKey) {
          return getLock(lockKey, LOCK_TRY_TIMEOUT, LOCK_TRY_INTERVAL, -1);
       }
    
       /**
        * 尝试获取 分布式锁
        * 
        * @param lockKey
        *            锁名
        * @param timeout
        *            获取锁最大等待时间
        * @return true 得到了锁 ,false 获取锁失败
        */
       public boolean tryLock(String lockKey, long timeout) {
          return getLock(lockKey, timeout, LOCK_TRY_INTERVAL, LOCK_EXPIRE);
       }
    
       /**
        * 尝试获取 分布式锁(不自动释放锁)
        * 
        * @param lockKey
        *            锁名
        * @param timeout
        *            获取锁最大等待时间
        * @return true 得到了锁 ,false 获取锁失败
        */
       public boolean tryLockNotAutoRelease(String lockKey, long timeout) {
          return getLock(lockKey, timeout, LOCK_TRY_INTERVAL, -1);
       }
    
       /**
        * 尝试获取 分布式锁
        * 
        * @param lockKey
        *            锁名
        * @param timeout
        *            获取锁最大等待时间
        * @param tryInterval
        *            获取锁尝试 时间间隔
        * @return true 得到了锁 ,false 获取锁失败
        */
       public boolean tryLock(String lockKey, long timeout, long tryInterval) {
          return getLock(lockKey, timeout, tryInterval, LOCK_EXPIRE);
       }
    
       /**
        * 尝试获取 分布式锁(不释放锁)
        * 
        * @param lockKey
        *            锁名
        * @param timeout
        *            获取锁最大等待时间
        * @param tryInterval
        *            获取锁尝试 时间间隔
        * @return true 得到了锁 ,false 获取锁失败
        */
       public boolean tryLockNotAutoRelease(String lockKey, long timeout, long tryInterval) {
          return getLock(lockKey, timeout, tryInterval, -1);
       }
    
       /**
        * 尝试获取 分布式锁
        * 
        * @param lockKey
        *            锁名
        * @param timeout
        *            获取锁最大等待时间
        * @param tryInterval
        *            获取锁尝试 时间间隔
        * @param lockExpireTime
        *            锁最大持有时间
        * @return true 得到了锁 ,false 获取锁失败
        */
       public boolean tryLock(String lockKey, long timeout, long tryInterval, long lockExpireTime) {
          return getLock(lockKey, timeout, tryInterval, lockExpireTime);
       }
    
       /**
        * 获取分布式锁
        * 
        * @param lockKey
        *            锁名
        * @param timeout
        *            获取锁最大等待时间
        * @param tryInterval
        *            获取锁尝试 时间间隔
        * @param lockExpireTime
        *            锁最大持有时间
        * @return true 得到了锁 ,false 获取锁失败
        */
       public boolean getLock(String lockKey, long timeout, long tryInterval, long lockExpireTime) {
          try {
             if (StringUtils.isEmpty(lockKey)) {
                return false;
             }
             long startTime = System.currentTimeMillis();
             do {
                ValueOperations<String, String> ops = template.opsForValue();
                if (ops.setIfAbsent(lockKey, "lockValue")) {
                   if (lockExpireTime > 0) {
                      template.expire(lockKey, lockExpireTime, TimeUnit.MILLISECONDS);
                   }
                   return true;
                }
                Thread.sleep(tryInterval);
             } while (System.currentTimeMillis() - startTime < timeout);
          } catch (InterruptedException e) {
             logger.error(e.getMessage());
             return false;
          }
          return false;
       }
    
       /**
        * 释放锁
        * 
        * @param lockKey
        */
       public void unLock(String lockKey) {
          if (!StringUtils.isEmpty(lockKey)) {
             template.delete(lockKey);
          }
       }
    
    }

    2、 在定时任务中使用

    @Component
    public class AutoComfirmReceied {
       private static final Logger logger = LoggerFactory.getLogger(AutoComfirmReceied.class);
    
       @Resource
       OrderService orderService;
       
       @Resource
       OrderItemMapper orderItemMapper;
       
       @Autowired
       DistributedLockHandler distributedLockHandler;
       
       @Scheduled(cron = "${cron.autoComfirmReceied}")
       public void run() {
          String lockKey = RedisKeyResolver.getLockkey( "AutoComfirmReceied:run" );;
          
          if( distributedLockHandler.tryLockNotAutoRelease( lockKey ) ) {
             try {
                runTask();
             } catch (Exception e) {
                e.printStackTrace();
             }finally {
                distributedLockHandler.unLock( lockKey );
             }
          }else {
             if( logger.isDebugEnabled() ) {
                logger.debug("没有获取锁超时..............");
             }
          }
          
       }
    
       
        private void runTask() {
          logger.info("3分钟执行一次定时任务" + System.currentTimeMillis());
          List<String> orderItemReturnStatus = new ArrayList<>();
          orderItemReturnStatus.add(OrderItemReturnStatus.WTH.name());
          orderItemReturnStatus.add(OrderItemReturnStatus.YJJ.name());
          orderItemReturnStatus.add(OrderItemReturnStatus.YQX.name());
    
          OrderItemExample orderItemExample = new OrderItemExample();
          OrderItemExample.Criteria oderc = orderItemExample.createCriteria();
          oderc.andIsDelEqualTo(false)
                .andOrderStatusEqualTo(OrderItemStatus.SENDED.name())
                .andReturnStatusIn(orderItemReturnStatus)
                .andShippingStatusEqualTo(OrderItemShippingStatus.YFH.name());
    
    
          List<OrderItem> orderItemList = orderItemMapper.selectByExample(orderItemExample);
          Set<String> set = new HashSet<>();
          for (OrderItem orderItem : orderItemList) {
             Long sendTime10 = AutoConfirmReceivedDateUtil.getAdd10Day(orderItem.getSendDate(), 10);
             Long currentTime = new Date().getTime();
             if(currentTime > sendTime10){ //当前时间大于,发货后10天的时间,则确认收货
                set.add(orderItem.getLogisticsId() + "," + orderItem.getUserId());
             }
          }
    
          if(!set.isEmpty()){
             for (String orderItem : set) {
                String[] item = orderItem.split(",");
                StringBuffer stringBuffer = new StringBuffer();
                stringBuffer.append("超过10天自动确认收货,logisticsId:" + item[0] + ",userId:" + item[1]);
                orderService.confirmReceive(Long.valueOf(item[0]), Long.valueOf(item[1]));
                stringBuffer.append(",成功!");
                logger.info(stringBuffer.toString());
    
             }
          }
       }
    }
  • 相关阅读:
    Jessica's Reading Problem POJ
    FatMouse and Cheese HDU
    How many ways HDU
    Humble Numbers HDU
    Doing Homework again
    Stacks of Flapjacks UVA
    Party Games UVA
    24. 两两交换链表中的节点
    面试题 03.04. 化栈为队
    999. 可以被一步捕获的棋子数
  • 原文地址:https://www.cnblogs.com/longyao/p/11719931.html
Copyright © 2011-2022 走看看