集群分布式场景高并发
1.negix配置代理和路由
高并发场景超卖问题
1.使用原生redis控制超卖时(若是商品,则可以将商品id作为锁对象),会遇到的问题
问题一:若直接使用:将获取锁的对象和设置的超时的时间分开,则不能控制原子性,如下所示
Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, "zhuge");
stringRedisTemplate.expire(lockKey, 10, TimeUnit.SECONDS);
问题二:若直接使用:将获取锁的对象和设置的超时的时间放在一个原子操作里执行时,在临界条件下,当程序执行到最后准备释放锁时候,锁的超时时间已到,则此时的锁成为已过期,则释放不了锁;而当下一个线程也来执行任务时,前一个任务将这个任务所拿的所给释放掉了(释放掉不属于自己的锁对象);则引入redisson分布式锁来解决当前的问题,redisson具有锁续命机制
@RestController
public class IndexController {
@Autowired
private Redisson redisson;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate redisTemplate;
@RequestMapping("/deduct_stock")
public String deductStock() {
String lockKey = "lock:product_101";
//Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, "zhuge");
//stringRedisTemplate.expire(lockKey, 10, TimeUnit.SECONDS);
String clientId = UUID.randomUUID().toString();
Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 30, TimeUnit.SECONDS); //jedis.setnx(k,v)
if (!result) {
return "error_code";
}
try {
int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock")); // jedis.get("stock")
if (stock > 0) {
int realStock = stock - 1;
stringRedisTemplate.opsForValue().set("stock", realStock + ""); // jedis.set(key,value)
System.out.println("扣减成功,剩余库存:" + realStock);
} else {
System.out.println("扣减失败,库存不足");
}
} finally {
if (clientId.equals(stringRedisTemplate.opsForValue().get(lockKey))) {
stringRedisTemplate.delete(lockKey);