定时器+redis分布式锁、定时器+redisson框架分布式锁

xiaoxiao2025-09-12  310

定时器+redis分布式锁

 

在xml中添加:

<task:annotation-driven/>

 

1. 不带锁的定时器:

 

 

2. 带redis分布式锁的定时器:

原理:设置锁的lokkey,值为当前毫秒值+超时毫秒值,redis的setnx方法为,如果不存在lokkey,返回1并设置lokkey,返回0,代表已存在锁

 

代码

 

 

 

3.上面的方法虽然好,但是如果在设置锁的有效期之前,tomcat异常关闭,比如:杀死tomcat进程,在redis中已经存在锁,这种情况会出现死锁,所以需要进行改进

 

优化版:设置锁的lokkey,值为当前毫秒值+超时毫秒值,redis的setnx方法为,如果不存在lokkey,返回1并设置lokkey,返回0,代表已存在锁

返回0时,判断当前时间是否为空&&是否 > redis的value值 lockvalueA

{

不为空且大于:使用getset方法,设置值为当前毫秒+超时毫秒,返回旧值 lockvalueB,判断lockvalueB是否为空 || (lockvalueB不为空且lockvalueA==lockvalueB)

    {

         lockvalueB为空:代表走到这一步,别的tomcat已经执行了一遍代码并且释放了锁

         lockvalueB不为空且lockvalueA==lockvalueB:代表开启定时后第一次执行此代码

         lockvalueA != lockvalueB:代表别的tomcat已经在执行此代码,并且锁还未被释放

    }

不为空且小于:结束

为空:结束

}

 

 

代码

@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){ 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("关闭订单定时任务结束"); }

 

 

 

 

定时器+redisson框架分布式锁

 

使用这个方法代码会简单很多

在pom.xml中添加:

<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-avro</artifactId> <version>2.9.0</version> </dependency>

 

 

RedissonManager类

@Component @Slf4j public class RedissonManager { private Config config = new Config(); private Redisson redisson = null; public Redisson getRedisson() { return redisson; } private static String redis1Ip = PropertiesUtil.getProperty("redis1.ip"); private static Integer redis1Port = Integer.parseInt(PropertiesUtil.getProperty("redis1.port")); private static String redis2Ip = PropertiesUtil.getProperty("redis2.ip"); private static Integer redis2Port = Integer.parseInt(PropertiesUtil.getProperty("redis2.port")); @PostConstruct private void init(){ try { config.useSingleServer().setAddress(new StringBuilder().append(redis1Ip).append(":").append(redis1Port).toString()); redisson = (Redisson) Redisson.create(config); log.info("初始化Redisson结束"); } catch (Exception e) { log.error("redisson init error",e); } } }

 

 

转载请注明原文地址: https://www.6miu.com/read-5036204.html

最新回复(0)