赞
踩
如下代码段(在单机环境下多线程访问会有库存扣减不一致问题,比如线程一扣完库存,同时线程二争抢到资源,此时线程二获取到的库存仍是没有扣减的库存)
- @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";
- }
- }

分布式环境下上面的代码就会失效,仍然会出现库存扣减不一致的问题。假如我们通过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 lockKey = "kockKey";
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。