在看代码之前请先看优化篇:基于Redis的Setnx实现分布式锁_p&f°的博客-CSDN博客
1、在启动了上加 @EnableScheduling 注解
@SpringBootApplication
@MapperScan("com.xpf.distributelock.dao")
@EnableScheduling
public class DistributeLockApplication {
public static void main(String[] args) {
SpringApplication.run(DistributeLockApplication.class, args);
}
}
2、 写一个server类
import com.xpf.distributelock.until.RedisLock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
/**
* @auther xpf
* @date 2022/6/10 21:24
* @description 定时任务
*/
@Slf4j
@Service
public class SchedulerService {
@Autowired
private RedisTemplate redisTemplate;
@Scheduled(cron = "0/5 * * * * ?")
public void sendSms(){
try(RedisLock redisLock = new RedisLock("autoSms", 30, redisTemplate)){
if(redisLock.getLock()){
log.info("向我开炮。。。。🤺");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
以防急用,没看前一篇文章,把 RedisLock 也再贴一下
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.core.types.Expiration;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/**
* @auther xpf
* @date 2022/6/10 11:15
* @description 封装redis分布式锁
*/
public class RedisLock implements AutoCloseable {
private String key;
private String value;
private int expiration;
private RedisTemplate redisTemplate;
public RedisLock(String key, int expiration, RedisTemplate redisTemplate) {
this.key = key;
this.value = UUID.randomUUID().toString();
this.expiration = expiration;
this.redisTemplate = redisTemplate;
}
public Boolean getLock(){
RedisCallback<Boolean> redisCallback = connection -> {
//设置NX
RedisStringCommands.SetOption setOption = RedisStringCommands.SetOption.ifAbsent();
//设置过期时间
Expiration expiration1 = Expiration.seconds(expiration);
//序列化key
byte[] redisKey = redisTemplate.getKeySerializer().serialize(key);
//序列化value
byte[] redisValue = redisTemplate.getValueSerializer().serialize(value);
//执行setnx操作
Boolean result = connection.set(redisKey, redisValue, expiration1, setOption);
return result;
};
//获取分布式锁
Boolean lock = (Boolean) redisTemplate.execute(redisCallback);
return lock;
}
public Boolean unLock(){
String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +
" return redis.call(\"del\",KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";
RedisScript<Boolean> redisScript = RedisScript.of(script, Boolean.class);
List<String> keys = Arrays.asList(key);
Boolean result = (Boolean) redisTemplate.execute(redisScript, keys, value);
return result;
}
/**
* jdk1.7新特性:实现 AutoCloseable ,就可以不用在finally里面写释放锁的代码了
* @throws Exception
*/
@Override
public void close() throws Exception {
unLock();
}
}
3、启动两个Application模拟分布式服务,查看定时任务执行情况,发现是顺序执行的,结果截图如下
8080执行情况
8081执行情况