- SpringBoot使用Redis实现分布式锁
- 分布式锁说明
- SpringBoot中实现
- maven依赖
- redis配置
- java代码
Java中的锁:当多个线程去访问共享数据时,防止一些操作被覆盖(并发问题),这个时候就需要用到抢锁机制,抢到锁的线程才能进行操作,其余线程等待锁释放并抢到锁才能进行操作,例如Sychonized,Lock等。
分布式锁和java中的锁最大的区别在于共享资源是由多个进程去访问,这时候线程之间的锁机制就无法起到作用了,所以就需要引入一些可以被所有服务都能访问的外部服务来让实现锁,例如数据库,Redis,Zookeeper等
redis配置org.springframework.boot spring-boot-starter-data-redis
spring.redis.hostName = 地址 spring.redis.port = 6379 spring.redis.password = pwd spring.redis.enableTransactionSupport = falsejava代码
package com.servingcloud.foreign.service.common.util;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtilExt {
private final static long DEFAULT_TIMEOUT = 30000;
private final static String PWD_KEY = "redis_lock";
@Resource(
name = "stringRedisTemplate"
)
private RedisTemplate stringRedisTemplate;
public String getSortStr(Object obj){
String objStr = JSON.toJSONString(obj);
return MD5Util.generate(PWD_KEY,"1",objStr);
}
public boolean getLock(String key){
//value值为系统当前时间
if(stringRedisTemplate.opsForValue().setIfAbsent(key,String.valueOf(System.currentTimeMillis()))){
//设置超时时间 防止死锁
stringRedisTemplate.expire(key,DEFAULT_TIMEOUT,TimeUnit.MILLISECONDS);
return true;
}
//获取上锁时间 判断锁是否超时,超时则删除key(redis重启会造成重启时间内一些过期的key未被清理),防止死锁
String valueTime = stringRedisTemplate.opsForValue().get(key);
if(StringUtils.isNotEmpty(valueTime) && System.currentTimeMillis()-Long.parseLong(valueTime)>DEFAULT_TIMEOUT){
//释放锁 再次抢锁
unLock(key);
return getLock(key);
}
return false;
}
public void unLock(String key){
stringRedisTemplate.opsForValue().getOperations().delete(key);
}
}



