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
  • 相关阅读:
    ContextLoaderListener和Spring MVC中的DispatcherServlet学习 随手记
    Linux目录详解
    9---PIP 管理工具的使用
    8. Python自定义模块humansize
    1. Hyper上的CentOS 6.5 网络配置
    Python基础学习8---list列表的操作
    Python基础学习6---存储器
    Python基础学习3---数据结构
    Python基础学习2---模块
    Python基础学习1---函数
  • 原文地址:https://www.cnblogs.com/callbin/p/14581399.html
Copyright © 2011-2022 走看看