java&redis实现缓存
缓存概述
- 缓存:从数据库(磁盘)中取数据到前端展示,速度很慢。为了提高速度可以使用缓存,即把数据预先查出来,放到一个更快读取的介质,比如内存,不用在从数据库很慢的查。
- 预加载缓存:定时更新缓存,为了不让第一次使用次此系统时数据加载很慢,可以在选一个用户访问较少的时间,定时加载缓存。
- 分布式锁:控制同一时间只用一台机器去执行定时任务,同一份代码不用在多个机器加载缓存。
- 缓存的实现
单机缓存和分布式缓存
- 单机本地缓存:在同一个进程内的内存空间中缓存数据,数据读写都是在同一个进程内完成;
- 分布式缓存:一个独立部署的进程并且一般都是与应用进程部署在不同的机器,故需要通过网络来完成分布式缓存的数据读写操作的数据传输。
Redis
Redis定义:
NoSQL(非关系型数据库)
key-value键值对存储系统(区别于mysql的键值对数据库)
☆Redis的数据结构(5种基本+高级)
- 基本
- 高级
Redis在java中的实现方式(Spring Data Redis , Lettuce,Jedis 和Redisson)
不同的场景使用不同的实现方式,
1. 如果用spring框架,并且没有过多的定制化要求,可以使用spring Data Redis,最方便
2. 如果使用的不是Spring,并且追求简单,没有过高的性能要求,可以用jedis + jedis Pool
3. 如果不是spring,并且追求高性能高定制化可以使用Lettuce,支持异步,连接池
4. 如果项目是分布式的,需要用到一些分布式的特征(比如分布式锁,分布式集合),可以使用redisson
-
使用Spring Data Redis 实现
- spring Data:通用的数据访问框架,定义了一组增删改查的接口,操做mysql,redis,jpa等数据库,通过应入不同的数据库依赖实现对不同数据库的操作。
- 引入Redis依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.6.4</version> </dependency>
- 配置Redis地址
# Redis 配置 redis: port: 6379 host: localhost database: 0
- Redis增删改查示例【如何使用Redis依赖中的增删改查接口,使用redis提供的,操作redis的类和对象】
//操作redis的类 @SpringBootTest public class RedisTest { //操作redis的对象 @Resource private RedisTemplate redisTemplate; @Test void test(){ ValueOperations valueOperations = redisTemplate.opsForValue(); //增 valueOperations.set("erhaString","fish"); valueOperations.set("erhaInt",1); valueOperations.set("erhaDouble",2.0); User user = new User(); user.setId(001); user.setUsername("testRedisString"); valueOperations.set("erhaUser",user); //查 Object erha = valueOperations.get("erhaString"); Assert.assertTrue("fish".equals((String) erha)); erha = valueOperations.get("erhaInt"); Assert.assertTrue(1== (int)erha); erha = valueOperations.get("erhaDouble"); Assert.assertTrue(2.0 == (Double) erha); erha = valueOperations.get("erhaUser"); System.out.println(valueOperations.get("erhaUser")); } }
注:为了解决序列化问题,自编代码实现序列化配置
@Configuration public class RedisTemplateConfig { @Bean public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory){ RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(connectionFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); return redisTemplate; } }
- 在项目首页推荐出提取缓存
- 设计缓存key,不同用户看到的数据不同。systemId:moduleId:func:options(不和别人冲突)
lack:user:recommed:userId - 用缓存实现主页推荐
/** * 首页推荐接口(分页查询) * @param request * @return */ @GetMapping("/recommend") public BaseResponse<Page<User>> recommendUsers(long pageSize,long pageNum,HttpServletRequest request) { //先获取当前登录对象 User loginUser = userService.getLoginUser(request); ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue(); //判断有无缓存,有直接读缓存 String redisKey = String.format("lack:user:recommed:userId:%s",loginUser.getId()); Page<User> userPage =(Page<User>)redisTemplate.opsForValue().get(redisKey); if(userPage != null){ return ResultUtils.success(userPage); } //无缓存查数据库 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); userPage = userService.page(new Page<>(pageNum,pageSize),queryWrapper); //写缓存 try { //redis的内存不能无限增加,一定要设置过期时间 valueOperations.set(redisKey,userPage,30000, TimeUnit.MILLISECONDS); } catch (Exception e) { log.error("redis set key error",e); } return ResultUtils.success(userPage); }
- 设计缓存key,不同用户看到的数据不同。systemId:moduleId:func:options(不和别人冲突)
- 优化=>缓存预热
-
缓存预热解决的问题:
-
缓存预热的优缺点:
-
缓存预热的意义:
-
缓存预热的注意点:
- 缓存空间不能太大,要预留给其他缓存空间
- 缓存数据的周期(每天一次)
-
实现缓存预热
- 手动模拟触发
- 定时触发(定时任务实现,每天刷新所有用户的推荐列表)
-
☆Spring Schedule(spring boot默认整合)
- 主类开启@EnableScheduling
- 给要定时执行的方法添加@Scheduled注解,编写方法
/** * 缓存预热任务 * */ @Slf4j @Component public class PreCacheJob { @Resource private UserService userService; @Resource private RedisTemplate<String, Object> redisTemplate; //重点用户 private List<Long> mainUserList = Arrays.asList(2l); //每天执行,预热推荐用户 @Scheduled(cron = "0 31 19 * * ? ") public void doCacheRecommendUser() { for (Long userId : mainUserList) { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); Page<User> userPage = userService.page(new Page<>(1, 20), queryWrapper); String redisKey = String.format("yupao:user:recommend:%s", userId); ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue(); //写缓存 try { valueOperations.set(redisKey, userPage, 30000, TimeUnit.MILLISECONDS); } catch (Exception e) { log.error("redis set key error", e); } } } }
-
XXL-job分布式任务调度平台(界面+sdk)
-
-
原文地址:https://blog.csdn.net/weixin_52154534/article/details/134629984
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_1156.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。