在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。那具体什么是分布式锁,分布式锁应用在哪些业务场景、如何来实现分布式锁呢?本文采用stringRedisTemplate来实现分布式锁.
1:什么是分布式锁?
在单机应用下的并发编程中,我们通过锁(synchronized 、Lock
),来避免由于竞争而造成的数据不一致问题。而分布式锁,就是为了解决分布式应用中的数据不一致问题.通常使用redis分布式锁.
2:分布式锁的条件
- 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行
- 高可用的获取锁与释放锁
- 高性能的获取锁与释放锁
- 具备可重入特性(可理解为重新进入,由多于一个任务并发使用,而不必担心数据错误)
- 具备锁失效机制,防止死锁
- 具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败
3:stringRedisTemplate实现分布式锁
加锁
加锁的话,需要有2个参数,( key保证唯一性, value为锁的存活时间)
public boolean lock(String key, String value) {
//判断key是否为空, StringUtil是自己写的工具类
if (StringUtil.isNullOrEmpty(key)) return false;
//默认锁的存活时间为5分钟
if (StringUtil.isNullOrEmpty(value)) value = System.currentTimeMillis() + 60000 * 5 + "";
//采用stringRedisTemplate.opsForValue().setIfAbsent的方法加锁
if (stringRedisTemplate.opsForValue().setIfAbsent(key, value)) {
return true;
}
//如果get找不到对应的key值,或者系统当前时间大于锁存活时间,判断锁失效
String current_value = stringRedisTemplate.opsForValue().get(key);
if (!StringUtil.isNullOrEmpty(current_value)
//超时了
&& Long.parseLong(current_value) < System.currentTimeMillis()) {
String old_value = stringRedisTemplate.opsForValue().getAndSet(key, value);
if (!StringUtil.isNullOrEmpty(current_value)
&& old_value.equals(current_value)) {
return true;
}
}
return false;
}
解锁
解锁就很简单了,如果判断key存在,就删除掉key就完成了解锁.
public void unlock(String key, String value) {
try {
if (stringRedisTemplate.opsForValue().get(key).equals(value)) {
stringRedisTemplate.opsForValue().getOperations().delete(key);
}
} catch (Exception e) {
e.printStackTrace();
}
}
因博主水平有限,代码中的不足之处请多多指正.