美文网首页
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