最近项目中要用到redis的分布式锁,参考了网上整合jedis的资料,但运行时候会各种报错。重新整理下复制直接可用。
- maven导入相关包:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
- 新建 classpath:property/redis.properties
#最大分配的对象数
redis.pool.maxActive=200
#最大能够保持idel状态的对象数
redis.pool.maxIdle=50
redis.pool.minIdle=10
redis.pool.maxWaitMillis=20000
#当池内没有返回对象时,最大等待时间
redis.pool.maxWait=300
#格式:redis://:[密码]@[服务器地址]:[端口]/[db index]
#redis.uri = redis://:12345@127.0.0.1:6379/0
redis.host = 127.0.0.1
redis.port = 6379
redis.timeout=30000
redis.password =
redis.database = 0
- 新建配置文件 spring-jedis.xml 内容如下
<?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" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd"> <!-- 引入jedis的properties配置文件 --> <!--如果你有多个数据源需要通过<context:property-placeholder管理,且不愿意放在一个配置文件里,那么一定要加上ignore-unresolvable=“true"--> <!-- redis.properties 路径改为项目对应的 --> <context:property-placeholder location="classpath:property/redis.properties" ignore-unresolvable="true" /> <!--Jedis连接池的相关配置--> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!--新版是maxTotal,旧版是maxActive--> <property name="maxTotal"> <value>${redis.pool.maxActive}</value> </property> <property name="maxIdle"> <value>${redis.pool.maxIdle}</value> </property> <property name="testOnBorrow" value="true"/> <property name="testOnReturn" value="true"/> </bean> <bean id="jedisPool" class="redis.clients.jedis.JedisPool"> <constructor-arg name="poolConfig" ref="jedisPoolConfig" /> <constructor-arg name="host" value="${redis.host}" /> <constructor-arg name="port" value="${redis.port}" type="int" /> <constructor-arg name="timeout" value="${redis.timeout}" type="int" /> <!-- redis没设密码。配置为null--> <constructor-arg name="password" value="#{'${redis.password}'!=''?'${redis.password}':null}" /> <constructor-arg name="database" value="${redis.database}" type="int" /> </bean> <!--配置JedisConnectionFactory--> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="poolConfig" ref="jedisPoolConfig"/> </bean> </beans>
- 创建工具类
@Service
public class JedisFactory {
private JedisFactory(){}
@Autowired
private JedisPool jedisPool;
private static Jedis jedis;
/**
* 获得jedis对象
*/
public Jedis getJedis() {
//从JedisPool Jedis实例
if(jedis == null){
jedis = jedisPool.getResource();
}
return jedis;
}
}
-
redis分布式锁
@Service
public class DistributedLock {
@Autowired
private JedisFactory JedisFactory;
/**
* 占用锁
* @param lockKey 锁key
* @return 锁id
*/
public String occupyDistributedLock(String lockKey) {
//获得jedis实例
Jedis jedis = JedisFactory.getJedis();
//锁id(必须拥有此id才能释放锁)
String lockId = UUID.randomUUID().toString();
//占用锁同时设置失效时间 EX = seconds;秒 PX = milliseconds 毫秒
String isSuccees = jedis.set(lockKey, lockId, "NX","PX", 15000);
//占用锁成功返回锁id,否则返回null
if("OK".equals(isSuccees)){
return lockId;
}else{
return null;
}
}
/**
* 释放锁
* @param lockKey 锁key
* @param lockId 加锁id
*/
public void releaseDistributedLock(String lockKey,String lockId) {
if(lockId != null){
//获得jedis实例
Jedis jedis = JedisFactory.getJedis();
//执行Lua代码删除lockId匹配的锁
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(lockId));
}
}
}
- 业务代码。省了controller部分。
@Autowired
private DistributedLock jedisLock;
@RequestMapping(value = "test", method = RequestMethod.POST)
public void test() {
String key = "key";
String lockId = null;
try {
//用redis分布式锁。
lockId = jedisLock.occupyDistributedLock(key);
if (lockId != null) {
//业务代码
System.out.println("test");
}
} catch (Exception e) {
e.printStackTrace();
log.error(e);
throw e;
} finally {
//释放锁
jedisLock.releaseDistributedLock(key, lockId);
}
}