文章目录
- 前言
- 一、redis
- 二、Redisson
- 1.引入库
- 2. 分布式锁
- 3. 锁自动续期
- 总结
前言
上篇文章介绍了Java中锁的应用,在SpringBoot单体应用中完全够用,但是SpringCloud微服务集群中就力所不及了。
我的使用场景是某些微服务应用中使用spring注解的形式来完成定时任务的功能,服务集群之后每台服务器都会调起定时任务,这和预想的不一样,需要添加分布式锁来控制任务的执行,推荐大家使用quartz和xxl-job来完成定时任务的调度。
一、redis
redis的使用我就不过多介绍了,前面文章写了好几篇了,可以自行爬楼翻看。
@Service
public class StudentService {private static final Logger log = LoggerFactory.getLogger(StudentService.class);@AutowiredStringRedisTemplate stringRedisTemplate;@Value("${server.port}")private String port;@Scheduled(cron = "0 0/1 6-23 * * ?")public void execute(){ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();String key="student-"+ DateUtils.format(new Date(),"yyyyMMdd");String value = RandomUtil.randomNumbers(6);long timeout=24 * 60 * 60;Boolean absent = operations.setIfAbsent(key, value, timeout, TimeUnit.SECONDS);log.debug(port+"获取锁:"+absent);try {//todo 业务处理if(absent){Thread.sleep(1000);}} catch (InterruptedException e) {e.printStackTrace();}finally {if(value.equals(operations.get(key))){stringRedisTemplate.delete(key);log.debug(port+"执行完成,解除锁");}}}
}
定时任务集群要保证服务器时间一致,否则每次执行都可能跑到时间较为靠前的那台服务器上
二、Redisson
1.引入库
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.23.0</version>
</dependency>
2. 分布式锁
@Service
public class StudentService {private static final Logger log = LoggerFactory.getLogger(StudentService.class);@Value("${server.port}")private String port;@Autowiredprivate RedissonClient redissonClient;@Scheduled(cron = "0 0/1 6-23 * * ?")public void redisson(){String key="student-"+ DateUtils.format(new Date(),"yyyyMMdd");long timeout=24 * 60 * 60;RLock lock = redissonClient.getLock(key);boolean tryLock=false;try {tryLock = lock.tryLock();log.debug(port+"获取锁["+key+"]:"+tryLock);if(tryLock){lock.lock(timeout, TimeUnit.SECONDS);//锁到期自动解锁//todo 业务处理Thread.sleep(10000);}} catch (Exception e) {e.printStackTrace();}finally {if(tryLock&&lock.isHeldByCurrentThread()){lock.unlock();log.debug(port+"执行完成,解除锁["+key+"]");}}}
}
3. 锁自动续期
@Service
public class StudentService {private static final Logger log = LoggerFactory.getLogger(StudentService.class);@Value("${server.port}")private String port;@Autowiredprivate RedissonClient redissonClient;@Scheduled(cron = "0 0/1 6-23 * * ?")public void redissonRenewal(){String key="student-"+ DateUtils.format(new Date(),"yyyyMMdd");long time=10;RLock lock = redissonClient.getLock(key);boolean tryLock=false;try {tryLock = lock.tryLock(time,TimeUnit.SECONDS);log.debug(port+"获取锁["+key+"]:"+tryLock);if(tryLock){log.debug(port+"锁["+key+"]剩余生存时间为:"+(lock.remainTimeToLive()/1000)+"秒");lock.lock();//todo 业务处理Thread.sleep(40000);log.debug(port+"锁["+key+"]剩余生存时间为:"+(lock.remainTimeToLive()/1000)+"秒");}} catch (Exception e) {e.printStackTrace();}finally {if(tryLock&&lock.isHeldByCurrentThread()){lock.unlock();log.debug(port+"执行完成,解除锁["+key+"]");}}}
}
总结
回到顶部
Redisson
redisson-spring-boot-starter