Redis的分布式锁实现代码(商品秒杀)
准备工作
下载Apache JMeter软件:模拟多线程,高并发情况
导入依赖
导入redis包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
分布式锁代码
该方法有三个接口
①init():初始化商品数量为100
②synchronizedBuy():使用synchronizedBuy锁模拟商品秒杀
③redisBuy():使用redis分布式锁模拟商品秒杀
@RestController
public class OrderController {
@Autowired
private RedisTemplate redisTemplate;
@GetMapping("/initCount")
public String init(){
redisTemplate.opsForValue().set("count","100");
return "库存初始化成功";
}
/**
* @author:
* @description: synchronized锁
* @date: 2021/10/23
* @param
* @return java.lang.String
*/
@GetMapping("/synchronizedBuy")
public String synchronizedBuy(){
synchronized (OrderController.class){
Integer count = Integer.parseInt(redisTemplate.opsForValue().get("count").toString());
if (count > 0)
{
Integer realCount = count - 1;
System.out.println("购买商品成功,库存为:" + realCount.toString());
redisTemplate.opsForValue().set("count",realCount.toString());
}else {
System.out.println("库存不足,购买失败");
}
return "ok";
}
}
/**
* @author:
* @description: 使用分布式锁
* @date: 2021/10/23
* @param
* @return java.lang.String
*/
@GetMapping("/redisBuy")
public String redisBuy(){
String lockKey = "ShangPin";
String clientId = UUID.randomUUID().toString();
try {
//setnx加锁
//setIfAbsent()方法:如果这个锁已经存在,则返回flase,获得锁失败,如果返回true则说明加锁成功
Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey,clientId,10, TimeUnit.SECONDS);
if (lock)
{
//执行购买业务
int count1 = Integer.parseInt(redisTemplate.opsForValue().get("count").toString());
if (count1 > 0)
{
Integer realCount = count1 - 1;
System.out.println("购买商品成功,库存为:" + realCount.toString());
redisTemplate.opsForValue().set("count",realCount.toString());
}else {
System.out.println("库存不足,购买失败");
}
}else {
try {
//获取锁失败,每隔0.1秒再获取
Thread.sleep(100);
redisBuy();
}catch (InterruptedException e)
{
e.printStackTrace();
}
}
}catch (Exception e){
e.printStackTrace();
}finally {
//删锁,判断当前客户端的clientId与redis持有的一样
if(clientId.equals(redisTemplate.opsForValue().get(lockKey)))
redisTemplate.delete(lockKey);
}
return "ok";
}
}
启动项目
为了模拟集群环境,idea需要启动两个端口不一样的服务,方法如下:
修改好后,端口为17055时启动项目
再把端口修改为17054,再次启动项目
启动Jmeter
使用Apache Jmeter软件模拟多线程并发。
Jmeter分别调用17055端口和17054端口的synchronizedBuy()接口和redisBuy()接口,分别模拟80个线程,以及17055端口的init()接口,具体配置如下。
调用17054的synchronizedBuy()接口
调用17055的synchronizedBuy()接口
其余几个接口可仿照上面内容进行创建。
运行结果
首先调用init()接口进行商品初始化操作。
单击环境下,使用synchronized锁
只调用一个接口,结果如下所示:
商品有100件,只模拟了80个线程,所有商品应该卖出80件,可以看出在单击环境下是哟synchronized锁没有问题。
购买商品成功,库存为:99
购买商品成功,库存为:98
购买商品成功,库存为:97
购买商品成功,库存为:96
购买商品成功,库存为:95
购买商品成功,库存为:94
购买商品成功,库存为:93
购买商品成功,库存为:92
购买商品成功,库存为:91
购买商品成功,库存为:90
购买商品成功,库存为:89
购买商品成功,库存为:88
购买商品成功,库存为:87
购买商品成功,库存为:86
购买商品成功,库存为:85
购买商品成功,库存为:84
购买商品成功,库存为:83
购买商品成功,库存为:82
购买商品成功,库存为:81
购买商品成功,库存为:80
购买商品成功,库存为:79
购买商品成功,库存为:78
购买商品成功,库存为:77
购买商品成功,库存为:76
购买商品成功,库存为:75
购买商品成功,库存为:74
购买商品成功,库存为:73
购买商品成功,库存为:72
购买商品成功,库存为:71
购买商品成功,库存为:70
购买商品成功,库存为:69
购买商品成功,库存为:68
购买商品成功,库存为:67
购买商品成功,库存为:66
购买商品成功,库存为:65
购买商品成功,库存为:64
购买商品成功,库存为:63
购买商品成功,库存为:62
购买商品成功,库存为:61
购买商品成功,库存为:60
购买商品成功,库存为:59
购买商品成功,库存为:58
购买商品成功,库存为:57
购买商品成功,库存为:56
购买商品成功,库存为:55
购买商品成功,库存为:54
购买商品成功,库存为:53
购买商品成功,库存为:52
购买商品成功,库存为:51
购买商品成功,库存为:50
购买商品成功,库存为:49
购买商品成功,库存为:48
购买商品成功,库存为:47
购买商品成功,库存为:46
购买商品成功,库存为:45
购买商品成功,库存为:44
购买商品成功,库存为:43
购买商品成功,库存为:42
购买商品成功,库存为:41
购买商品成功,库存为:40
购买商品成功,库存为:39
购买商品成功,库存为:38
购买商品成功,库存为:37
购买商品成功,库存为:36
购买商品成功,库存为:35
购买商品成功,库存为:34
购买商品成功,库存为:33
购买商品成功,库存为:32
购买商品成功,库存为:31
购买商品成功,库存为:30
购买商品成功,库存为:29
购买商品成功,库存为:28
购买商品成功,库存为:27
购买商品成功,库存为:26
购买商品成功,库存为:25
购买商品成功,库存为:24
购买商品成功,库存为:23
购买商品成功,库存为:22
购买商品成功,库存为:21
购买商品成功,库存为:20
集群环境下,使用synchronized锁
同时选中调用两个不同端口的synchronizedBuy()接口( 模拟集群环境下使用synchronized锁实现商品秒杀的现象)
结果如下:
购买商品成功,库存为:95
购买商品成功,库存为:94
购买商品成功,库存为:93
购买商品成功,库存为:92
购买商品成功,库存为:91
购买商品成功,库存为:90
购买商品成功,库存为:89
购买商品成功,库存为:88
购买商品成功,库存为:87
购买商品成功,库存为:86
购买商品成功,库存为:85
购买商品成功,库存为:84
购买商品成功,库存为:83
购买商品成功,库存为:82
购买商品成功,库存为:81
购买商品成功,库存为:80
购买商品成功,库存为:78
购买商品成功,库存为:77
购买商品成功,库存为:76
购买商品成功,库存为:75
购买商品成功,库存为:74
购买商品成功,库存为:73
购买商品成功,库存为:72
购买商品成功,库存为:71
购买商品成功,库存为:70
购买商品成功,库存为:69
购买商品成功,库存为:67
购买商品成功,库存为:65
购买商品成功,库存为:64
购买商品成功,库存为:62
购买商品成功,库存为:61
购买商品成功,库存为:60
购买商品成功,库存为:58
购买商品成功,库存为:57
购买商品成功,库存为:56
购买商品成功,库存为:55
购买商品成功,库存为:54
购买商品成功,库存为:53
购买商品成功,库存为:51
购买商品成功,库存为:50
购买商品成功,库存为:49
购买商品成功,库存为:48
购买商品成功,库存为:47
购买商品成功,库存为:46
购买商品成功,库存为:45
购买商品成功,库存为:43
购买商品成功,库存为:42
购买商品成功,库存为:40
购买商品成功,库存为:39
购买商品成功,库存为:38
购买商品成功,库存为:37
购买商品成功,库存为:36
购买商品成功,库存为:35
购买商品成功,库存为:34
购买商品成功,库存为:33
购买商品成功,库存为:32
购买商品成功,库存为:30
购买商品成功,库存为:28
购买商品成功,库存为:27
购买商品成功,库存为:25
购买商品成功,库存为:24
购买商品成功,库存为:23
购买商品成功,库存为:22
购买商品成功,库存为:21
购买商品成功,库存为:19
购买商品成功,库存为:18
购买商品成功,库存为:17
购买商品成功,库存为:15
购买商品成功,库存为:13
购买商品成功,库存为:12
购买商品成功,库存为:11
购买商品成功,库存为:10
购买商品成功,库存为:9
购买商品成功,库存为:8
购买商品成功,库存为:7
购买商品成功,库存为:6
购买商品成功,库存为:5
购买商品成功,库存为:4
购买商品成功,库存为:3
购买商品成功,库存为:2
购买商品成功,库存为:99
购买商品成功,库存为:98
购买商品成功,库存为:97
购买商品成功,库存为:96
购买商品成功,库存为:95
购买商品成功,库存为:94
购买商品成功,库存为:93
购买商品成功,库存为:92
购买商品成功,库存为:92
购买商品成功,库存为:91
购买商品成功,库存为:90
购买商品成功,库存为:89
购买商品成功,库存为:88
购买商品成功,库存为:87
购买商品成功,库存为:86
购买商品成功,库存为:85
购买商品成功,库存为:84
购买商品成功,库存为:83
购买商品成功,库存为:82
购买商品成功,库存为:80
购买商品成功,库存为:79
购买商品成功,库存为:78
购买商品成功,库存为:77
购买商品成功,库存为:76
购买商品成功,库存为:71
购买商品成功,库存为:70
购买商品成功,库存为:69
购买商品成功,库存为:68
购买商品成功,库存为:66
购买商品成功,库存为:65
购买商品成功,库存为:64
购买商品成功,库存为:63
购买商品成功,库存为:62
购买商品成功,库存为:61
购买商品成功,库存为:60
购买商品成功,库存为:59
购买商品成功,库存为:57
购买商品成功,库存为:56
购买商品成功,库存为:55
购买商品成功,库存为:54
购买商品成功,库存为:53
购买商品成功,库存为:52
购买商品成功,库存为:51
购买商品成功,库存为:50
购买商品成功,库存为:49
购买商品成功,库存为:48
购买商品成功,库存为:47
购买商品成功,库存为:46
购买商品成功,库存为:45
购买商品成功,库存为:44
购买商品成功,库存为:43
购买商品成功,库存为:42
购买商品成功,库存为:41
购买商品成功,库存为:40
购买商品成功,库存为:39
购买商品成功,库存为:38
购买商品成功,库存为:37
购买商品成功,库存为:36
购买商品成功,库存为:35
购买商品成功,库存为:34
购买商品成功,库存为:32
购买商品成功,库存为:31
购买商品成功,库存为:30
购买商品成功,库存为:29
购买商品成功,库存为:28
购买商品成功,库存为:27
购买商品成功,库存为:26
购买商品成功,库存为:25
购买商品成功,库存为:24
购买商品成功,库存为:23
购买商品成功,库存为:22
购买商品成功,库存为:21
购买商品成功,库存为:20
购买商品成功,库存为:19
购买商品成功,库存为:17
购买商品成功,库存为:16
购买商品成功,库存为:15
购买商品成功,库存为:14
购买商品成功,库存为:13
购买商品成功,库存为:12
可以看出商品已经超卖了。
集群环境下,使用redis分布式锁
运行结果:
购买商品成功,库存为:94
购买商品成功,库存为:93
购买商品成功,库存为:88
购买商品成功,库存为:87
购买商品成功,库存为:85
购买商品成功,库存为:83
购买商品成功,库存为:82
购买商品成功,库存为:81
购买商品成功,库存为:79
购买商品成功,库存为:73
购买商品成功,库存为:67
购买商品成功,库存为:62
购买商品成功,库存为:61
购买商品成功,库存为:58
购买商品成功,库存为:57
购买商品成功,库存为:56
购买商品成功,库存为:55
购买商品成功,库存为:50
购买商品成功,库存为:49
购买商品成功,库存为:47
购买商品成功,库存为:46
购买商品成功,库存为:45
购买商品成功,库存为:44
购买商品成功,库存为:43
购买商品成功,库存为:41
购买商品成功,库存为:40
购买商品成功,库存为:39
购买商品成功,库存为:38
购买商品成功,库存为:37
购买商品成功,库存为:34
购买商品成功,库存为:33
购买商品成功,库存为:32
购买商品成功,库存为:28
购买商品成功,库存为:27
购买商品成功,库存为:23
购买商品成功,库存为:22
购买商品成功,库存为:18
购买商品成功,库存为:17
购买商品成功,库存为:15
购买商品成功,库存为:14
购买商品成功,库存为:13
购买商品成功,库存为:12
购买商品成功,库存为:9
购买商品成功,库存为:8
购买商品成功,库存为:7
购买商品成功,库存为:4
购买商品成功,库存为:3
购买商品成功,库存为:2
库存不足,购买失败
库存不足,购买失败
库存不足,购买失败
购买商品成功,库存为:86
购买商品成功,库存为:84
购买商品成功,库存为:80
购买商品成功,库存为:78
购买商品成功,库存为:77
购买商品成功,库存为:76
购买商品成功,库存为:75
购买商品成功,库存为:74
购买商品成功,库存为:72
购买商品成功,库存为:71
购买商品成功,库存为:70
购买商品成功,库存为:69
购买商品成功,库存为:68
购买商品成功,库存为:66
购买商品成功,库存为:65
购买商品成功,库存为:64
购买商品成功,库存为:63
购买商品成功,库存为:60
购买商品成功,库存为:59
购买商品成功,库存为:54
购买商品成功,库存为:53
购买商品成功,库存为:52
购买商品成功,库存为:51
购买商品成功,库存为:48
购买商品成功,库存为:42
购买商品成功,库存为:36
购买商品成功,库存为:35
购买商品成功,库存为:31
购买商品成功,库存为:30
购买商品成功,库存为:29
购买商品成功,库存为:26
购买商品成功,库存为:25
购买商品成功,库存为:24
购买商品成功,库存为:21
购买商品成功,库存为:20
购买商品成功,库存为:19
购买商品成功,库存为:16
购买商品成功,库存为:11
购买商品成功,库存为:10
购买商品成功,库存为:6
购买商品成功,库存为:5
购买商品成功,库存为:1
购买商品成功,库存为:0
库存不足,购买失败
库存不足,购买失败
可以看出集群环境下使用redis分布式锁刚好买了100件商品,不会出现超卖现象。