Redis分布式锁是什么?
- Redis分布式锁是一种控制分布式系统有序地去对公共资源进行操作,保证分布式环境下数据一致性的技术。
为什么要使用Redis分布式锁?
- redis除了可以用来做分布式锁,还可用来做缓存
- redis是纯内存操作【速度快】,单线程操作【避免频繁的上下文操作】,坑容易查到【用的人多】
- synchronized、ReenTrantLock等在分布式系统上没用了
使用Redis分布式模拟商品超卖
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ae745851a993650cd2841e1d44cd2347.png)
配置开发环境
- 首先创建一个springboot项目,然后pom.xml依赖目录如下
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 引入redis -->
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.3.0</version>
</dependency>
<!--引入log4j日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- 引入jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 引入redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- application.yml配置文件内容如下
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/aqs?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.jdbc.Driver
server:
port: 8080
- log4j.properties配置文件如下
#logger
log4j.rootLogger=debug,appender1
log4j.appender.appender1=org.apache.log4j.ConsoleAppender
log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout
实战分布式锁
import org.apache.log4j.Logger;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
public class TradeService {
Logger logger = Logger.getLogger(TradeService.class);
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private Redisson redisson;
public String decStockWithLock(){
String lockKey = "lockKey+id";
RLock redissonLock = redisson.getLock(lockKey);
try{
redissonLock.lock();
Integer stock;
List<Map<String,Object>> result = jdbcTemplate.queryForList("select stock from shop_order WHERE id=10");
if(result==null ||
(stock=(Integer)result.get(0).get("stock"))<=0){
logger.info("下单失败,已经没有库存了");
return "下单失败,已经没有库存了";
}
stock--;
jdbcTemplate.update("update shop_order set stock=? where id=10",stock);
logger.info("下单成功,当前剩余产品 ----> "+ stock);
return "下单成功,当前剩余产品 ----> "+ stock;
}finally {
redissonLock.unlock();
}
}
}
import com.redis.distrib_lock.service.TradeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TradeController {
@Autowired
protected TradeService tradeService;
@PostMapping("order")
public String order(){
return tradeService.decStockWithLock();
}
}
- Redis配置类RedissonConfig.java
import org.redisson.Redisson;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedissonConfig {
@Bean
public Redisson redisson(){
Config config = new Config();
config.useSingleServer().setAddress("redis://localhost:6379").setDatabase(0);
return (Redisson) Redisson.create(config);
}
}
JMeter工具模拟多用户测试
- 结果图
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/850ba797b1f3675a6753bd1c4564ec99.png)
总结
- redis分布式锁在高并发条件能保证分布式环境下的数据一致性。
项目结构图
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/13c9a898f19299a0ab969e0cee2df093.png)