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
| BuyController.java
@RestController
public class BuyController {
private final SellService sellService;
public BuyController(SellService sellService) {
this.sellService = sellService;
}
@GetMapping("/quickBuy/{item}/{buyer}")
public String quickBuy(@PathVariable String item, @PathVariable String buyer) {
String res = sellService.quickBuy(item, buyer);
return res.equals("1") ? buyer + " Success" : buyer + "Fail";
}
@GetMapping("/quickBuy/benchMark")
public String benchMark() {
for (int i = 0; i < 15; i++) {
new BenchMarkTest().start();
}
return "Success";
}
}
SellService.java
@Service
public class SellService {
private final RedisTemplate redisTemplate;
public SellService(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public String quickBuy(String item, String buyer) {
String luaScript = """
local buyer=ARGV[1];
local productName=KEYS[1];
local leftCount=tonumber(redis.call('get',productName));
if(leftCount<=0) then
return 0
else
redis.call('decrby',productName,1);
redis.call('rpush',"buyerList",buyer)
return 1
end
""";
// 如果这里不设置序列化器,会使用默认的Jdk会序列器,导致key和value有乱码,而且会导致上面的lua脚本查询不到数据。
// 当然这里的代码可以移到配置文件中
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
// 注意,这里必须使用Long返回类型,因为redis中的Integer对应java中的Long
RedisScript<Long> defaultRedisScript = new DefaultRedisScript<>(luaScript, Long.class);
Object res = redisTemplate.execute(defaultRedisScript, Collections.singletonList(item), buyer);
return res.toString();
}
}
BenchMarkTest.java
public class BenchMarkTest extends Thread {
@Override
public void run() {
new QuickBuyClient().quickBuy("Gold", "buyer" + Thread.currentThread().getName());
}
}
QuickBuyClient.java
public class QuickBuyClient {
private final RestTemplate restTemplate = new RestTemplate();
public void quickBuy(String item, String buyer) {
String res = restTemplate.getForObject("http://localhost:8080/quickBuy/{item}/{buyer}", String.class, item, buyer);
System.out.println("秒杀结果:" + res);
}
}
|