redis分布式锁工具类

(1)需要导入的包

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

(2)JedisUtil类


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

import java.util.Collections;

/**
 * 不采用springTemplate 的操作类
 * 因为springTemplate 的SetNx 非原子性,可能导致锁永久锁住,释放失败
 */
@Component("jedisUtil")
public class JedisUtil {

	private static final String LOCK_SUCCESS = "OK";
	private static final String SET_IF_NOT_EXIST = "NX";
	private static final String SET_WITH_EXPIRE_TIME = "PX";
	private static final Long RELEASE_SUCCESS = 1L;

	@Autowired
	private JedisPool jedisPool;

	/**
	 * 尝试获取分布式锁
	 * @param lockKey 锁
	 * @param requestId 请求标识
	 * @param expireTime 超期时间
	 * @return 是否获取成功
	 */
	public boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) {
		Jedis jedis = null;
		try{
			jedis = jedisPool.getResource();
			String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
			if (LOCK_SUCCESS.equals(result)) {
				return true;
			}
		} finally {
			//归还 jedis 连接
			if(jedis != null){
				jedis.close();
			}
		}
		return false;
	}

	/**
	 * 释放分布式锁
	 * @param lockKey 锁
	 * @param requestId 请求标识
	 * @return 是否释放成功
	 */
	public boolean releaseDistributedLock(String lockKey, String requestId) {
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
			Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
			if (RELEASE_SUCCESS.equals(result)) {
				return true;
			}
		} finally {
			//归还 jedis 连接
			if(jedis != null){
				jedis.close();
			}
		}
		return false;
	}

	/**
	 * 设置值并设置超时时间
	 * @param key
	 * @param value
	 * @param expireTime
	 * @return
	 */
	public Long rpushString(String key, String value, int expireTime){
		Jedis jedis = null;
		Long result = 0L;
		try {
			jedis = jedisPool.getResource();
			result = jedis.rpush(key, value);
			if(result > 0){
				jedis.expire(key,expireTime);
			}
		} finally {
			if(jedis != null){
				jedis.close();
			}
		}
		return result;
	}

	/**
	 * 批量插入
	 * @param key
	 * @param values
	 * @param expireTime
	 * @return
	 */
	public Long batchRpushString(String key, String[] values, int expireTime){
		Jedis jedis = null;
		Long result = 0L;
		try {
			jedis = jedisPool.getResource();
			result = jedis.rpush(key, values);
			if(result > 0){
				jedis.expire(key,expireTime);
			}
		} finally {
			if(jedis != null){
				jedis.close();
			}
		}
		return result;

	}

	/**
	 * 释放锁
	 * @param lockKey
	 */
	public Long releaseLock(String lockKey){
		Long result = 0L;
		Jedis jedis = null;
		try {
			jedis = jedisPool.getResource();
			result = jedis.del(lockKey);
		} finally {
			if(jedis != null){
				jedis.close();
			}
		}
		return result;
	}

}

(3)jedisPool配置

可以根据自己情况换成pringboot类配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean >
        <property name="maxTotal" value="3000"></property>
        <property name="maxIdle" value="300"></property>
        <property name="minIdle" value="10"></property>
        <property name="maxWaitMillis" value="15000"></property>
        <property name="minEvictableIdleTimeMillis" value="300000"></property>
        <property name="numTestsPerEvictionRun" value="3"></property>
        <property name="timeBetweenEvictionRunsMillis" value="60000"></property>
        <property name="testOnBorrow" value="true"></property>
        <property name="testOnReturn" value="true"></property>
        <property name="testWhileIdle" value="true"></property>
    </bean>

    <bean >
        <!-- config -->
        <constructor-arg ref="jedisPoolConfig"/>
        <!-- host -->
        <constructor-arg value="127.0.0.1" type="java.lang.String" />
        <!-- port -->
        <constructor-arg value="6379" type="int" />
        <!-- timeout -->
        <constructor-arg value="15000" />
    </bean>
    <context:component-scan base-package="com.td.yousan.util"/>
</beans>

(4)使用举例

@Resource
private JedisUtil jedisUtil;


String lockKey=userId;//锁key
String requestId = UUID.randomUUID().toString();//请求标识
final int EXPIRED_TIME = 300*1000;//redis 数据存储过期时间

//加锁举例
boolean lockResult = jedisUtil.tryGetDistributedLock(lockKey, requestId, EXPIRED_TIME)

//放锁举例
booleanr releaseResult =jedisUtil.releaseDistributedLock(lockKey, requestId);