简易的Redis分布式事务锁
0.背景
在物联网微服务时代,面对源源不断的数据,难免会遇到需要一把分布式事务" title="分布式事务">分布式事务锁的情况,今天,我们学习一下Redis分布式事务锁。
1.用于上锁的类
RedisLock.java
public class RedisLock { private static final Logger log = LoggerFactory.getLogger(RedisLock.class);
@Resource(name = "deviceStringRedisTemplate")
private StringRedisTemplate redisTemplate;
/**
* redis键过期时间,毫秒为单位
*/
private static final long EXPIRE = 5 * 1000L;
/**
* 尝试获取锁的超时时间,不能一直尝试获取锁,空耗资源。
*/
private static final long TIMEOUT = 10 * 1000L;
public boolean lock(String key, String value) {
log.info("尝试获取锁 kye:{},value:{}", key, value);
//请求锁时间
long requestTime = System.currentTimeMillis();
while (true) {
//等待锁时间
long watiTime = System.currentTimeMillis() - requestTime;
//如果等待锁时间超过10s,加锁失败
if (watiTime > TIMEOUT) {
log.info("等待锁超时 kye:{},value:{}", key, value);
return false;
}
if (redisTemplate.opsForValue().setIfAbsent(key, String.valueOf(System.currentTimeMillis()))) {
//获取锁成功
log.info("获取锁成功 kye:{},value:{}", key, value);
//设置超时时间,防止解锁失败,导致死锁
redisTemplate.expire(key, EXPIRE, TimeUnit.MILLISECONDS);
return true;
}
String valueTime = redisTemplate.opsForValue().get(key);
if (!StringUtils.isEmpty(valueTime) && System.currentTimeMillis() - Long.parseLong(valueTime) > EXPIRE) {
//加锁时间超过过期时间,删除key,防止死锁
log.info("锁超时, key:{}, value:{}", key, value);
try {
redisTemplate.opsForValue().getOperations().delete(key);
} catch (Exception e) {
log.info("删除锁异常 key:{}, value:{}", key, value);
e.printStackTrace();
}
return false;
}
// 获取锁失败,等待20毫秒继续请求
try {
log.info("等待20 nanoSeconds key:{},value:{}", key, value);
TimeUnit.NANOSECONDS.sleep(20);
} catch (InterruptedException e) {
log.info("等待20 nanoSeconds 异常 key:{},value:{}", key, value);
e.printStackTrace();
}
}
}
/**
* 解锁
*
* @param key
* @param value
*/
public void unlock(String key, String value) {
try {
redisTemplate.opsForValue().getOperations().delete(key);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.应用举例
我们以得到锁之后的第一个线程才处理业务为例,给出一个例子:
String redisKey = RedisPrefix.MY_BIZ + name;
try {
boolean lockResult = redisLock.lock(redisKey, name);
if (lockResult) {
userInfo = userService.findUser(name);
if (userInfo == null) {
// 抢到锁,且为第一个到来的线程,开始处理业务。
userService.createUserInfo(name);
}
}
} catch (Exception e) {
e.printStackTrace();
log.error("redis lock error:", e);
} finally {
redisLock.unlock(redisKey, name);
}
以上是 简易的Redis分布式事务锁 的全部内容, 来源链接: utcz.com/z/519122.html