问:什么是超卖问题?
当宝贝库存接近0时,如果多个买家同时付款购买此宝贝,将会出现超卖现象。超卖现象本质上就是买到了比仓库中数量更多的宝贝。
如何解决超卖问题?
我们可以使用分布式锁来解决这个问题,使用redis构建分布式锁流程如下:
使用Redission分布式锁解决超卖问题
在pom.xml中添加坐标
<!--rediss-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--Redission-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.6.5</version>
</dependency>
application.yml配置文件
spring:
redis:
port: 6379 # Redis服务器连接端口
host: 127.0.0.1 # Redis服务器地址
database: 0 # Redis数据库索引(默认为0)
password: # Redis服务器连接密码(默认为空)
timeout: 5000ms # 连接超时时间(毫秒)
jedis:
pool:
max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 8 # 连接池中的最大空闲连接
min-idle: 0 # 连接池中的最小空闲连接
server:
port: 8070
将RedissonClient添加到IOC容器
package demo;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@SpringBootApplication
@Configuration
public class Demo {
public static void main(String[] args) {
SpringApplication.run(Demo.class);
}
@Bean
public RedissonClient redisson(){
// 1. Create config object
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
// config.useClusterServers()
// // use "rediss://" for SSL connection
// .addNodeAddress("redis://127.0.0.1:7181");
return Redisson.create(config);
}
}
初始化库存和销售
package demo.controller;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
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;
@RestController
public class TestController {
@Autowired(required = false)
private StringRedisTemplate stringRedisTemplate;
@Autowired(required = false)
private RedissonClient redissonClient;
//设置基本库存
@RequestMapping("/t1")
public String createStock() {
stringRedisTemplate.boundValueOps("stock").set("100");
return "t1";
}
//销售商品(削减库存量)
@RequestMapping("/t2")
public void deductStock4() {
RLock lock = redissonClient.getLock("redisson:stockLock");
try {
//加锁
lock.lock();
String stock = stringRedisTemplate.opsForValue().get("stock");
int stockNum = Integer.parseInt(stock);
if (stockNum > 0) {
//设置库存减1
int realStock = stockNum - 1;
stringRedisTemplate.opsForValue().set("stock", realStock + "");
System.out.println("设置库存" + realStock);
} else {
System.out.println("库存不足");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
文章评论