美文网首页
redis高级功能-分布式锁

redis高级功能-分布式锁

作者: tuoxie119 | 来源:发表于2018-02-22 20:04 被阅读0次

    同步锁

    多线程访问共享资源的时候,为了防止发生资源争抢,持有资源不能释放等一系列问题,就需要锁来防止并发访问共享资源。因为是单进程在访问,所以线程锁(同步锁等)就能完成。

    分布式锁

    在开始访问共享资源的程序部署在同一台服务器上,所以使用程序中的同步锁就可以实现共享资源的顺序访问,随着微服务架构的流行,越来越多的服务部署在不止一台服务器上,就出现了分布式、多进程访问共享资源的问题,就需要分布式锁解决。

    实现方式

    分布式锁的实现方式,常用的有三种:

    1. 数据库乐观锁实现
    2. Zookeeper实现
    3. 缓存实现

    三种方案的比较
    上面几种方式,哪种方式都无法做到完美。就像CAP一样,在复杂性、可靠性、性能等方面无法同时满足,所以,根据不同的应用场景选择最适合自己的才是王道。

    从理解的难易程度角度(从低到高)
    数据库 > 缓存 > Zookeeper

    从实现的复杂性角度(从低到高)
    Zookeeper >= 缓存 > 数据库

    从性能角度(从高到低)
    缓存 > Zookeeper >= 数据库

    从可靠性角度(从高到低)
    Zookeeper > 缓存 > 数据库

    redis实现

    RedisTool 分布式锁工具类

    /**
     * 参考网址:https://www.cnblogs.com/linjiqin/p/8003838.html
     */
    public class RedisTool {
        private static final String LOCK_SUCCESS = "OK";
        private static final String SET_IF_NOT_EXIST = "NX";
        private static final String SET_WITH_EXPIRE_TIME = "PX";
    
        private static final Long RELEASE_SUCCESS = 1L;
    
        /**
         * 尝试获取分布式锁
         * @param jedis Redis客户端
         * @param lockKey 锁
         * @param requestId 请求标识
         * @param expireTime 超期时间
         * @return 是否获取成功
         */
        public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
    
            String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
    
            if (LOCK_SUCCESS.equals(result)) {
                return true;
            }
            return false;
    
        }
    
    
        /**
         * 释放分布式锁
         * @param jedis Redis客户端
         * @param lockKey 锁
         * @param requestId 请求标识
         * @return 是否释放成功
         */
        public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
    
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
    
            if (RELEASE_SUCCESS.equals(result)) {
                return true;
            }
            return false;
    
        }
    
    }
    
    

    模拟并发访问的线程类

    public class DistributeLockClientThread implements Runnable {
        private String requestId;
        private Jedis jedis;
    
        public DistributeLockClientThread(String requestId, Jedis jedis) {
            this.requestId = requestId;
            this.jedis = jedis;
        }
    
        public void run() {
            boolean flag = RedisTool.tryGetDistributedLock(jedis,"distributelock",requestId,5000);
            if(flag){
                System.out.println(requestId +"==get lock success");
            }else {
                System.out.println(requestId +"==get lock fail");
            }
    
            try {
                Random random = new Random();
                Thread.sleep(1000* random.nextInt(4));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            boolean releaseFlag = RedisTool.releaseDistributedLock(jedis,"distributelock",requestId);
            if(releaseFlag){
                System.out.println(requestId +"==release lock success");
            }else {
                System.out.println(requestId +"==release lock fail");
            }
    
            jedis.close();
        }
    }
    

    测试类

    public class DistributeLockTest {
        public static void main(String[] args) {
            JedisPoolConfig config = new JedisPoolConfig();
    
            // 设置最大连接数
            config.setMaxIdle(100);
    
            // 设置最大阻塞时间,记住是毫秒数milliseconds
            config.setMaxWaitMillis(10000);
    
            // 设置空间连接
            config.setMaxIdle(100);
    
            // 创建连接池
            JedisPool pool = new JedisPool(config, "192.168.222.188",6379);
            ExecutorService executorService = Executors.newFixedThreadPool(1000);
            for (int i=0;i<1000;i++){
                DistributeLockClientThread distributeLockClientThread = new DistributeLockClientThread(String.valueOf(i),pool.getResource());
                executorService.execute(distributeLockClientThread);
            }
            executorService.shutdown();
        }
    }
    
    

    相关文章

      网友评论

          本文标题:redis高级功能-分布式锁

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