Redis分布式锁释放锁是否必须用lua脚本?
无lua脚本释放锁:
public void unlock(String key, String uniqueValue) {
String value =redisDao.getString(key);
if (value != null && value.equals(uniqueValue))
redisDao.delete(key);
}
使用lua脚本释放锁:
// LUA脚本 -> 分布式锁解锁原子操作脚本
private static final String LUA_SCRIPT =
"if redis.call('get',KEYS[1]) == ARGV[1] then" +
" return redis.call('del',KEYS[1]) " +
"else" +
" return 0 " +
"end";
// lockId 一个不重复id -> 区分不同客户端
public boolean unlock(String lockId) {
Jedis client = jedisPool.getResource();
try {
Object result = client.eval(LUA_SCRIPT, Arrays.asList(LOCK_KEY), Arrays.asList(lockId));
if (result != null && "1".equalsIgnoreCase(result.toString())) {
return ture;
}
return false;
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage());
}
return false;
}
在释放锁的时候,如果没用原子操作,那么取值、比较、删除是三步操作。
假设现在是线程A在执行当前的动作。如果线程A取值之后,删除操作之前,key正好过期了,那么锁就自动释放了。这时,又被另外一个线程B获取了锁,那么在删除操作时,就会把线程B的锁给删除掉。如果这时线程B还在执行中,因为线程B的锁被线程A给删除掉了,那么其他的线程C也就可以获取到锁了。这样,其实临界区就有多个线程在运行了。