只是做个简单的demo测试使用(核心代码)
/**
* 单体架构,没有添加锁(可以使用Synchronization实现单体架构同步代码块)
* */
@RequestMapping("/getVlaue")
public String getVlaue(){
// redisTemplate.opsForValue().set("num","100");
int num = Integer.parseInt(redisTemplate.opsForValue().get("num"));
if(num>0){
num = num -1;
redisTemplate.opsForValue().set("num",zs+"");
}else{
System.out.println("库存不足");
}
System.out.println(redisTemplate.opsForValue().get("num"));
return redisTemplate.opsForValue().get("num");
}
使用redis
//redis实现(存在两个问题
// 1.高并发的情况下,如果两个线程同时进入循环,可能导致加锁失败。
// 2.SETNX 是一个耗时操作,因为它需要判断 Key 是否存在,因为会存在性能问题。)
@RequestMapping("/getRedis")
public String getRedis(){
String lock ="lock";
//为了避免本线程删除其他线程的锁,为每个线程的锁设置唯一的指
String clientId = UUID.randomUUID().toString();
try {
// //1.获取锁
// redisTemplate.opsForValue().set(lock,clientId);
// //2.设置过期时间
// redisTemplate.expire(lock,10,TimeUnit.SECONDS);
//为保证程序的原子性,把1 2两步合并
Boolean result = redisTemplate.opsForValue().setIfAbsent(lock,clientId,10,TimeUnit.SECONDS);
if(!result){
System.out.println("error");
return "error";
}
int num = Integer.parseInt(redisTemplate.opsForValue().get("num"));
if(num > 0){
num = num -1;//
redisTemplate.opsForValue().set("num",num+"");
System.out.println("剩余"+num);
}else{
System.out.println("库存不足");
}
}finally {
//只有值为本线程的值时才释放锁
if(clientId.equals(redisTemplate.opsForValue().get("lock"))){
redisTemplate.delete(lock);
}
}
return redisTemplate.opsForValue().get("num");
}
使用redisson,简单实用
//合适解决方案
@RequestMapping("/getRedisson")
public String getRedisson(){
String lockKey = "lock";
String clientId = UUID.randomUUID().toString();
//获取锁
RLock lock =redisson.getLock(lockKey);
try {
//加锁
lock.lock(30,TimeUnit.SECONDS);
int num = Integer.parseInt(redisTemplate.opsForValue().get("num"));
if(num>0){
num = num -1;
redisTemplate.opsForValue().set("num",num+"");
System.out.println("剩余"+num);
}else{
System.out.println("库存不足");
}
}finally {
//释放锁
lock.unlock();
}
return redisTemplate.opsForValue().get("num");
}
使用jMeter测试