1、配置Redis连接:添加pox.xml依赖:
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 通用池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2,application.yml
server:
port: 8989
spring:
datasource:
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
#连接本地数据库
url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
redis:
host: 127.0.0.1
timeout: 1000
jedis:
pool:
min-idle: 5
max-idle: 10
max-wait: -1
mybatis-plus:
# mapper.xml 文件扫描
mapper-locations: classpath*:/mapper/*.xml
configuration:
map-underscore-to-camel-case: true
# 日志配置
logging:
level:
com.xxx.xxx: debug
org.springframework: warn
对Redis生成的key,value进行数据格式转换一下:工具类 RedisConfig
/**
* 设定redis返回的展示格式
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
//指定key,value的序列化方式
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
}
3,生成MVC基础结构:《简单利用mybatis-plus代码生成》
4,为什么需要MySQL数据库表?
这就需要说说Redis的作用:
在实际开发中,企业为了减小关系型数据库(MySQL为例)的访问压力,防止因为访问量过大(高并发情况下)导致数据库罢机情况,我们就引入Redis(非关系型数据库)通过键key--对value的方式来进行数据缓存一份在Redis数据,这样当用户第一访问MySQL数据库时,通过把访问的数据缓存在Redis中,当下一次访问同样的数据时就会直接访问Redis数据库缓存的数据,从而减小了MySQL数据库的压力,也大大提高了查询数据,同样也提高了安全性
所以现在的查询的步骤是什么呢:
1.先查询Redis数据库看看访问的数据是否在Redis数据库有缓存,有缓存直接返回缓存的数据,没有缓存的情况,查询MySQL数据库,把查询的数据写入到Redis中缓存备份数据;
2.这里面就涉及到查询数据的判断:先判断Redis缓存是否有数据,没有就通过MySQL查询出来的数据写入
5,数据库表:
CREATE TABLE `redis_cs` (
`id` int NOT NULL AUTO_INCREMENT,
`user_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb3;
6,RedisCsController层的编写
通过前端传递id查询数据:
@RestController
@RequestMapping("/redis-cs")
public class RedisCsController {
//redis基类
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private RedisCsService redisCsService;
@GetMapping("getById/{id}")
public Object getById(@PathVariable("id")Integer id){
//创建一个线程来模拟高并发情况
ExecutorService es = Executors.newFixedThreadPool(200);
for (int i = 0; i <300; i++) {
es.submit(new Runnable() {
@Override
public void run() {
redisCsService.findById(id);
}
});
}
Object obj = redisCsService.findById(id);
return R.ok().data("obj",obj);
}
}
7,RedisCsService方法:
public interface RedisCsService extends IService<RedisCs> {
Object findById(Integer id);
}
8.RedisCsServiceImpl实现类:
@Service
@Slf4j
public class RedisCsServiceImpl extends ServiceImpl<RedisCsMapper, RedisCs> implements RedisCsService {
@Autowired
private RedisCsMapper redisCsMapper;
@Autowired
private RedisUtils redisUtils;
@Autowired
private RedisTemplate redisTemplate;
@Override
public Object findById(Integer id) {
//创建key的展示形式
String key = "user:" + id;
//先查询Redis缓存
Object userObj = redisTemplate.opsForValue().get(key);
if (userObj == null) {
//多线程同步数据
synchronized (this.getClass()) {
//再查一次缓存,防止查询数据有延迟
userObj = redisTemplate.opsForValue().get(key);
if (userObj==null){
log.debug("====查询数据库====");
//缓存没有数据,查询MySQL数据库里面的数据
RedisCs redisCs = baseMapper.selectById(id);
//帮MySQL查询出来的数据返回的同时,把数据写入到Redis进行缓存
redisTemplate.opsForValue().set(key,redisCs);
return redisCs;
}else {
log.debug("====查询缓存(同步代码块)====");
return userObj;
}
}
}else {
log.debug("====查询缓存====");
}
return userObj;
}
}
现在Redis数据是没有缓存数据的情况:
通过Postman测试一下看看后端打印的日志:
postman成功返回了数据,看看后端的情况:
首先分析一下:因为现在我们Redis没有数据缓存的情况下访,那么会先查询数据,因为我们并发了300次,展示的结果应该是只能查询一次MySQL数据库,接下来的299次都应该查询缓存;
看看返回结果吧:
这就是最常见高并发情况下访问数据的实现:接下来看看有缓存数据的情况下吧:
现在Redis已经有了缓存:我们在访问ID=1 看看后端是否查询了缓存:要是查询了数据库那我们这个程序就是个错误的程序: