zoukankan      html  css  js  c++  java
  • 基于Redis的Setnx实现分布式锁

    一、 redis分布式锁原理

      并发 到Redis里变成了串行排队,单线程

     

    二、基于Redis的Setnx实现分布式锁 

      1、pom

       

      <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    2、application.properties  配置redis

      

    spring.redis.host=192.168.73.130

    3、Controller层测试

    package com.example.distributelock.controller;
    
    import com.example.distributelock.lock.RedisLock;
    import com.example.distributelock.lock.ZkLock;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @Slf4j
    public class RedisLockController {
        @Autowired
        private RedisTemplate redisTemplate;
    
        @RequestMapping("redisLock")
        public String redisLock(){
            log.info("我进入了方法!");
            try (RedisLock redisLock = new RedisLock(redisTemplate,"redisKey",30)){
                if (redisLock.getLock()) {
                    log.info("我进入了锁!!");
                    Thread.sleep(15000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.info("方法执行完成");
            return "方法执行完成";
        }
    
        @RequestMapping("zkLock")
        public String zkLock(){
            log.info("我进入了方法!");
            try (ZkLock zkLock = new ZkLock("localhost:2181","order")){
                if (zkLock.getLock()) {
                    log.info("我进入了锁!!");
                    Thread.sleep(15000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.info("方法执行完成");
            return "方法执行完成";
        }
    }
    View Code

    4、Redis的Setnx实现分布式锁操作

    package com.example.distributelock.lock;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.data.redis.connection.RedisStringCommands;
    import org.springframework.data.redis.core.RedisCallback;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.script.RedisScript;
    import org.springframework.data.redis.core.types.Expiration;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.UUID;
    
    @Slf4j
    public class RedisLock implements AutoCloseable {
    
        private RedisTemplate redisTemplate;
        private String key;
        private String value;
        //单位:秒
        private int expireTime;
    
        public RedisLock(RedisTemplate redisTemplate,String key,int expireTime){
            this.redisTemplate = redisTemplate;
            this.key = key;
            this.expireTime=expireTime;
            this.value = UUID.randomUUID().toString();
        }
    
        /**
         * 获取分布式锁
         * @return
         */
        public boolean getLock(){
            RedisCallback<Boolean> redisCallback = connection -> {
                //设置NX
                RedisStringCommands.SetOption setOption = RedisStringCommands.SetOption.ifAbsent();
                //设置过期时间
                Expiration expiration = Expiration.seconds(expireTime);
                //序列化key
                byte[] redisKey = redisTemplate.getKeySerializer().serialize(key);
                //序列化value
                byte[] redisValue = redisTemplate.getValueSerializer().serialize(value);
                //执行setnx操作
                Boolean result = connection.set(redisKey, redisValue, expiration, setOption);
                return result;
            };
    
            //获取分布式锁
            Boolean lock = (Boolean)redisTemplate.execute(redisCallback);
            return lock;
        }
    
        public boolean unLock() {
            String script = "if redis.call("get",KEYS[1]) == ARGV[1] then
    " +
                    "    return redis.call("del",KEYS[1])
    " +
                    "else
    " +
                    "    return 0
    " +
                    "end";
            RedisScript<Boolean> redisScript = RedisScript.of(script,Boolean.class);
            List<String> keys = Arrays.asList(key);
    
            Boolean result = (Boolean)redisTemplate.execute(redisScript, keys, value);
            log.info("释放锁的结果:"+result);
            return result;
        }
    
    
        @Override
        public void close() throws Exception {
            unLock();
        }
    }
    View Code
  • 相关阅读:
    计算机网路基础
    [python基础] python 2与python 3之间的区别 —— 默认中文字符串长
    [python基础] 同时赋值多个变量与变量值交换
    [python基础] python 2与python 3的区别,一个关于对象的未知的坑
    [python基础] python 2与python 3之间的区别 —— 不同数据类型间的运算
    [python基础] 浮点数乘法的误差问题
    关于HTMLTestRunner的中断与实时性问题
    [python自动化] 关于python无法修改全局变量的问题
    关于RFC2544中的Cut-Through和Store-and-Forward模式
    google filament pbr
  • 原文地址:https://www.cnblogs.com/callbin/p/14581399.html
Copyright © 2011-2022 走看看