redisson分布式锁并发测试
模拟秒杀抢购场景,100库存,用jmeter并发测试,起300个线程并发请求2次,总计600个请求数,最后查看库存是否为负数,证明分布式锁是否锁住了库存。
注意:分布式锁并不是实现秒杀最佳方式,本文只是侧重说明分布式锁
一、编写相关代码
1、添加依赖项
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web:2.2.0.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-data-redis:2.2.0.RELEASE'
compile 'org.redisson:redisson-spring-boot-starter:3.11.5'
compileOnly 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
2、添加启动类
package com.opensource.components.lock;
import org.redisson.Redisson;
import org.redisson.config.Config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class DistributedLockApplication {
public static void main(String[] args) {
SpringApplication.run(DistributedLockApplication.class, args);
}
@Bean
public Redisson redisson() {
Config config = new Config();
config.useClusterServers().addNodeAddress("redis://172.16.10.212:6379", "redis://172.16.10.212:6380", "redis://172.16.10.212:6381");
return (Redisson) Redisson.create(config);
}
}
3、添加商品接口类
package com.opensource.components.lock;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@Slf4j
@RestController
public class ItemController {
private final static String ITEM_COUNT = "item:count";
private final static String LOCK_KEY = "item:count:lock";
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private Redisson redisson;
/**
* 初始化商品数量
*
* @param value
* @return
*/
@RequestMapping("/setCount")
public String setCount(int value) {
stringRedisTemplate.opsForValue().set(ITEM_COUNT, value + "");
return "success";
}
/**
* 查询商品数量
*
* @return
*/
@RequestMapping("/getCount")
public String getCount() {
return stringRedisTemplate.opsForValue().get(ITEM_COUNT);
}
/**
* 模拟秒杀抢购
*
* @return
*/
@RequestMapping("/spike")
public String spike() {
String result = "fail";
RLock lock = redisson.getLock(LOCK_KEY);
boolean isLock = false;
lock.lock(30, TimeUnit.SECONDS);
if (lock.isLocked()) {
try {
int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get(ITEM_COUNT).toString());
if (stock > 0) {
result = "success";
stringRedisTemplate.opsForValue().set(ITEM_COUNT, (stock - 1) + "");
} else {
result = "fail";
}
} finally {
if (lock.isHeldByCurrentThread()) {
//手动释放锁
lock.unlock();
}
}
}
log.info(Thread.currentThread().getName() + ", result: " + result);
return result;
}
}