redis分布式锁的实现


   本文为博主原创文章,转载请附带博客地址:https://www.cnblogs.com/xbjhs/p/11041221.html

     这个分布式锁满足:

  1. 互斥性。在任意时刻,只有一个客户端能持有锁。
  2. 不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
  3. 解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了

1.jedisPool

package com.test;


import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;


/**
 * Description:redis线程池 <br/>
 *
 * @author: 
 * @date 2019-06-17 11:04
 * @Param:
 * @Return:
 */
public class JedisPoolUtil {
    /**
     * 被volatile修饰的变量不会被本地线程缓存,对该变量的读写都是直接操作共享内存
     */
    private static volatile JedisPool jedisPool = null;

    private JedisPoolUtil() {
    }

    public static JedisPool getJedisPoolInstance() {
        if (null == jedisPool) {
            synchronized (JedisPoolUtil.class) {
                if (null == jedisPool) {
                    JedisPoolConfig poolConfig = new JedisPoolConfig();
                    // 设置最大实例总数
                    poolConfig.setMaxTotal(1000);
                    //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
                    poolConfig.setMaxIdle(100);
                    //表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
                    poolConfig.setMaxWaitMillis(100 * 1000);
                    //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的
                    poolConfig.setTestOnBorrow(true);
                    // 实例在还给pool时,是否提前进行validate操作
                    poolConfig.setTestOnReturn(true);
                    jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379);
                }
            }
        }
        return jedisPool;
    }

    public static void release(Jedis jedis) {
        if (null != jedis) {
            jedis.close();
        }
    }

}

 

 
2.获取redis锁,解锁的测试类
package com.test;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.Arrays;
import java.util.UUID;

/**
 * Description:redis锁实现类 <br/>
 *
 * @author: 
 * @date 2019-06-17 11:43
 * @Param:
 * @Return:
 */

public class TestPool {

    public static void main(String[] args) {
        Jedis jedis = null;
        try {
            RedisLock redisLock = new RedisLock("123421342134");
            //获取锁
            redisLock.getRedisLock();
            //doSomething
            //释放锁
            redisLock.unlock();
        } catch (Exception e) {
            System.out.println("获取||释放redis锁异常" + e);
        } finally {
            if (null != jedis) {
                JedisPoolUtil.release(jedis);
            }
        }
    }
}

 

package com.test;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.Arrays;
import java.util.UUID;

/**
 * Description:redis锁 <br/>
 *
 * @author: 
 * @date 2019-06-17 17:07
 * @Param:
 * @Return:
 */
public class RedisLock {

    public static final String SET_SUCCESS = "OK";
    private String key;
    private String val;


    public RedisLock(String key) {
        this.key = key;
        this.val = UUID.randomUUID().toString();
    }

    /**
     * 加锁
     */
    public void getRedisLock() {
        Jedis jedis = getResource();
        /**
         *第三个参数是NX,意思是SET IF NOT EXIST,即当key不存在时,进行set操作;若key已经存在,则不做任何操作;
         *第四个参数是PX,意思是我们要给这个key加一个过期的设置,具体时间由第五个参数决定。
         *第五个为time,与第四个参数相呼应,代表key的过期时间。
         */
        String response = jedis.set(key, val, "NX", "PX", 20000);
        if (!SET_SUCCESS.equals(response)) {
            //抛出自定义异常
        }
        if (null != jedis) {
            JedisPoolUtil.release(jedis);
        }
    }

    /**
     * 获取实例
     */
    public static Jedis getResource() {
        JedisPool jedisPool = JedisPoolUtil.getJedisPoolInstance();
        JedisPool jedisPool2 = JedisPoolUtil.getJedisPoolInstance();
        System.out.println(jedisPool == jedisPool2);
        Jedis jedis = jedisPool.getResource();
        return jedis;
    }

    /**
     * 解锁
     */
    public void unlock() {
        Jedis jedis = getResource();
        jedis.eval("if redis.call('get',KEYS[1]) == ARGV[1] then \n return redis.call('del',KEYS[1]) \n else return 0 \n end",
                Arrays.asList(key), Arrays.asList(val));
        System.out.println("释放锁成功");
        if (null != jedis) {
            JedisPoolUtil.release(jedis);
        }
    }
}

 

3.pom依赖

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.2</version>
</dependency>

  4.截图

posted @ 2019-06-17 17:53  小宝的进化之路  阅读(184)  评论(0编辑  收藏  举报