SpringBoot使用Redisson实现分布式锁
目录
一、前言
1.Redisson
Redisson是Redis官方推荐的Java版的Redis客户端(Jedis、letture也是官方推荐的java版本redis客户端程序)。它提供的功能非常多,也非常强大,特别是它默认提供的分布式锁支持功能。
2.准备工作
数据库信息:
t_product商品信息:
二、Spring Boot 集成Redisson
1.添加依赖
redisson相关依赖:
<!--spring data redis启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>1.4.2.RELEASE</version>
</dependency>
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.19.3</version>
</dependency>
其他依赖如下:
<!--tk.mybatis依赖-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>1.2.4</version>
</dependency>
<!--web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.16</version>
</dependency>
2.配置redis信息
# 服务端口
server:
port: 8083
## Redisson 分布式锁配置
redisson:
address: redis://localhost:6379
password:
3.编写Redisson配置类
package com.example.distributedlockdemo.config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* redisson配置类
* @author qzz
* @date 2023/3/10
*/
@Configuration
public class RedissonAutoConfiguration {
/**
* redis 链接地址
*/
@Value("${redisson.address}")
private String addressUrl;
/**
* 密码
*/
@Value("${redisson.password}")
private String password;
/**
* 单机模式配置
* @return
*/
@Bean
public RedissonClient getRedisson(){
Config config = new Config();
//单机模式
config.useSingleServer()
.setAddress(addressUrl).setPassword(password)
.setRetryInterval(5000)
.setTimeout(10000)
.setConnectTimeout(10000);
return Redisson.create(config);
}
/**
* 主从模式配置
* @return
*/
// @Bean
// public RedissonClient getRedisson(){
// Config config = new Config();
// //主从模式
// config.useMasterSlaveServers()
// .setMasterAddress("redis://***(主服务器IP):6379").setPassword(password)
// .addSlaveAddress("redis://***(从服务器IP):6379")
// .setRetryInterval(5000)
// .setTimeout(10000)
// //连接超时,单位:毫秒 默认值:3000
// .setConnectTimeout(10000);
// return Redisson.create(config);
// }
/**
* 哨兵模式配置
* @return
*/
// @Bean
// public RedissonClient getRedisson(){
// Config config = new Config();
// //哨兵模式
// config.useSentinelServers()
// .setMasterName("myMaster").setPassword(password)
// .addSentinelAddress("***(哨兵IP):26379","***(哨兵IP):26379");
// return Redisson.create(config);
// }
}
4.编写下单接口(秒杀接口)
package com.example.distributedlockdemo.controller;
import com.example.distributedlockdemo.dao.OrderMapper;
import com.example.distributedlockdemo.dao.ProductMapper;
import com.example.distributedlockdemo.entity.Order;
import com.example.distributedlockdemo.entity.Product;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* @author qzz
* @date 2023/3/10
*/
@RestController
public class TestController {
@Autowired
private RedissonClient redissonClient;
@Autowired
private ProductMapper productMapper;
@Autowired
private OrderMapper orderMapper;
/**
* 下单,减库存
* @param order
* @return
*/
@PostMapping("/order/add")
public String createOrderTest(@RequestBody Order order){
//1.判断库存
if(!decProductStore(order.getProductId(),order.getProductNum())){
return "库存不足!";
}
//2.商品下单
//订单状态 0:未支付 1:已支付 2:已发货 3:已取消
order.setStatus(0);
order.setCreateTime(new Date());
Integer result = orderMapper.insert(order);
if(result>0){
//3.减商品库存
productMapper.updateProductStock(order.getProductId(),order.getProductNum());
}
return "下单成功";
}
/**
* 判断库存
* @param productId 商品id
* @param productNum 购买数量
* @return
*/
public boolean decProductStore(Long productId, Integer productNum){
String key="decrease_stock_lock:" + productId;
RLock lock = redissonClient.getLock(key);
//1.加锁
lock.lock();
try {
//2.执行业务
//根据商品id和购买数量判断商品剩余库存
Product product = productMapper.selectByPrimaryKey(productId);
//如果库存为空或库存不足
if (product.getStock() == 0 || product.getStock()-productNum <0) {
return false;
}
}catch (Exception e){
System.out.println(e.getMessage());
}finally {
//解锁
lock.unlock();
}
return true;
}
}
5.测试
执行一次:购买数量100
商品库存:
执行一次:购买数量1
数据库中的商品已经全部被秒杀完 并未出现超库存的情况。