redis分布式锁

package com.rdj.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;

//AutoCloseable  jdk1.7 后增加的 自动关闭特性
@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 -> {
            RedisStringCommands.SetOption setOption = RedisStringCommands.SetOption.ifAbsent();
            Expiration expiration = Expiration.seconds(expireTime);
            byte[] redisKey = redisTemplate.getKeySerializer().serialize(key);
            byte[] redisValue = redisTemplate.getKeySerializer().serialize(value);
            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\n" +
                "  return redis.call(\"del\",KEYS[1])\n" +
                "else\n" +
                "  return 0\n" +
                "end";
        RedisScript<Boolean> redisScript = RedisScript.of(script,Boolean.class);
        List<String> keys = Arrays.asList(key);
        Boolean res = (Boolean) redisTemplate.execute(redisScript, keys, value);
        log.info("释放锁的结果 {}",res);
        return res;
    }


    @Override
    public void close() throws Exception {
        unLock();
    }
}

  

package com.rdj.distributelock.controller;

import com.rdj.distributelock.lock.RedisLock;
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 "方法执行完成";
    }
}

  

posted @ 2020-08-24 16:57  shijiu520  阅读(222)  评论(0)    收藏  举报