美文网首页
Redis分布式锁

Redis分布式锁

作者: 楼兰King | 来源:发表于2021-01-19 10:01 被阅读0次

功能介绍
分布式锁的获取
分布式锁尝试获取
分布式锁的释放
适用范围
需要
支持立即获取锁方式,如果获取到返回true,获取不到则返回false;
支持等待获取锁方式,如果获取到,直接返回true,获取不到在等待一小段时间,在这一小段时间内反复尝试,如果尝试成功,则返回true,等待时间过后还获取不到则返回false;
不能产生死锁的情况;
不能释放非自己加的锁
业务流程图
通过 redis 来实现分布式锁的加锁逻辑如下所示:


image.png
image.png

使用教程
核心代码说明
获取锁

public String lock(String key) {
    Jedis jedis = null;
    try {
        jedis = redisConnection.getJedis();
        jedis.select(dbIndex);
        key = KEY_PRE + key;
        String value = fetchLockValue();
        //多个客户端可能拿到同一把锁,用新的redis命令
        //redis 在2.6.12版本之后,对 set 命令进行了扩充,能够规避上面的两个问题。新版的 redis set 命令的参数如下SET key value [EX seconds] [PX milliseconds] [NX|XX]
        if (SET_SUCCESS.equals(jedis.set(key, value, "NX", "EX", lockExpirseTime))) {
            return value;
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (jedis != null) {
            jedis.close();
        }
    }
    return null;
}

解锁

public boolean unLock(String key, String value) {
    Long RELEASE_SUCCESS = 1L;
    Jedis jedis = null;
    try {
        jedis = redisConnection.getJedis();
        jedis.select(dbIndex);
        key = KEY_PRE + key;
        //在这里我们利用 redis 执行 Lua 脚本的能力来解决原子操作的问题
        String command = "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
        if (RELEASE_SUCCESS.equals(jedis.eval(command, Collections.singletonList(key), Collections.singletonList(value)))) {
            return true;
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (jedis != null) {
            jedis.close();
        }
    }
    return false;
}

测试类:RedisLockTest

public class RedisLockTest {
    public static void main(String[] args) {
        for (int i = 0; i < 9; i++) {
            new Thread(new Runnable() {
                public void run() {
                    RedisConnection redisConnection = RedisConnectionUtil.create();
                    LockServiceRedisImpl lockServiceRedis = new LockServiceRedisImpl();
                    lockServiceRedis.setRedisConnection(redisConnection);
                    lockServiceRedis.setDbIndex(15);
                    lockServiceRedis.setLockExpirseTime(20);
                    String key = "20200518";
                    String value = lockServiceRedis.lock(key);
                    try {
                        if (value != null) {
                            System.out.println(Thread.currentThread().getName() + " lock key = " + key + " success! ");
                            Thread.sleep(2 * 1000);
                        } else {
                            System.out.println(Thread.currentThread().getName() + " lock key = " + key + " failure! ");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (value == null) {
                            value = "";
                        }
                        System.out.println(Thread.currentThread().getName() + " unlock key = " + key + " " + lockServiceRedis.unLock(key, value));

                    }
                }
            }).start();
        }
    }
}

相关文章

网友评论

      本文标题:Redis分布式锁

      本文链接:https://www.haomeiwen.com/subject/zxlqzktx.html