Redis 分布式锁 解决集群环境下多次定时任务执行
1、设置分布式锁
/** * 设置redis 分布式锁 * @param lockName * @param acquireTimeout * @param lockTimeout * @return */ public String acquireDistributedLockWithTimeout(String lockName, long acquireTimeout, int lockTimeout) { String lockValue = UUID.randomUUID().toString(); String lockKey = "lock:" + lockName; long acquireTime = System.currentTimeMillis() + acquireTimeout; ValueOperations ops = this.redisTemplate.opsForValue(); while(acquireTime > System.currentTimeMillis()) { boolean locked = ops.setIfAbsent(lockKey, lockValue); if (locked) { this.redisTemplate.expire(lockKey, (long)lockTimeout, TimeUnit.SECONDS); return lockValue; } try { TimeUnit.MILLISECONDS.sleep(1L); } catch (InterruptedException var12) { Thread.currentThread().interrupt(); } } return null; }
2、释放redis分布式锁
/** * 释放redis锁 * @param lockName * @param lockValue * @return */ public boolean releaseDistributedLock(String lockName, String lockValue) { String lockKey = "lock:" + lockName; List<Object> result = null; ValueOperations ops = this.redisTemplate.opsForValue(); do { this.redisTemplate.watch(lockKey); if (!Objects.equal(lockValue, ops.get(lockKey))) { break; } this.redisTemplate.delete(lockKey); } while(result == null); this.redisTemplate.unwatch(); return true; }
3、定时逻辑
//集群环境 定时任务加锁,保证执行一次 异常情况6个小时 释放锁 String lock = redisService.acquireDistributedLockWithTimeout("incomeStatistics", 10, 60*60*6); //判断是否获得锁 if(StringUtils.isNotBlank(lock)){ logger.info("定时任务 开始执行"); try{ //业务逻辑 }catch (Exception e){ //异常处理 } finally { //释放锁 redisService.releaseDistributedLock("incomeStatistics",lock); } }