在 Spring Boot 项目里,运用 Redisson 实现分布式锁来处理销售扣减库存和入库增加库存,且同时操作一个库存值,可按以下步骤完成:
1、添加依赖#
在pom.xml
文件里添加 Redisson 和 Spring Boot Data Redis 的依赖:
1
2
3
4
5
6
7
8
9
10
11
12
13
| <dependencies>
<!-- Redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.16.2</version>
</dependency>
<!-- Spring Boot Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
|
2、配置 Redisson#
在application.yml
文件里配置 Redis:
1
2
3
4
| spring:
redis:
host: localhost
port: 6379
|
3、在service中使用#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
| import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class InventoryService {
@Autowired
private RedissonClient redissonClient;
// 库存键名
private static final String INVENTORY_KEY = "product:inventory:1";
/**
* 销售扣减库存
* @param quantity 扣减数量
* @return 是否成功
*/
public boolean deductInventory(int quantity) {
// 获取分布式锁
RLock lock = redissonClient.getLock(INVENTORY_KEY);
try {
// 尝试加锁,等待10秒,自动释放锁时间为30秒
if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
// 模拟从Redis获取当前库存
Integer currentInventory = getInventoryFromRedis();
if (currentInventory != null && currentInventory >= quantity) {
// 扣减库存
int newInventory = currentInventory - quantity;
// 更新Redis中的库存
updateInventoryInRedis(newInventory);
return true;
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// 释放锁
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
return false;
}
/**
* 入库增加库存
* @param quantity 增加数量
*/
public void addInventory(int quantity) {
// 获取分布式锁
RLock lock = redissonClient.getLock(INVENTORY_KEY);
try {
// 尝试加锁,等待10秒,自动释放锁时间为30秒
if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
// 模拟从Redis获取当前库存
Integer currentInventory = getInventoryFromRedis();
if (currentInventory != null) {
// 增加库存
int newInventory = currentInventory + quantity;
// 更新Redis中的库存
updateInventoryInRedis(newInventory);
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// 释放锁
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
/**
* 从Redis获取当前库存
* @return 当前库存
*/
private Integer getInventoryFromRedis() {
// 这里需要根据实际情况实现从Redis获取库存的逻辑
return 100;
}
/**
* 更新Redis中的库存
* @param newInventory 新的库存数量
*/
private void updateInventoryInRedis(int newInventory) {
// 这里需要根据实际情况实现更新Redis库存的逻辑
}
}
|
代码解释
- 获取分布式锁:借助redissonClient.getLock(INVENTORY_KEY)获取分布式锁。
- 加锁操作:运用tryLock方法尝试加锁,并且设置了等待时间和自动释放锁的时间。
- 业务逻辑处理:在加锁成功之后,对库存进行扣减或者增加操作。
- 释放锁:在finally块中释放锁,以此保证锁一定会被释放。
4、使用服务类#
在控制器或者其他服务类中注入InventoryService并调用相应的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class InventoryController {
@Autowired
private InventoryService inventoryService;
@GetMapping("/deduct")
public String deductInventory(@RequestParam int quantity) {
if (inventoryService.deductInventory(quantity)) {
return "扣减库存成功";
}
return "扣减库存失败";
}
@GetMapping("/add")
public String addInventory(@RequestParam int quantity) {
inventoryService.addInventory(quantity);
return "增加库存成功";
}
}
|