zoukankan      html  css  js  c++  java
  • redis 实现分布式锁

    1,分布式锁的应用场景之前在zookeeper 的已经说过了,zookpper 的实现方式如下

    https://www.cnblogs.com/pickKnow/p/11338579.html

    2,基于redis 实现分布式锁

        了解set 和 setnx 命令的不同:

    127.0.0.1:6379> set name 'chris'
    OK
    127.0.0.1:6379> setnx name 'chris'
    (integer) 0
    127.0.0.1:6379> setnx age 20
    (integer) 1
    127.0.0.1:6379> set name 'chris'
    OK
    127.0.0.1:6379> 

        set:往数据库里面插入值,成功,返回ok,key 如果相同,后面的会覆盖前面的

        setnx: 往数据库里面插入值,成功返回1,失败返回0,如果key已经存在,则会插入失败,则会返回0

    expire key timeout:设置有效时长

    name 设置了20秒,过期了key 就不存在了

    127.0.0.1:6379> expire name 20
    (integer) 1
    127.0.0.1:6379> get name
    (nil)
    127.0.0.1:6379> get age
    "20"

    del key: 删除key

    127.0.0.1:6379> del age

    3,基于上面三条命令,可以实现redis分布式锁

        实现思想:在分布式集群环境中,多台JVM 共同去创建key,通过setnx 方式去创建,返回1,代表创建成功,创建成功,则能够获取到锁。

                          给锁设置有效期,根据业务逻辑来设置时长,方式死锁。

                          没有获取到锁的JVM,则一直等待。获取到锁的JVM 实现业务逻辑,逻辑完成,则删除key,将锁释放。

    4,实现脚本如下:

    private static JedisPool pool = null;
        // 设置最大连接数
        private static int maxTotal =200;
        // 设置最大空闲数
        private static int maxIdle = 8;
        // 设置最大等待时间
        private static long maxWaitMillis = 1000*100;
        // 在borrow一个jedis实例时,是否需要验证,若为true,则所有jedis实例均是可用的
        private static boolean testOnBorrow = true;
        // redis ip
        private static String ip = "192.168.178.110";
        // redis 端口
        private static int port = 6379;
        // redis连接timeout
        private static int timeOut = 6000;
        // redis 上锁的key
        private static String redisLockKey = "redisLockKey";
        // redis 上锁的key 豪秒
        private static long redisLockTimeOut = 6000;
    
        static {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(maxTotal);
            config.setMaxIdle(maxIdle);
            config.setMaxWaitMillis(maxWaitMillis);
            config.setTestOnBorrow(testOnBorrow);
            pool = new JedisPool(config, ip, port, timeOut);
        }
    
        @Override
        public boolean lock(String redisLockValue) {
            Jedis resource = null;
            try {
                resource = pool.getResource();
                // 当前时间
                long moment = System.currentTimeMillis();
                // 一把锁的的有效期是 redisLockTimeOut,所以在这个期间内,一直抢key
                // 超过这个时间,说明锁不用抢了,已经过期了,等待下次抢
                while (System.currentTimeMillis() < moment + redisLockTimeOut) {
                    Long setnx = resource.setnx(redisLockKey, redisLockValue);
                    if (setnx == 1) {
                        // 获取到了锁,给锁加上有效期
                        resource.pexpire(redisLockKey, redisLockTimeOut);
                        return true;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                resource.close();
            }
            return false;
        }
    
        public void unlock() {
            Jedis resource = null;
            try {
                resource = pool.getResource();
                resource.del(redisLockKey);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                resource.close();
            }
        }
  • 相关阅读:
    大小端表示法
    构建二叉树并求其深度
    输入一行字符反向输出
    C++读取一行字符串输入
    关于递归调用的深度
    2016-9-22题目:extern char* 与char[]
    Ubuntu安装搜狗输入法
    判断字符串相等
    [Warning] deprecated conversion from string constant to 'char*' 原因
    ArcGIS API for JavaScript 4.2学习笔记[31] (补充学习)Task类
  • 原文地址:https://www.cnblogs.com/pickKnow/p/11357779.html
Copyright © 2011-2022 走看看