场景
很多情况下我们会遇到这样的情况,程序根据数据的状态进行相应的操作,例如更新用户Token,分布式环境下,使得问题变得复杂,多个线程同时更新一条数据会导致状态出现未知状态,例如线程A看到用户User的Token过期就去刷新,此时线程B也做同样的操作,线程A先获取到新的Token,线程B后获取到新的Token,线程B的操作覆盖了线程A的操作,线程B又先刷新到缓存中去,线程A用无效的Token覆盖了缓存。
此时我们就希望有一把分布式锁可以让线程单独执行该操作,分布式锁实现的方式有很多,利用MySQL,Redis都可以,这里我们专门介绍下Redis分布式锁的实现。
加锁
使用Redis的setnx功能实现加锁
public boolean tryLock(String key, String value, Integer expire) {
String result = jedis.set(lockKey, lockValue, "nx", "ex", expire);
return "OK".equals(result, true);
}
循环加锁直到成功为止
public void lock() {
while (true) {
if (tryLock()) return true;
Thread.sleep(1000);
}
}
解锁
使用lua脚本实现解锁,而不是直接使用del直接删除,del可能会导致误删,使用lua脚本通过事务实现解。
public boolean unlock(String key, String value) {
String lua = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
String result = jedis.eval(lua, key, value)
return result == 0
}
转载于:https://my.oschina.net/u/2950586/blog/1827835