用redis实现分布式锁
现在很多项目都开始做分布式部署或者双活等增加系统的的稳定性。但是随之而来的就是会出现并发事件对相同数据集进行同时操作。项目中遇到了需要定时执行大批量数据的操作。为了防止多服务器同时执行定时任务,对定时处理逻辑进行了加锁操作(Redis)。
Redis工具类
package cn
.yunda
.guns
.webUtils
;
import java
.util
.List
;
import java
.util
.Map
;
import java
.util
.Set
;
import java
.util
.concurrent
.TimeUnit
;
import org
.springframework
.beans
.factory
.annotation
.Autowired
;
import org
.springframework
.dao
.DataAccessException
;
import org
.springframework
.data
.redis
.connection
.RedisConnection
;
import org
.springframework
.data
.redis
.core
.RedisCallback
;
import org
.springframework
.data
.redis
.core
.RedisTemplate
;
import org
.springframework
.data
.redis
.serializer
.RedisSerializer
;
import org
.springframework
.stereotype
.Component
;
import org
.springframework
.util
.CollectionUtils
;
@Component
public class RedisUtil {
@Autowired
private RedisTemplate
<String, Object> redisTemplate
;
public void setRedisTemplate(RedisTemplate
<String, Object> redisTemplate
) {
this.redisTemplate
= redisTemplate
;
}
public boolean getRedisSetNX(String key
,String value
) {
Boolean execute
= redisTemplate
.execute(new RedisCallback<Boolean>() {
@Override
public Boolean
doInRedis(RedisConnection connection
) throws DataAccessException
{
Boolean setNX
= connection
.setNX(key
.getBytes(), value
.getBytes());
return setNX
;
}
});
return execute
;
}
public boolean expire(String key
, long time
) {
try {
redisTemplate
.expire(key
, time
, TimeUnit
.SECONDS
);
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public long getExpire(String key
) {
return redisTemplate
.getExpire(key
, TimeUnit
.SECONDS
);
}
public boolean hasKey(String key
) {
try {
return redisTemplate
.hasKey(key
);
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
@SuppressWarnings("unchecked")
public void del(String
... key
) {
if (key
!= null
&& key
.length
> 0) {
if (key
.length
== 1) {
redisTemplate
.delete(key
[0]);
} else {
redisTemplate
.delete(CollectionUtils
.arrayToList(key
));
}
}
}
public Object
get(String key
) {
return key
== null
? null
: redisTemplate
.opsForValue().get(key
);
}
public boolean set(String key
, Object value
) {
try {
redisTemplate
.opsForValue().set(key
, value
);
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public boolean set(String key
, Object value
, long time
) {
try {
if (time
> 0) {
redisTemplate
.opsForValue().set(key
, value
, time
, TimeUnit
.SECONDS
);
} else {
set(key
, value
);
}
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public long incr(String key
, long delta
) {
if (delta
< 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate
.opsForValue().increment(key
, delta
);
}
public long decr(String key
, long delta
) {
if (delta
< 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate
.opsForValue().increment(key
, -delta
);
}
public Object
hget(String key
, String item
) {
return redisTemplate
.opsForHash().get(key
, item
);
}
public Map
<Object, Object> hmget(String key
) {
return redisTemplate
.opsForHash().entries(key
);
}
public boolean hmset(String key
, Map
<String, Object> map
) {
try {
redisTemplate
.opsForHash().putAll(key
, map
);
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public boolean hmset(String key
, Map
<String, Object> map
, long time
) {
try {
redisTemplate
.opsForHash().putAll(key
, map
);
if (time
> 0) {
expire(key
, time
);
}
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public boolean hset(String key
, String item
, Object value
) {
try {
redisTemplate
.opsForHash().put(key
, item
, value
);
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public boolean hsetAll(String key
, Map
<String,Object> m
) {
try {
redisTemplate
.opsForHash().putAll(key
, m
);
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public List
<Object> hgetAll(String key
) {
try {
List
<Object> values
= redisTemplate
.opsForHash().values(key
);
return values
;
} catch (Exception e
) {
e
.printStackTrace();
}
return null
;
}
public boolean hset(String key
, String item
, Object value
, long time
) {
try {
redisTemplate
.opsForHash().put(key
, item
, value
);
if (time
> 0) {
expire(key
, time
);
}
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public void hdel(String key
, Object
... item
) {
redisTemplate
.opsForHash().delete(key
, item
);
}
public boolean hHasKey(String key
, String item
) {
return redisTemplate
.opsForHash().hasKey(key
, item
);
}
public Long
hincr(String key
, String item
, int by
) {
return redisTemplate
.opsForHash().increment(key
, item
, by
);
}
public Long
hdecr(String key
, String item
, int by
) {
return redisTemplate
.opsForHash().increment(key
, item
, -by
);
}
public Set
<Object> sGet(String key
) {
try {
return redisTemplate
.opsForSet().members(key
);
} catch (Exception e
) {
e
.printStackTrace();
return null
;
}
}
public boolean sHasKey(String key
, Object value
) {
try {
return redisTemplate
.opsForSet().isMember(key
, value
);
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public long sSet(String key
, Object
... values
) {
try {
return redisTemplate
.opsForSet().add(key
, values
);
} catch (Exception e
) {
e
.printStackTrace();
return 0;
}
}
public long sSetAndTime(String key
, long time
, Object
... values
) {
try {
Long count
= redisTemplate
.opsForSet().add(key
, values
);
if (time
> 0)
expire(key
, time
);
return count
;
} catch (Exception e
) {
e
.printStackTrace();
return 0;
}
}
public long sGetSetSize(String key
) {
try {
return redisTemplate
.opsForSet().size(key
);
} catch (Exception e
) {
e
.printStackTrace();
return 0;
}
}
public long setRemove(String key
, Object
... values
) {
try {
Long count
= redisTemplate
.opsForSet().remove(key
, values
);
return count
;
} catch (Exception e
) {
e
.printStackTrace();
return 0;
}
}
public List
<Object> lGet(String key
, long start
, long end
) {
try {
return redisTemplate
.opsForList().range(key
, start
, end
);
} catch (Exception e
) {
e
.printStackTrace();
return null
;
}
}
public long lGetListSize(String key
) {
try {
return redisTemplate
.opsForList().size(key
);
} catch (Exception e
) {
e
.printStackTrace();
return 0;
}
}
public Object
lGetIndex(String key
, long index
) {
try {
return redisTemplate
.opsForList().index(key
, index
);
} catch (Exception e
) {
e
.printStackTrace();
return null
;
}
}
public boolean lSet(String key
, Object value
) {
try {
redisTemplate
.opsForList().rightPush(key
, value
);
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public boolean lSet(String key
, Object value
, long time
) {
try {
redisTemplate
.opsForList().rightPush(key
, value
);
if (time
> 0)
expire(key
, time
);
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public boolean lSet(String key
, List
<Object> value
) {
try {
redisTemplate
.opsForList().rightPushAll(key
, value
);
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public boolean lSet(String key
, List
<Object> value
, long time
) {
try {
redisTemplate
.opsForList().rightPushAll(key
, value
);
if (time
> 0)
expire(key
, time
);
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public boolean lUpdateIndex(String key
, long index
, Object value
) {
try {
redisTemplate
.opsForList().set(key
, index
, value
);
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public long lRemove(String key
, long count
, Object value
) {
try {
Long remove
= redisTemplate
.opsForList().remove(key
, count
, value
);
return remove
;
} catch (Exception e
) {
e
.printStackTrace();
return 0;
}
}
}
项目中只用到了工具类中部分方法,涉及到的jar包自行导入。
业务调用
@Autowired
private RedisUtil redisUtil
;
public static final String key
="dd_push_data";
@Scheduled(cron
= "0 30 14 * * ?")
@Scheduled(fixedRate
=2*60*1000)
private void configureTasks() {
String value
= System
.currentTimeMillis()+"";
int expire
=1000 * 60 * 5;
Date date
= new Date();
boolean redisSetnx
= redisUtil
.getRedisSetNX(key
,value
);
if(!redisSetnx
) {
Object val
= redisUtil
.get(key
);
if(val
!= null
&& (Long
.valueOf(val
.toString())+expire
) > date
.getTime()) {
log
.info("分布式锁未释放=======");
}else {
redisUtil
.del(key
);
redisUtil
.getRedisSetNX(key
,value
);
pushData();
redisUtil
.del(key
);
}
}else{
pushData();
redisUtil
.del(key
);
}
}
记录代码,以便以后再次使用好找。