通过引入SpringRedisTemplate使用redis
1.单机模式下使用
如下代码段(在单机环境下多线程访问会有库存扣减不一致问题,比如线程一扣完库存,同时线程二争抢到资源,此时线程二获取到的库存仍是没有扣减的库存)
@RestController
public class IndexController{
@Autowired
private StringRedisTemplate stringRedisTempldate;
public String deductStock(){
int stock = Integer.parseInt(stringRedisTempldate.opsForValue().get("stock"));
if(stock > 0){
int realStock = stock - 1;
StringRedisTemplate.opsForValue().set("stock",realStock+"");
System.out.println("减扣成功,剩余库存:"+realStock );
}else{
System.out.println("减扣失败,余额不足");
}
return "end";
}
}
单机环境下解决办法:加入同步块或者锁,修改如下:
@RestController
public class IndexController{
@Autowired
private StringRedisTemplate stringRedisTempldate;
public String deductStock(){
synchronized(this){
int stock = Integer.parseInt(stringRedisTempldate.opsForValue().get("stock"));
if(stock > 0){
int realStock = stock - 1;
StringRedisTemplate.opsForValue().set("stock",realStock+"");
System.out.println("减扣成功,剩余库存:"+realStock );
}else{
System.out.println("减扣失败,余额不足");
}
}
return "end";
}
}
2.分布式环境下
分布式环境下上面的代码就会失效,仍然会出现库存扣减不一致的问题。假如我们通过nginx配置一个负载均衡,反响代理到自己模式的两台服务器上面,通过jmeter进行高并发请求压测,就会出现库存扣减不一致的问题,出现超卖的概率越大。synchronized可以控制解决单机的并发问题,不能跨jvm。
解决步骤思路如下:
1.使用用redis的setnx的命令(
sentnx命令格式:setnx key value
将key的值设为value,当且仅当key存在。
若给定的key已经存在,则setnx不做任何操作。
setnx是『set if not exists』(如果不存在,则set)的简写。
),可以简单的构建分布式锁。
@RestController
public class IndexController{
@Autowired
private StringRedisTemplate stringRedisTempldate;
public String deductStock(){
String lockKe