Redis锁

*redis分布式锁的实现(Redis)

分布式锁实现的关键是在分布式的应用服务器外,搭建一个存储服务器,存储锁信息,这时候我们很容易就想到了Redis。首先我们要搭建一个Redis服务器,用Redis服务器来存储锁信息。

在实现的时候要注意的几个关键点:

1、锁信息必须是会过期超时的,不能让一个线程长期占有一个锁而导致死锁;

2、同一时刻只能有一个线程获取到锁。

几个要用到的redis命令:

setnx(key, value):“set if not exits”,若该key-value不存在,则成功加入缓存并且返回1,否则返回0。

get(key):获得key对应的value值,若不存在则返回nil。

getset(key, value):先获取key对应的value值,若不存在则返回nil,然后将旧的value更新为新的value。

expire(key, seconds):设置key-value的有效期为seconds秒。

看一下流程图:

在这个流程下,不会导致死锁。

我采用Jedis作为Redis客户端的api,下面来看一下具体实现的代码。

(1)首先要创建一个Redis连接池。

public class RedisPool {

private static JedisPool pool;//jedis连接池

private static int maxTotal = 20;//最大连接数

private static int maxIdle = 10;//最大空闲连接数

private static int minIdle = 5;//最小空闲连接数

private static boolean testOnBorrow = true;//在取连接时测试连接的可用性

private static boolean testOnReturn = false;//再还连接时不测试连接的可用性

static {
    initPool();//初始化连接池
}

public static Jedis getJedis(){
    return pool.getResource();
}

public static void close(Jedis jedis){
    jedis.close();
}

private static void initPool(){
    JedisPoolConfig config = new JedisPoolConfig();
    config.setMaxTotal(maxTotal);
    config.setMaxIdle(maxIdle);
    config.setMinIdle(minIdle);
    config.setTestOnBorrow(testOnBorrow);
    config.setTestOnReturn(testOnReturn);
    config.setBlockWhenExhausted(true);
    pool = new JedisPool(config, "127.0.0.1", 6379, 5000, "liqiyao");
}

}
(2)对Jedis的api进行封装,封装一些实现分布式锁需要用到的操作。

public class RedisPoolUtil {

private RedisPoolUtil(){}

private static RedisPool redisPool;

public static String get(String key){
    Jedis jedis = null;
    String result = null;
    try {
        jedis = RedisPool.getJedis();
        result = jedis.get(key);
    } catch (Exception e){
        e.printStackTrace();
    } finally {
        if (jedis != null) {
            jedis.close();
        }
        return result;
    }
}

public static Long setnx(String key, String value){
    Jedis jedis = null;
    Long result = null;
    try {
        jedis = RedisPool.getJedis();
        result = jedis.setnx(key, value);
    } catch (Exception e){
        e.printStackTrace();
    } finally {
        if (jedis != null) {
            jedis.close();
        }
        return result;
    }
}

public static String getSet(String key, String value){
    Jedis jedis = null;
    String result = null;
    try {
        jedis = RedisPool.getJedis();
        result = jedis.getSet(key, value);
    } catch (Exception e){
        e.printStackTrace();
    } finally {
        if (jedis != null) {
            jedis.close();
        }
        return result;
    }
}

public static Long expire(String key, int seconds){
    Jedis jedis = null;
    Long result = null;
    try {
        jedis = RedisPool.getJedis();
        result = jedis.expire(key, seconds);
    } catch (Exception e){
        e.printStackTrace();
    } finally {
        if (jedis != null) {
            jedis.close();
        }
        return result;
    }
}

public static Long del(String key){
    Jedis jedis = null;
    Long result = null;
    try {
        jedis = RedisPool.getJedis();
        result = jedis.del(key);
    } catch (Exception e){
        e.printStackTrace();
    } finally {
        if (jedis != null) {
            jedis.close();
        }
        return result;
    }
}

}
(3)分布式锁工具类

public class DistributedLockUtil {

private DistributedLockUtil(){
}

public static boolean lock(String lockName){//lockName可以为共享变量名,也可以为方法名,主要是用于模拟锁信息
    System.out.println(Thread.currentThread() + "开始尝试加锁!");
    Long result = RedisPoolUtil.setnx(lockName, String.valueOf(System.currentTimeMillis() + 5000));
    if (result != null && result.intValue() == 1){
        System.out.println(Thread.currentThread() + "加锁成功!");
        RedisPoolUtil.expire(lockName, 5);
        System.out.println(Thread.currentThread() + "执行业务逻辑!");
        RedisPoolUtil.del(lockName);
        return true;
    } else {
        String lockValueA = RedisPoolUtil.get(lockName);
        if (lockValueA != null && Long.parseLong(lockValueA) >= System.currentTimeMillis()){
            String lockValueB = RedisPoolUtil.getSet(lockName, String.valueOf(System.currentTimeMillis() + 5000));
            if (lockValueB == null || lockValueB.equals(lockValueA)){
                System.out.println(Thread.currentThread() + "加锁成功!");
                RedisPoolUtil.expire(lockName, 5);
                System.out.println(Thread.currentThread() + "执行业务逻辑!");
                RedisPoolUtil.del(lockName);
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值