Redis在实际工作的几种使用方法,其中最吸引笔者的是Redis在分布式锁方面的应用。在第二段代码中我会贴出笔者在练习中苏哦用的代码
/**
* 功能描述: Redis的几种常用工具方法,其中Redis分布式锁注意setIfAbsent方法的使用
* @param:
* @return:
* @auther: Rhine
* @date: 2018/11/12 23:42
*/
public class RedisUtil {
@Autowired
private RedisTemplate redisTemplate;
/**
* 批量删除对应的value
* @param keys
*/
public void remove(final String... keys){
for(String key:keys){
remove(key);
}
}
/**
* 批量删除key
* @param pattern
*/
public void removePattern(final String pattern){
Set<Serializable> keys=redisTemplate.keys(pattern);
if (keys.size()>0){
redisTemplate.delete(keys);
}
}
/**
* 删除对应的value
* @param key
*/
public void remove(final String key){
if (exists(key)){
redisTemplate.delete(key);
}
}
/**
* 判断缓存中是否有对应的value
* @param key
* @return
*/
public boolean exists(final String key){
return redisTemplate.hasKey(key);
}
/**
* 读取缓存
* @param key
* @return
*/
public Object get(final String key){
Object result=null;
ValueOperations<Serializable,Object> operations=redisTemplate.opsForValue();
result=operations.get(key);
return result;
}
/**
* 写入缓存
* @param key
* @param value
* @return
*/
public boolean set(final String key,Object value){
boolean result=false;
try{
ValueOperations<Serializable,Object> operations=redisTemplate.opsForValue();
operations.set(key,value);
result=true;
}catch (Exception e){
//log.error("RedisUtil set exeption",e);
}
return result;
}
/**
* 写入缓存
* @param key
* @param value
* @param expireTime
* @return
*/
public boolean set(final String key,Object value,long expireTime){
boolean result=false;
try{
ValueOperations<Serializable,Object> operations=redisTemplate.opsForValue();
operations.set(key,value);
redisTemplate.expire(key,expireTime,TimeUnit.SECONDS);
result=true;
}catch (Exception e){
//log.error("RedisUtil set exception",e);
}
return result;
}
/**
* 写入缓存
* 当且仅当key不存在,若给定的key已经存在,则不做任何动作
* @param key
* @param value
* @return
*/
public boolean setIfAbsent(final String key,Object value){
boolean result=false;
try{
ValueOperations<Serializable,Object> operations=redisTemplate.opsForValue();
result=operations.setIfAbsent(key,value);
}catch (Exception e){
//log.error("RedisUtil setIfAbsent exception",e);
}
return result;
}
/**
* 写入缓存
* 当且仅当key不存在,若给定的key已经存在,则不做任何动作
* @param key
* @param value true:设置成功; false:设置失败,已经存在
* @param expireTime
* @return
*/
public boolean setIfAbsent(final String key,Object value,long expireTime){
boolean result=false;
try{
ValueOperations<Serializable,Object> operations=redisTemplate.opsForValue();
result=operations.setIfAbsent(key,value);
if (result){
redisTemplate.expire(key,expireTime,TimeUnit.SECONDS);
}
}catch (Exception e){
//log.error("RedisUtil setIfAbsent exception",e);
}
return result;
}
/**
* 利用指定key作为Redis更新锁(锁有过期时长)
* @param key
* @param cacheSeconds
* @return 获得锁则返回true,否则返回false
*/
public boolean tryLock(String key,long cacheSeconds){
boolean isLock=false;
try {
isLock=setIfAbsent(key,"",cacheSeconds);
}catch (Exception e){
//log.error("RedisUtil tryLock exception",e);
}
return isLock;
}
}
下面是Redis获取锁和删除锁的一对操作,因为Redis的单线程属性以及setIfAbsent方法,常用于商品秒杀的场景。用syn注解虽然可以解决同步的问题,但是此操作是每次让一个线程进入方法,势必会导致程序的运行的时间过长,不能满足实际的需求,这里推荐使用Redis分布式锁。日常使用中,按照先上锁,运行代码,解锁的步骤运行。
/**
* @Author Rhine
* @Date 2018/11/8 2:37
**/
@Component
@Slf4j
public class RedisLock {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 功能描述: 加锁
* @param: key value 当前时间+超时时间
* @return: boolean
* @auther: Rhine
* @date: 2018/11/8 2:40
*/
public boolean lock(String key,String value){
if (redisTemplate.opsForValue().setIfAbsent(key, value)){
return true;
}
String currentValue=redisTemplate.opsForValue().get(key);
//如果锁过期
if (!StringUtils.isEmpty(currentValue)&&Long.parseLong(currentValue)<System.currentTimeMillis()){
//获取上一个锁的时间
String oldValue=redisTemplate.opsForValue().getAndSet(key, value);
if (!StringUtils.isEmpty(oldValue)&&oldValue.equals(currentValue)){
return true;
}
}
return false;
}
/**
* 功能描述: 解锁
* @param: [key, value]
* @return: void
* @auther: Rhine
* @date: 2018/11/8 3:03
*/
public void unlock(String key,String value){
try{
String currentValue=redisTemplate.opsForValue().get(key);
if (!StringUtils.isEmpty(currentValue)&¤tValue.equals(value)){
redisTemplate.opsForValue().getOperations().delete(key);
}
}catch (Exception e){
log.error("【redis分布式锁】 解锁异常,{}",e);
}
}
}