添加分布式部署定时任务
This commit is contained in:
+57
@@ -0,0 +1,57 @@
|
|||||||
|
package com.jero.common.aspect;
|
||||||
|
|
||||||
|
import com.jero.common.aspect.annotation.RedisLock;
|
||||||
|
import com.jero.common.exception.JeroBootException;
|
||||||
|
import com.jero.common.util.RedisLockHelper;
|
||||||
|
import com.jero.common.util.RedisUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分布式部署定时任务
|
||||||
|
* @Author lqt
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
public class LockMethodAspect {
|
||||||
|
@Resource
|
||||||
|
private RedisLockHelper redisLockHelper;
|
||||||
|
@Resource
|
||||||
|
private RedisUtil redisUtis;
|
||||||
|
|
||||||
|
@Around("@annotation(com.jero.common.aspect.annotation.RedisLock)")
|
||||||
|
public Object around(ProceedingJoinPoint joinPoint) {
|
||||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
|
Method method = signature.getMethod();
|
||||||
|
RedisLock redisLock = method.getAnnotation(RedisLock.class);
|
||||||
|
String value = UUID.randomUUID().toString();
|
||||||
|
log.info("====value=====" + value + "===========");
|
||||||
|
String key = redisLock.key();
|
||||||
|
log.info("====key======" + key + "===========");
|
||||||
|
try {
|
||||||
|
final boolean islock = redisLockHelper.lock(redisUtis, key, value, redisLock.expire(), redisLock.timeUnit());
|
||||||
|
log.info("isLock : {}", islock);
|
||||||
|
if (!islock) {
|
||||||
|
log.error("获取锁失败");
|
||||||
|
throw new JeroBootException("获取锁失败");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return joinPoint.proceed();
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
throw new JeroBootException("系统异常");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
log.info("释放锁");
|
||||||
|
redisLockHelper.unlock(redisUtis, key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package com.jero.common.aspect.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
/**
|
||||||
|
* @author LQT
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
public @interface RedisLock {
|
||||||
|
/*** 业务键** @return*/
|
||||||
|
String key();
|
||||||
|
|
||||||
|
/*** 锁的过期秒数,默认是5秒** @return*/
|
||||||
|
int expire() default 5;
|
||||||
|
|
||||||
|
/*** 尝试加锁,最多等待时间** @return*/
|
||||||
|
long waitTime() default Long.MIN_VALUE;
|
||||||
|
|
||||||
|
/*** 锁的超时时间单位** @return*/
|
||||||
|
TimeUnit timeUnit() default TimeUnit.SECONDS;
|
||||||
|
}
|
||||||
+116
@@ -0,0 +1,116 @@
|
|||||||
|
package com.jero.common.util;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||||
|
import org.springframework.data.redis.core.script.RedisScript;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class RedisLockHelper {
|
||||||
|
|
||||||
|
private long sleepTime = 100;
|
||||||
|
/**
|
||||||
|
* 直接使用setnx + expire方式获取分布式锁
|
||||||
|
* 非原子性
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
* @param timeout
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean lockSetNx(RedisUtil redisTemplate, String key, String value, int timeout) {
|
||||||
|
if ( redisTemplate.setnx(key, value)) {
|
||||||
|
return redisTemplate.expire(key, timeout);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用Lua脚本,脚本中使用setnex+expire命令进行加锁操作
|
||||||
|
*
|
||||||
|
* @param redisTemplate
|
||||||
|
* @param key
|
||||||
|
* @param uniqueId
|
||||||
|
* @param seconds
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean lockWithLua(RedisUtil redisTemplate, String key, String uniqueId, int seconds) {
|
||||||
|
if(!Objects.isNull(seconds)){
|
||||||
|
log.info("未使用参数:" + seconds);
|
||||||
|
}
|
||||||
|
String luaScript = "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then" +
|
||||||
|
"redis.call('expire',KEYS[1],ARGV[2]) return 1 else return 0 end";
|
||||||
|
Object result = redisTemplate.eval(RedisScript.of(luaScript), Collections.singletonList(key), uniqueId);
|
||||||
|
//判断是否成功
|
||||||
|
return result.equals(1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在Redis的2.6.12及以后中,使用 set key value [NX] [EX] 命令
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
* @param timeout
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean lock(RedisUtil redisTemplate, String key, String value, int timeout, TimeUnit timeUnit) {
|
||||||
|
long seconds = timeUnit.toSeconds(timeout);
|
||||||
|
return redisTemplate.setnx(key, value, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义获取锁的超时时间
|
||||||
|
*
|
||||||
|
* @param redisTemplate
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
* @param timeout
|
||||||
|
* @param waitTime
|
||||||
|
* @param timeUnit
|
||||||
|
* @return
|
||||||
|
* @throws InterruptedException
|
||||||
|
*/
|
||||||
|
public boolean lockWithWaitTime(RedisUtil redisTemplate, String key, String value, int timeout, long waitTime, TimeUnit timeUnit) throws InterruptedException {
|
||||||
|
long seconds = timeUnit.toSeconds(timeout);
|
||||||
|
while (waitTime >= 0) {
|
||||||
|
if (redisTemplate.setnx(key, value, seconds)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
waitTime -= sleepTime;
|
||||||
|
Thread.sleep(sleepTime);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 错误的解锁方法—直接删除key
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
public void unlockWithDel(RedisUtil redisTemplate, String key) {
|
||||||
|
redisTemplate.del(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用Lua脚本进行解锁操纵,解锁的时候验证value值
|
||||||
|
*
|
||||||
|
* @param redisTemplate
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean unlock(RedisUtil redisTemplate, String key, String value) {
|
||||||
|
String luaScript = "if redis.call('get',KEYS[1]) == ARGV[1] then " +
|
||||||
|
"return redis.call('del',KEYS[1]) else return 0 end";
|
||||||
|
DefaultRedisScript<Long> redisScript =new DefaultRedisScript<> ();
|
||||||
|
redisScript.setScriptText(luaScript);
|
||||||
|
// 这个值类型要跟lua返回值类型一致才行,否则就会报 java.lang.IllegalStateException
|
||||||
|
redisScript.setResultType(Long.class);
|
||||||
|
return redisTemplate.eval(redisScript, Collections.singletonList(key), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
+35
@@ -1,10 +1,12 @@
|
|||||||
package com.jero.common.util;
|
package com.jero.common.util;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.*;
|
import org.springframework.data.redis.core.*;
|
||||||
|
import org.springframework.data.redis.core.script.RedisScript;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
@@ -609,4 +611,37 @@ public class RedisUtil {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setnx
|
||||||
|
*/
|
||||||
|
public boolean setnx(String key, String value) {
|
||||||
|
try {
|
||||||
|
return redisTemplate.opsForValue().setIfAbsent(key, value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setnx
|
||||||
|
*/
|
||||||
|
public boolean setnx(String key, String value,long time) {
|
||||||
|
try {
|
||||||
|
return redisTemplate.opsForValue().setIfAbsent(key,value, Duration.ofSeconds(time));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eval
|
||||||
|
*/
|
||||||
|
public Boolean eval(RedisScript<Long> luaScripts, List<String> keys, String values) {
|
||||||
|
Long flag = redisTemplate.execute(luaScripts, keys, values);
|
||||||
|
//判断是不是为1
|
||||||
|
return flag == 1L;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -1,12 +1,16 @@
|
|||||||
package com.jero.modules.quartz.job;
|
package com.jero.modules.quartz.job;
|
||||||
|
|
||||||
|
import com.jero.common.aspect.annotation.RedisLock;
|
||||||
import com.jero.common.util.DateUtils;
|
import com.jero.common.util.DateUtils;
|
||||||
|
import org.quartz.DisallowConcurrentExecution;
|
||||||
import org.quartz.Job;
|
import org.quartz.Job;
|
||||||
import org.quartz.JobExecutionContext;
|
import org.quartz.JobExecutionContext;
|
||||||
import org.quartz.JobExecutionException;
|
import org.quartz.JobExecutionException;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 示例带参定时任务
|
* 示例带参定时任务
|
||||||
*
|
*
|
||||||
@@ -25,6 +29,7 @@ public class SampleParamJob implements Job {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@RedisLock(key = "lock----TestJob",expire=60,timeUnit= TimeUnit.SECONDS)
|
||||||
public void execute(JobExecutionContext jobExecutionContext) {
|
public void execute(JobExecutionContext jobExecutionContext) {
|
||||||
log.info(" Job Execution key:"+jobExecutionContext.getJobDetail().getKey());
|
log.info(" Job Execution key:"+jobExecutionContext.getJobDetail().getKey());
|
||||||
log.info("welcome " + this.parameter + " Jero-Boot 带参数定时任务 SampleParamJob ! 时间:" + DateUtils.now());
|
log.info("welcome " + this.parameter + " Jero-Boot 带参数定时任务 SampleParamJob ! 时间:" + DateUtils.now());
|
||||||
|
|||||||
Reference in New Issue
Block a user