目录
- 引出
- Redis的高并发问题
- redis的高并发问题
- Redisson中间件
- 引入Redisson
- Redisson配置
- Redisson应用
- 报错:java.lang.NoClassDefFoundErro
- Redis的项目应用(二):抢购图书
- 1.0版本,Java代码:数据不安全
- 测试方法
- 1.用client方法测试
- 2.用JMeter进行高并发测试
- 问题:redis出现了数据不安全的情况
- 2.0版本,改进:加锁分布式锁Redission,保证原子性
- Redisson中间件
- 1.导包+配置类
- 2.进行加锁
- 3.高并发测试
- 总结
引出
1.Redis是线程安全的,但是高并发时出现数据不安全的问题;
2.解决办法,加锁,Redission分布式锁的使用;
3.Redis项目应用,图书的抢购,不加锁,数据不安全;
4.加了Redission中间件,保证原子性,数据安全;
Redis的高并发问题
redis的高并发问题
Redisson中间件
Redisson是一个基于Redis的Java驻留内存数据网格(In-Memory Data Grid)。它封装了Redis客户端API,并提供了一个分布式锁、分布式集合、分布式对象、分布式Map等常用的数据结构和服务。
引入Redisson
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.21.3</version>
</dependency>
Redisson配置
@Configuration
public class RedissionConfig {
@Value("${spring.redis.host}")
private String host;
// @Bean
public RedissonClient redissonClient(){
Config config = new Config();
config.setTransportMode(TransportMode.EPOLL);
config.useSingleServer().setAddress("redis://192.168.198.130:6379");
return Redisson.create(config);
}
}
Redisson应用
@Autowired
private RedissonClient redissonClient;
// 1.获取锁对象
RLock myLock = redissonClient.getLock("myLock");
try{
// 2.准备锁代码,并进行加锁
myLock.lock();
}finally{
// 3.解除锁
myLock.unlock(); // 把锁释放
}
报错:java.lang.NoClassDefFoundErro
java.lang.NoClassDefFoundError: org/springframework/data/redis/connection/zset/Tuple
org.springframework.data.redis.connection.zset.Tuple
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.9.1</version>
</dependency>
Redis的项目应用(二):抢购图书
1.0版本,Java代码:数据不安全
controller层的代码
package com.tianju.redisDemo.controller;
import com.tianju.redisDemo.dto.HttpResp;
import com.tianju.redisDemo.dto.ResultCode;
import com.tianju.redisDemo.service.IBookService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
@Controller
@RequestMapping("/api/book")
@Slf4j
public class BookController {
@Autowired
private IBookService bookService;
@GetMapping("/rush")
public HttpResp rushBook(String key){
Integer rushBuy = bookService.rushBuy(key);
// 如果为null,说明图书还没进入抢购的队列
if (rushBuy==null){
return HttpResp.results(ResultCode.BOOK_RUSH_ERROR,new Date(),"图书还不能秒杀抢购");
}
log.debug("》》》》图书剩余库存:"+rushBuy);
return HttpResp.results(ResultCode.BOOK_RUSH_SUCCESS,new Date(),null);
}
}
service层的代码
package com.tianju.redisDemo.service.impl;
import com.tianju.redisDemo.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class IBookServiceImpl implements IBookService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public Integer rushBuy(String key) {
String numStr = stringRedisTemplate.opsForValue().get(key);
if (numStr==null){
return null; // 商品剩余数量还没有进入缓存,不能抢购
}
int num = Integer.parseInt(numStr);
// 如果库存数量大于1;执行-1,去库存操作
if (num>0){
num--; // 去库存
// 更新当前库存数量
stringRedisTemplate.opsForValue().set(key, String.valueOf(num));
}
return num;
}
}
application.yml配置文件
server:
port: 9099
spring:
# redis的相关配置
redis:
host: localhost
port: 6379
database: 0
# 日志需要配置一下
logging:
level:
com.tianju.redisDemo: debug
测试方法
1.用client方法测试
2.用JMeter进行高并发测试
问题:redis出现了数据不安全的情况
2.0版本,改进:加锁分布式锁Redission,保证原子性
Redisson中间件
Redisson是一个基于Redis的Java驻留内存数据网格(In-Memory Data Grid)。它封装了Redis客户端API,并提供了一个分布式锁、分布式集合、分布式对象、分布式Map等常用的数据结构和服务。
要点:
- 获取锁对象;
- 准备锁代码;
- 进行加锁;
- 解除锁,把锁释放;
@Autowired private RedissonClient redissonClient; @Override public Integer rushBuy(String key) { // 1.获取锁对象 RLock myLock = redissonClient.getLock("myLock"); try { // 2.准备锁代码,并进行加锁 myLock.lock(); // 进行图书的抢购,去库存 -1 } return num; } finally { // 3.解除锁 myLock.unlock(); // 把锁释放
1.导包+配置类
<!-- 分布式锁-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.9.1</version>
</dependency>
RedissonConfig.java
package com.tianju.springboot.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;
@Configuration
public class RedissonConfig {
@Value("${spring.redis.host}")
private String host;
@Bean // 别人写的对象,放到spring中
public RedissonClient redissonClient(){
Config config = new Config();
// "redis://192.168.198.130:6379"
config.useSingleServer().setAddress("redis://"+host+":6379");
return Redisson.create(config);
}
}
2.进行加锁
package com.tianju.redisDemo.service.impl;
import com.tianju.redisDemo.service.IBookService;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class IBookServiceImpl implements IBookService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedissonClient redissonClient;
@Override
public Integer rushBuy(String key) {
// 1.获取锁对象
RLock myLock = redissonClient.getLock("myLock");
try {
// 2.准备锁代码,并进行加锁
myLock.lock();
// 进行图书的抢购,去库存 -1
String numStr = stringRedisTemplate.opsForValue().get(key);
if (numStr==null){
return null; // 商品剩余数量还没有进入缓存,不能抢购
}
int num = Integer.parseInt(numStr);
// 如果库存数量大于1;执行-1,去库存操作
if (num>0){
num--; // 去库存
// 更新当前库存数量
stringRedisTemplate.opsForValue().set(key, String.valueOf(num));
}
return num;
} finally {
// 3.解除锁
myLock.unlock(); // 把锁释放
}
}
}
3.高并发测试
总结
1.Redis是线程安全的,但是高并发时出现数据不安全的问题;
2.解决办法,加锁,Redission分布式锁的使用;
3.Redis项目应用,图书的抢购,不加锁,数据不安全;
4.加了Redission中间件,保证原子性,数据安全;