redis分布式锁

一: 分布式锁要求

  1. 在任意时刻只能有一个线程可持有该锁。
  2. 该锁只能被加锁人解锁。
  3. 不会发生死锁。

二: 分布式锁实现

2.1 基于Jedis 实现分布式锁

2.1.1 引入依赖

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

2.1.2 加锁的代码

  1. Jedis 提供的方法
   /**
     *
     * @param jedis  jedis客户端
     * @param key    锁的key
     * @param value  客户端标识
     * @param nxxx   NX 或者 XX 。 NX Only set the key if it does not already exist.  XX Only set the key if it already exist
     * @param expx   EX 或者 PX。  xpire time units: EX = seconds; PX = milliseconds
     * @param time   expire time in the units of expx
     * @return
     */
    public boolean lockRedis(Jedis jedis,String key, String value, String nxxx, String expx, int time){
       String status  =  jedis.set(key,value,nxxx,expx,time);
       if("OK".equals(status)){
           return true;
       }else{
           return false;
       }
    }

ps: 这里主要说一下 nxxx 的作用 NX 只有 当 key不存在的时候进行 set操作。xx 只有当key存在的时候进行set操作。 所以显而易见 我们固定传 NX

  1. lua script 进行加锁
    /**
     *
     * @param jedis   jedis客户端
     * @param key     锁的key
     * @param value   客户端标识
     * @param time    超时时间
     * @return
     */
    public boolean lockRedis(Jedis jedis,String key, String value, int time){
        String luaScript = ""
                + "\nlocal respStr = tonumber(redis.call('SETNX', KEYS[1],ARGV[1]));"
                + "\nredis.call('PEXPIRE',KEYS[1],ARGV[2]);"
                + "\nreturn respStr";
        List<String> keys = new ArrayList<String>();
        keys.add(key);
        List<String> args = new ArrayList<String>();
        args.add(value);
        args.add(time+"");
        Long ret = (Long) jedis.eval(luaScript, keys, args);
        if( new Long(1).equals(ret)){
            return true;
        }
        return false;
    }

2.1.3 解锁代码

    /**
     *
     * @param jedis  jedis客户端
     * @param key    锁的key
     * @param value  客户端标识
     * @return
     */
    public boolean unlockRedis(Jedis jedis,String key, String value){
        String luaScript=""
                +"\nlocal v = redis.call('GET', KEYS[1]);"
                +"\nlocal r = 0;"
                +"\nif v == ARGV[1] then"
                +"\nr = tonumber(redis.call('DEL',KEYS[1]));"
                +"\nend"
                +"\nreturn r";
        List<String> keys = new ArrayList<String>();
        keys.add(key);
        List<String> args = new ArrayList<String>();
        args.add(value);
        Long r=(Long) jedis.eval(luaScript, keys, args);
        if( new Long(1).equals(r)){
            return true;
        }
        return false;
    }

ps: redis 会在 lua 命令执行结束之后再执行其他命令。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值