分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。
适用场景:分布式锁解决分布式情况下的多进程并发问题。
redis中的命令setnx特定,第一次设定后,后面不能再次设置,只能删除或者修改时间
192.168.219.128saber:0>setnx sex man
"1"
192.168.219.128saber:0>setnx sex woman
"0"
192.168.219.128saber:0>expire sex 10
"1"
192.168.219.128saber:0>
代码实现
redis加锁和解锁
/**
* 分布式锁 加锁
* @param lockKey
* @return true表示lockKey加锁成功 false表示LockKey已被锁
* redis命令setnx设置后不允许再次修改,只能删除和设置时间
*/
public boolean lock(String lockKey){
return redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
byte[] keyByte = stringRedisSerializer.serialize(lockKey);
byte[] valueByte = stringRedisSerializer.serialize("lock");
Boolean flag = redisConnection.setNX(keyByte,valueByte);//加锁
if (flag) {
redisConnection.expire(keyByte,Constants.Redis_Expire.DEFAULT_EXPIRE);//防止死锁,10秒后删除lockKey
}
return flag;
}
});
}
/**
* 分布式解锁
* @param lockKey
*/
public void unLock(String lockKey){
redisTemplate.setKeySerializer(new StringRedisSerializer());//加锁的时候设置了序列化,解锁也要设置
redisTemplate.delete(lockKey);
}
代码中加锁
try {
//true加锁成功说明是第一次进来,获取到了锁,可以执行后面的操作
//false说明已经加了锁,需要等待
//!true跳出循环
//!false等待
while (!redisUtils.lock("lock"+Id)) {
Thread.sleep(3000);
}
执行所内代码
。
。
。
。
} catch (Exception e) {
e.printStackTrace();
}finally {
redisUtils.unLock("lock"+Id);//释放锁
}