Redisson分布式锁使用实践
场景
电商平台出现了负库存的问题,然后进一步查看代码,发现电商平台下单的时候,先查询库存,然后生成订单,再扣减库存,应该是存在多人同时购买,下单的代码查询库存的时候没有加锁,导致查询库存的时候多人获取的库存都是足够的,然后下单,扣减库存,导致负库存。
解决方案
经过多种方案考量,最终选择使用Redisson分布式锁方案。
代码
maven
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.6.5</version>
</dependency>
注: 这边引入redisson,需要注意依赖冲突,我这边引入后启动报错,后面排查是因为netty-all冲突,把jpush里的netty-all排除就行。
<dependency>
<groupId>cn.jpush.api</groupId>
<artifactId>jpush-client</artifactId>
<version>${jpush-client}</version>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</exclusion>
</exclusions>
</dependency>
config
@Configuration
public class RedissonConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private String port;
@Value("${spring.redis.password}")
private String password;
/**
* RedissonClient,单机模式
*
* @return
* @throws IOException
*/
@Bean
public RedissonClient redisson() throws IOException {
Config config = new Config();
if(StringUtils.isNotNull(password)){
config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);
}else{
config.useSingleServer().setAddress("redis://" + host + ":" + port);
}
return Redisson.create(config);
}
}
加锁
@Resource
private RedissonClient redissonClient;
RLock redissonLock = redissonClient.getLock(ConstantUtil.LOCK_PRODUCT_NAME);
try {
log.info("--获取锁--");
redissonLock.lock();
//todo 业务操作
........
} catch (Exception e) {
e.printStackTrace();
} finally {
log.info("--释放锁--");
redissonLock.unlock();
}