Redis分布式锁
分布式锁的实现
多进程的架构:
1.资源共享问题
2.数据安全性
分布式锁的解决方案
1.怎么去获取锁
数据库
lock表(
methodName varchar(1000);
memo varchar(100);
modifyTime timestamp;
unique key mn(method) ---唯一约束
)
try{
exec insert into lock(methodName,memo) values('method','desc');
return true;
}catch(DuplicateException e){
return false;
}
zookeepeer
redis
delete去释放锁
2.怎么去释放锁
3.在redis当中使用锁需要使用到redis的命令 setnx这个命令
setnx这个命令的作用是当redis当中有数据的时候,命令不会执行,直接返回0,如果数据不存在,直接赋值,然后返回1
接下来代码演示在java中使用redis的锁:
首先在pom.xml文件当中增加下面的代码.
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
然后编写一个redis连接类:
public class RedisManager
{
private static JedisPool jedisPool;
static{
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxIdle(10);
jedisPoolConfig.setMaxTotal(20);
jedisPool = new JedisPool(jedisPoolConfig,"192.168.159.136",6379);
}
public static Jedis getJedis() throws Exception {
if(null!=jedisPool){
return jedisPool.getResource();
}
throw new Exception("jedis Pool is not init");
}
}
使用redis的锁,并且测试锁的执行:
public class RedisLock {
/**
*
* @param key 获取的key值
* @param timeout 获取锁的最大超时时间
* @return
*/
public String getLock(String key,int timeout){
try {
Jedis jedis = RedisManager.getJedis();
String value = UUID.randomUUID().toString();
long end = System.currentTimeMillis() + timeout;
//
while( System.currentTimeMillis()<end ){ //阻塞
//如果这里redis释放锁出问题了,会导致后续的线程没有办法继续获得锁,这个时候可以实现超时的机制
if (jedis.setnx(key, value) == 1) {
jedis.expire(key,timeout);
//锁设置成功,redis操作成功
return value;
}
//如果redis服务在设置nx的时候宕机了,expire没有办法设置成功
if(jedis.ttl(key)==-1){//没设置超时时间
//设置过期时间
jedis.expire(key,timeout);
}
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//释放锁
/**
* @param key
* @param value
* @return
*/
public boolean releaseLock(String key,String value){
try {
Jedis jedis = RedisManager.getJedis();
while(true) {
jedis.watch(key); //用来监控一个或多个键的key,一旦修改删除,后面代码不会执行
//判断获得锁的线程和当前redis当中存的锁是同一个
if (value.equals(jedis.get(key))) {
Transaction trans = jedis.multi();
trans.del(key);
List<Object> list = trans.exec();
if (list == null) {
continue;
}
return true;
}
jedis.unwatch();
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static void main(String[]args){
RedisLock lock = new RedisLock();
String lockId = lock.getLock("lock:aaa",10000);
if(null!=lockId){
System.out.println("获得锁成功!");
}
String lockId2 = lock.getLock("lock:aaa",10000);
System.out.println(lockId2);
}
}