抽出一个server服务类, 注入后使用
package com.yiweath.value.config.redis;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
/**
* 2 * @Author:
* 3 * @Date: 2021/4/28 10:37 上午
* 4
*/
@Component
public class RedisLock {
public static final String LOCK_PREFIX = "redis_lock";
public static final int LOCK_EXPIRE = 300; // ms
@Autowired
RedisTemplate<String,String> redisTemplate;
/**
* 加锁,无阻塞
* @param key
* @param expireTime
* @return
*/
public Boolean lock(String key, long expireTime) {
String requestId = UUID.randomUUID().toString();
long start = System.currentTimeMillis();
//自旋,在一定时间内获取锁,超时则返回错误
for (;;){
//Set命令返回OK,则证明获取锁成功
Boolean ret = redisTemplate.opsForValue().setIfAbsent( key, requestId, expireTime,
TimeUnit.SECONDS);
if (ret) {
return true;
}
//否则循环等待,在timeout时间内仍未获取到锁,则获取失败
long end = System.currentTimeMillis() - start;
if (end >= LOCK_EXPIRE){
return false;
}
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
}
调用方式 ,根据业务需求, 自己再增加验证
private final String lock ="award_poll_";
private void updateAwardPoolMoney(Long id,Integer money,String mark){
log.info("开始执行加锁");
boolean flag = false;
try {
//若任务执行时间过短,则有可能在等锁的过程中2个服务任务都会获取到锁,这与实际需要的功能不一致,故需要将waitTime设置为0
flag = redisLock.lock(id+"", 10);
if(flag) {
updateAwardMony(id, money,mark);
}else {
log.info("Redis分布式锁没有获取到锁:{},ThreadName :{}","award_poll_"+id,Thread.currentThread().getName());
}
} catch (Exception e) {
log.info("更新奖池剩余金额执行失败,分布式锁异常"+e);
}finally {
if(flag) {//释放锁
redisLock.del("award_poll_"+id);
log.info("锁已释放");
}
}
}