spring cloud网站简易接入基于redis的分布式锁(基于https://spring.academy/guides/spring-spring-distributed-lock)
前言:在19年自己写了一套spring cloud系统,当时对并发和锁这块并没有做任何处理,基本上是按照单节点来开发,突然想对系统进行一波改造升级。如果懂英文的话,可以直接参看参考网站,里面有详细的描述,本文仅使用我自己的系统来说明原文点我
准备条件: spring cloud系统 redis
1. 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring distributed lock -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-redis</artifactId>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
2. 注入实体类。如果和我一样又common模块的,可以将这部分直接写到common模块中
代码如下,参考链接完成。lock_name 可以自定义,是写入到redis中时的一部分
package com.lj2508.common.lock.redis.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.integration.redis.util.RedisLockRegistry;
@Configuration
public class RedisLockConfig {
private static final String LOCK_NAME = "lj2508-distributed-lock";
@Bean(destroyMethod = "destroy")
public RedisLockRegistry redisLockRegistry( RedisConnectionFactory redisConnectionFactory ) {
return new RedisLockRegistry(redisConnectionFactory, LOCK_NAME);
}
}
3. 在系统中使用分布式锁
- 注入在需要使用的类中注入分布式锁
@Autowired
private LockRegistry redisLockReistry;
- 代码中的应用
Lock lock = null;
String key = "saveBanner-1";
try {
lock = redisLockReistry.obtain(key);
} catch (Exception e) {
// in a production environment this should be a log statement
System.out.println(String.format("Unable to obtain lock: %s", key));
}
Mess returnVal = null;
try {
if (lock.tryLock()) {
//此处用来执行之前的业务代码
System.out.println("get lock successful");
returnVal = wxService.saveBanner(banner);;
} else {
System.out.println("get lock unsuccessful");
returnVal = new Mess(2006, "微服务不可用,分布式锁获取失败,请稍后再试!");
}
return returnVal;
} catch (Exception e) {
// in a production environment this should log and do something else
e.printStackTrace();
if (e.getMessage().equals("com.netflix.client.ClientException: Load balancer does not have available server for client: Wxapp"))
return new Mess(2006, "微服务不可用,请稍后再试!");
return new Mess(40001,"新增失败,请检查内容是否正确!");
} finally {
// always have this in a `finally` block in case anything goes wrong
lock.unlock();
}
然后测试,在第一个业务进行实。第二个请求,无法在进行操作
4. 原理猜测
通过查看redis的数据来看,是根据设置的lock_name和获取锁时的字符串来形成key,然后随机生成一个key存到redis中,并设置过期时间来判断锁是否有效, 和防止删除其他人设置的锁来实现的,其中应该还有一些过期时间的设置,以及其中可能涉及一些刷新锁的效果,我并没有去研究,因为目前对系统来说已经足够用。4中的代码也是参考文中链接来实现。链接来源google搜索 spring cloud distributed lock redis第一篇文章
如有错误,可在评论中指出
评论区