文章目录
-
- 一、简介
-
- (1)`SpringBoot2.x`配置`Redisson`注意事项
- 二、`Demo` 测试
-
- (1)配置 + 代码
- (2)`nginx` 负载均衡
- (3)压测
- 三、问题
-
- (1)若获得锁后,业务逻辑长时间没有释放锁?
- (2)若获得锁后,业务逻辑没有完成而锁过期(释放)?数据不一致?
- (3)若要释放锁时,进程挂了等等?
- (4)等待锁时,超时后,还没获得锁,之后业务该怎么办?
一、简介
Based on high-performance async and lock-free Java Redis client and Netty framework.
基于高能性异步锁自由Java Redis客户端 和 Netty框架
参数配置:https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95
(1) SpringBoot2.x
配置 Redisson
注意事项
SpringBoot2.x
Redisson
在
SpringBoot2.x
默认使用
Lettuce
冲突:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
// 会与下面这个冲突,二者存一
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.11.2</version>
</dependency>
若加入
redisson-spring-boot-starter
,里面会排除
lettuce
// 此配置会排除 Lettuce,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
二、 Demo
测试
Demo
(1)配置 + 代码
-
pom.xml
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.11.2</version>
</dependency>
-
RedisConfig.java
@Configuration
public class RedisConfig {
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(0);
return Redisson.create(config);
}
}
- Demo
@RestController
@RequestMapping("/redisson")
public class RedissonController {
@Autowired
private RedissonClient redissonClient;
@Autowired
private RedisDao redisDao;
@RequestMapping(value = "/sku/init")
public String initSku() {
redisDao.setString("product_sku", "4000");
return "初始化库存成功";
}
@RequestMapping("/sku/reduce")
public void reduce() {
RLock lock = redissonClient.getLock("product_sku");
boolean locked = false;
try {
locked = lock.tryLock(0, 10, TimeUnit.SECONDS);
if (locked) {
System.out.println("获取锁成功。。。");
} else {
System.out.println("获取锁失败。。。");
}
int sku = Integer.parseInt(redisDao.get("product_sku"));
if (--sku < 0) {
System.out.println("库存不足。。。");
return;
}
redisDao.setString("product_sku", Integer.toString(sku));
System.out.println("减库存成功: " + sku);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (!locked) {
System.out.println("获取锁失败。。。");
}
lock.unlock();
}
}
}
(2) nginx
负载均衡
nginx
-
sudo docker pull nginx
-
sudo docker run --name=nginx -p 8000:80 -d nginx
访问 localhost:8000
,即可访问 nginx 页面
- 挂载运行
# ro:只读
sudo docker run --name=nginx -p 80:80 \
-v /home/donald/Documents/Docker/Nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
-d nginx
upstream redis {
server 192.168.0.143:8080;
server 192.168.0.143:8081;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://redis;
}
}
-
运行sudo docker exec -it nginx bash
(3)压测
采用
ab
压测
sudo docker run --rm jordi/ab -k -c 200 -n 4000 http://192.168.0.143:8080/redisson/sku/reduce
- 使用
在此压测情况下,库存可刚好消费完lock.lock( 10, TimeUnit.SECONDS);
压测结果如图:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL9smaOFTUqJGaa1mYoplMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLxgjMyMzMxkTMxADMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
- 使用
在此压测情况下,库存大部分情况下均消费不完locked = lock.tryLock(1, 10, TimeUnit.SECONDS);
压测结果如图:
且有如下异常:
三、问题
如图: