赞
踩
数据查询慢怎么办?
用缓存:提前把数据取出来保存好(通常保存到读写更快的介质,比如内存),就可以更快地读写。
缓存
实现方式
对比
:::
Redis
NoSQL 数据库
key - value 存储系统(区别于 MySQL,他存储的是键值对)
Redis 数据结构
String 字符串类型: name: “yupi”
List 列表:names: [“yupi”, “dogyupi”, “yupi”]
Set 集合:names: [“yupi”, “dogyupi”](值不能重复)
Hash 哈希:nameAge: { “yupi”: 1, “dogyupi”: 2 }
Zset 集合:names: { yupi - 9, dogyupi - 12 }(适合做排行榜)
bloomfilter(布隆过滤器,主要从大量的数据中快速过滤值,比如邮件黑名单拦截)
geo(计算地理位置)
hyperloglog(pv / uv)
pub / sub(发布订阅,类似消息队列)
BitMap (1001010101010101010101010101)
Spring Data Redis(推荐)
Spring Data:通用的数据访问框架,定义了一组 增删改查 的接口
mysql、redis、jpa spring-data-redis
Just a moment…
<!-- redis -->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.6.4</version>
</dependency>
配置 Redis 地址
spring:
# redis 配置
redis:
port: 6379
host: localhost
database: 0
Jedis
独立于 Spring 操作 Redis 的 Java 客户端 要配合 Jedis Pool 使用
Lettuce
高阶 的操作 Redis 的 Java 客户端 异步、连接池
Redisson
分布式操作 Redis 的 Java 客户端,让你像在使用本地的集合一样操作 Redis(分布式 Redis 数据网格)
JetCache
对比
package com.ivy.heartchain.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; @Configuration public class RedisTemplateConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(connectionFactory); redisTemplate.setKeySerializer(RedisSerializer.string()); return redisTemplate; } }
引入一个库时,先写测试类
设计缓存 key
不同用户看到的数据不同
systemId:moduleId:func:options(不要和别人冲突)
yupao:user:recommed:userId
redis 内存不能无限增加,一定要设置过期时间!!!
修改主页推荐接口
/** * 推荐页面 * @param request * @return */ @GetMapping("/recommend") public BaseResponse<Page<User>> recommendUsers(long pageSize,long pageNum, HttpServletRequest request){ User loginUser = userService.getLoginUser(request); String redisKey = String.format("partner:user:recommend:%s", loginUser.getId()); ValueOperations<String,Object> valueOperations = redisTemplate.opsForValue(); //如果有缓存,直接读缓存 Page<User> userPage= (Page<User>)valueOperations.get(redisKey); if (userPage!=null){ return ResultUtils.success(userPage); } //无缓存,查数据库 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); userPage = userService.page(new Page<>(pageNum, pageSize), queryWrapper); //写缓存 try { valueOperations.set(redisKey,userPage,30000, TimeUnit.MILLISECONDS); }catch (Exception e){ log.error("redis set key error",e); } return ResultUtils.success(userPage); }
:::info
问题:第一个用户访问还是很慢(加入第一个老板),也能一定程度上保护数据库
缓存预热的优点:
缺点:
用定时任务,每天刷新所有用户的推荐列表
注意点:
第一种方式:
不要去背 cron 表达式!!!!!
新建文件夹新建文件。之前就写个的,就不具体写出来了。
:::
package com.yupi.usercenter.job; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yupi.usercenter.common.ResultUtils; import com.yupi.usercenter.model.domain.User; import com.yupi.usercenter.service.UserService; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; /** * @Description: 数据预热 */ @Component @Slf4j public class PreCacheJob { @Resource private UserService userService; @Resource private RedisTemplate<String, Object> redisTemplate; // 重点用户 private List<Long> mainUserList = Arrays.asList(1L); // 每天执行,预热推荐用户 @Scheduled(cron = "0 12 1 * * *") //自己设置时间测试 public void doCacheRecommendUser() { //查数据库 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); Page<User> userPage = userService.page(new Page<>(1,20),queryWrapper); String redisKey = String.format("sanshui:user:recommend:%s",mainUserList); ValueOperations valueOperations = redisTemplate.opsForValue(); //写缓存,30s过期 try { valueOperations.set(redisKey,userPage,30000, TimeUnit.MILLISECONDS); } catch (Exception e){ log.error("redis set key error",e); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。