当前位置:网站首页>分布式锁解决方案之Redis实现
分布式锁解决方案之Redis实现
2022-07-26 10:28:00 【范学博】
spring boot 版本 2.1.6.RELEASE
下面是分布式锁的获取和释放,成员变量:StringRedisTemplate(springboot整合redis获取redis,也可通过注入jedis实现,实现思路是一致的,我会在文末附上获取redis的实现)。
再来看看一些redis的基本命令: SETNX key value (stringRedisTemplate.opsForValue().setIfAbsent())
如果key不存在,就设置key对应字符串value。在这种情况下,该命令和SET一样。当key已经存在时,就不做任何操作。SETNX是”SET if Not eXists”。 expire KEY seconds (stringRedisTemplate.expire())
设置key的过期时间。如果key已过期,将会被自动删除。 del KEY (stringRedisTemplate.delete())
删除key
分布式锁的获取与释放
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* @author fanxuebo
* @description 分布式锁
* @company
* @create 2019/1/10 17:48
*/
public class DistributedLock {
private static final Logger LOGGER = LoggerFactory.getLogger(DistributedLock.class);
private StringRedisTemplate stringRedisTemplate;
public DistributedLock(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}
/**
* @Author fanxuebo
* @Date 2019/1/11 10:10
* @Description 获取锁,锁的名称,获取锁超时时间,释放锁的超时时间
**/
public String lockWithTimeout(String lockName, long timeout) {
String retIdentifier = null;
try {
String identifier = UUID.randomUUID().toString();// 随机生成一个value
String lockKey = "lock:" + lockName;// 锁名,即key值
int lockExpire = (int) (timeout / 1000);// 超时时间,上锁后超过此时间则自动释放锁
while (true) {
if (stringRedisTemplate.opsForValue().setIfAbsent(lockKey, identifier)) {
LOGGER.info("{}:获取到锁lockKey:{}", Thread.currentThread().getName(), lockKey);
stringRedisTemplate.expire(lockKey, lockExpire, TimeUnit.SECONDS);
retIdentifier = identifier;// 返回value值,用于释放锁时间确认
break;
}
// 返回-1代表key没有设置超时时间,为key设置一个超时时间
if (stringRedisTemplate.getExpire(lockKey) == -1L) {
stringRedisTemplate.expire(lockKey, lockExpire, TimeUnit.SECONDS);
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("获取锁异常:[{}]", e.getStackTrace()[0]);
}
return retIdentifier;
}
/**
* @Author fanxuebo
* @Date 2019/1/11 10:09
* @Description 释放锁
**/
public boolean releaseLock(String lockName, String identifier) {
String lockKey = "lock:" + lockName;
boolean retFlag = false;
try {
while (true) {
stringRedisTemplate.watch(lockKey);// 监视lock,准备开始事务
// 通过前面返回的value值判断是不是该锁,若是该锁,则删除,释放锁
if (identifier.equals(stringRedisTemplate.opsForValue().get(lockKey))) {
LOGGER.info("{}:删除锁lockKey:{}", Thread.currentThread().getName(), lockKey);
stringRedisTemplate.delete(lockKey);
retFlag = true;
}
stringRedisTemplate.unwatch();
break;
}
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("释放锁异常:[{}]", e.getStackTrace()[0]);
}
return retFlag;
}
}在需要上锁的代码块只需做如下操作:
DistributedLock distributedLock = new DistributedLock(stringRedisTemplate);
String lockName = XXX;
String identifier = null;
try {
identifier = distributedLock.lockWithTimeout(lockName, 3000);
//需要控制事务的代码
distributedLock.releaseLock(lockName, identifier);
} catch (Exception e) {
distributedLock.releaseLock(lockName, identifier);
}在获取锁方法处可做改进,传入获取锁的时间,在一定时间内获取,若未获取到返回的标识为NULL。
long end = System.currentTimeMillis() + acquireTimeout;
while (System.currentTimeMillis() < end) {}DistributedLock distributedLock = new DistributedLock(stringRedisTemplate);
String lockName = XXX;
String identifier = null;
try {
identifier = distributedLock.lockWithTimeout(lockName, 3000);
if (StringUtils.isBlank(identifier)) {
//获取锁等待超时的处理
}
//需要控制事务的代码
distributedLock.releaseLock(lockName, identifier);
} catch (Exception e) {
distributedLock.releaseLock(lockName, identifier);
}
springboot整合reids:
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<!-- <version>2.1.6.RELEASE</version> -->
</dependency>import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @author fanxuebo
* @description redis配置类
* @company
* @createDate 2019-11-27 08:46:17 星期三
*/
@Configuration
public class RedisConfiguration {
/**
* @Author fanxuebo
* @Date 2019/11/27 9:05
* @Description jdk序列方式,用来保存对象
**/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
return getRedisTemplate(redisTemplate, redisConnectionFactory);
}
/**
* @Author fanxuebo
* @Date 2019/11/27 9:06
* @Description string序列方式,用于存储字符串格式
**/
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
return (StringRedisTemplate) getRedisTemplate(stringRedisTemplate, redisConnectionFactory);
}
private RedisTemplate getRedisTemplate(RedisTemplate redisTemplate, RedisConnectionFactory redisConnectionFactory) {
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 设置value的序列化规则和 key的序列化规则
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
配置文件:
spring:
redis:
database:
host:
port: 6379
password:
timeout: 5000
jedis:
pool:
max-active: 50
max-wait: 5000希望阅读后会让你们有所收获,本文待完善。。。
边栏推荐
- Using native JS to realize custom scroll bar (click to reach, drag to reach)
- [Halcon vision] software programming ideas
- Data communication foundation - layer 2 switching principle
- [Halcon vision] image filtering
- [Qualcomm][Network] qti服务分析
- Some cutting-edge research work sharing of SAP ABAP NetWeaver containerization
- How to use Gmail to pick up / send mail on Foxmail
- cavans实现静态滚动弹幕
- [award-winning question] ask Judea pearl, the Turing prize winner and the father of Bayesian networks
- 函数模板与同名的非模板函数不可以重载(重载的定义)
猜你喜欢

数据库的复习--3.SQL语言

Learning about tensorflow (I)

The CLOB field cannot be converted when querying Damon database

Like, "new programmer" e-book is free for a limited time!

Dynamically determine file types through links
![[Halcon vision] threshold segmentation](/img/1c/e2463a796f99804a55680b69e714a6.png)
[Halcon vision] threshold segmentation

【Halcon视觉】图像的傅里叶变换

INSTALL_ FAILED_ SHARED_ USER_ Incompatible error resolution

【Halcon视觉】编程逻辑
软件打不开了
随机推荐
Android greendao数据库的使用
Using native JS to realize custom scroll bar (click to reach, drag to reach)
Listening freely, the next stop of online text traffic competition?
INSTALL_ FAILED_ SHARED_ USER_ Incompatible error resolution
Using undertow, Nacos offline logout delay after service stop
Learning about tensorflow (II)
[Halcon vision] affine transformation
js下载文件,FileSaver.js导出txt、excel文件
Some cutting-edge research work sharing of SAP ABAP NetWeaver containerization
[Qualcomm][Network] qti服务分析
Basics of data communication - basic knowledge of network
Learning about opencv (1)
【Halcon视觉】图像滤波
议程速递 | 7月27日分论坛议程一览
What is wrong about the description of function templates (how to solve link format errors)
All codes of Tetris
videojs转canvas暂停、播放、切换视频
【Halcon视觉】形态学膨胀
[Halcon vision] Fourier transform of image
Function templates and non template functions with the same name cannot be overloaded (definition of overloads)