1.demo
package com.hecr;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
/**
* redis分布式锁工具类
* <p>Date: Created in 9:33 2020/12/4</p>
* 参考链接:https://www.cnblogs.com/ZenoLiang/p/11209980.html
*
* @author hecanrong
*/
@Component
public class CommonRedisHelper<T> {
@Autowired
RedisTemplate redisTemplate;
/**
* 处理业务
*
* @param key key值
* @param expire 加锁失效时间
* @param timeUnit 单位
* @param supplier 供给型接口
* @return
*/
public T deal(String key, int expire, TimeUnit timeUnit, Supplier<T> supplier) {
if (lock(key, expire, timeUnit)) {
// 执行逻辑操作
T t = supplier.get();
delete(key);
return t;
}
// 设置失败次数计数器, 当到达5次时, 返回失败
for (int i = 0; i < 6; i++) {
if (i == 5) {
throw new RuntimeException("请勿频繁操作");
}
// 等待100ms重试
try {
Thread.sleep(100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (lock(key, expire, timeUnit)) {
// 执行逻辑操作
T t = supplier.get();
delete(key);
return t;
}
}
return null;
}
/**
* @param key key值
* @param expire 加锁失效时间
* @param timeUnit 单位
* @return 是否获取到
*/
private boolean lock(String key, int expire, TimeUnit timeUnit) {
long loclExpire = timeUnit.toMillis(expire);
// 利用lambda表达式
return (Boolean) redisTemplate.execute((RedisCallback) connection -> {
long expireAt = System.currentTimeMillis() + loclExpire + 1;
Boolean acquire = connection.setNX(key.getBytes(), String.valueOf(expireAt).getBytes());
if (acquire) {
return true;
} else {
byte[] value = connection.get(key.getBytes());
if (Objects.nonNull(value) && value.length > 0) {
long expireTime = Long.parseLong(new String(value));
// 如果锁已经过期
if (expireTime < System.currentTimeMillis()) {
// 重新加锁,防止死锁
byte[] oldValue = connection.getSet(key.getBytes(), String.valueOf(System.currentTimeMillis() + loclExpire + 1).getBytes());
return Long.parseLong(new String(oldValue)) < System.currentTimeMillis();
}
}
}
return false;
});
}
/**
* 删除锁
*/
private void delete(String key) {
redisTemplate.delete(key);
}
}
2.测试代码
3.测试结果
4.文章参考链接
a. https://www.cnblogs.com/ZenoLiang/p/11209980.html
b. https://blog.csdn.net/hecr_mingong/article/details/105694656